(Адский босс)

Переведено с английского

(Helluva Boss)

205

3,9 тыс.

Группа I.M.P, с возможностью TETO!?

⯆⚉⯆
~Teteteto~

"Не называй меня 'милашкой', я гангста!"
(Рекомендуется использовать с каким-нибудь прокси. Не знаю, сработает ли JLMM, и мне лень проверять это самому)

Сценарий первый:
Луна, Милли и Мокси убегают от копов.

Сценарий второй:
Ты работаешь в I.M.P уже месяц. Сегодня у них у всех собрание.

Сценарий третий:
Ты заболел. Луна заботится о тебе. (задумано как милота)

Сценарий четвёртый:
Ты и Милли на задании на Земле.

Сценарий пятый:
Ой-ой...

Сценарий шестой:
Случилась большая ссора. Иди утешь Луну.

Сценарий седьмой:
Ты и Луна дурачитесь.

Сценарий восьмой:
Луна, Милли, Мокси и Блитцо хотят удочерить нового адского пса. Это ты, близнец. (POV адского пса)

Сценарий девятый:
Введи свой собственный сценарий.

Теги:
Компьютеры не имеют смысла. Брось немного металла в коробку и — бам. Что вообще здесь происходит? Внутри твоего ПК находится центральный процессор, или CPU. По сути, это просто кусок кремния с миллиардами микроскопических переключателей, называемых транзисторами. В зависимости от потока электричества они могут быть включены или выключены, вроде лампочки, что даёт нам два состояния: единицу и ноль. Значение одного такого переключателя называется битом. Один бит сам по себе мало что делает, но собери их вместе и... Группа из 8 битов называется байтом и может иметь 256 различных комбинаций нулей и единиц. Поздравляю! Теперь мы можем хранить информацию, считая в системе, называемой двоичной. Каждый бит представляет степень двойки: 1 означает, что степень включена, а 0 — что нет, так что это число имеет 1 умножить на 64, 1 умножить на 4 и 1 умножить на 1, что в сумме даёт 69. Это здорово, но для людей шестнадцатеричная система ещё лучше. Её часто обозначают этим 0x, и это просто более читаемый формат, чем двоичный. Четыре двоичных бита могут принимать любое значение от 0 до 15. Шестнадцатеричная система использует от 0 до 9 и от A до F для представления этих значений, так что группа из четырёх битов может быть заменена одной шестнадцатеричной цифрой. Хорошо, теперь, когда мы умеем хранить числа, нам просто нужно, чтобы компьютеры на самом деле, ну знаете, что-то с ними делали. Используя транзисторы, можно создавать логические элементы — электронные схемы, инкапсулирующие логические высказывания. Это можно представить как лампочку с двумя выключателями, где свет включается только при определённых условиях, например только если A и B включены. Хитро сочетая логические элементы, можно строить схемы, выполняющие вычисления согласно булевой алгебре — системе, формализующей математические операции в двоичном виде. Но хотя компьютеры понимают нули и единицы, для людей это не так уж полезно. Поэтому, используя кодировку символов вроде ASCII, мы можем присвоить каждому символу двоичное число. Когда ты нажимаешь любую клавишу на клавиатуре, она преобразуется в этот двоичный код, и как только компьютер видит его, он говорит: ага, это заглавная A, и шлёпает её на экран. То, как эти устройства соединяются вместе, обрабатывается ядром операционной системы, вроде Windows, Linux или Mac, которое находится между аппаратным обеспечением компьютера и приложениями и управляет тем, как они все работают вместе, например, с помощью драйверов устройств. Устройства ввода позволяют тебе давать компьютеру инструкции нажатием кнопки, но на самом низком уровне компьютеры понимают инструкции только в машинном коде — двоичном коде, сообщающем CPU, что делать и какие данные использовать. Когда дело доходит до выполнения этих инструкций, CPU вроде как гений, только с памятью безумной золотой рыбки. Он может обрабатывать любые инструкции, но не может хранить никаких данных, так что по-настоящему полезен только с оперативной памятью, или RAM. Это можно представить как сетку, где каждая ячейка может хранить один байт информации, который может быть данными или инструкциями, и имеет адрес, чтобы CPU мог получить к нему доступ за четыре шага. Выборка из памяти, декодирование инструкций и данных, и наконец, выполнение и сохранение результата. Это один машинный цикл. Поскольку программа — это по сути просто список инструкций и памяти, чтобы запустить её, CPU выполняет их одну за другой в машинных циклах, пока она не завершится. Ах да, я упоминал, что это происходит, ну, очень быстро? Современные CPU могут выполнять миллиарды циклов каждую секунду, которые координируются и синхронизируются генератором тактовой частоты. Скорость этого такта измеряется в гигагерцах, и люди часто разгоняют свои CPU для повышения производительности, что здорово, но может просто подпалить твой ПК. Что ещё безумнее, так это то, что у CPU есть несколько ядер, которые могут выполнять разные инструкции параллельно, то есть одновременно. Каждое ядро также может быть разделено на несколько потоков, что позволяет каждому отдельному ядру обрабатывать несколько инструкций одновременно, то есть очень быстро переключаться между ними. Ладно, это круто, но неважно, насколько мощный компьютер, если у тебя вообще нет способа дать ему инструкции. Набирать машинный код вручную, вероятно, сведёт тебя с ума, но, к счастью, тебе не придётся. Ядро обёрнуто в оболочку — просто программу, которая открывает ядро пользователю, позволяя давать простые инструкции в интерфейсе командной строки с текстовым вводом. Но лучший способ заставить компьютер сделать что-то полезное — это язык программирования, который использует абстракцию, так что вместо этого ты можешь писать код, который выглядит вот так, а затем он преобразуется в машинный код за тебя. Некоторые языки, вроде Python, используют интерпретатор, который напрямую пытается выполнить исходный код строка за строкой. Другие языки, вроде C или Go, используют компилятор, который преобразует всю программу в машинный код, прежде чем поместить её в файл, который CPU может выполнить. Теперь, у каждого языка программирования свой синтаксис, но есть несколько базовых инструментов, которые есть почти у всех. Самый базовый способ использовать данные — это переменные, которые присваивают значение имени, которое затем можно повторно использовать и изменять. В зависимости от значения переменные могут иметь разные типы данных. Для текста это отдельные символы и строки из нескольких символов. Для чисел есть целые числа, которые также могут быть знаковыми, если они отрицательные, и числа с плавающей точкой для десятичных значений. Они называются с плавающей точкой, потому что десятичная точка может «плавать», обменивая точность на диапазон. Это возможно, потому что они используют научную нотацию. Это какое-то число, умноженное на степень, указывающую, куда поставить десятичную точку, — именно так они и выглядят под капотом. Само число хранится с помощью двоичных дробей. Некоторые дроби, например одна треть, можно только приблизить в двоичном виде с помощью бесконечной суммы. Но поскольку память не бесконечна, её приходится где-то обрезать, что приводит к ошибкам округления, иногда вызывая довольно странные вычисления. Если этого недостаточно, long и double используют вдвое больше памяти, чтобы удвоить диапазон int и float. Некоторые языки, вроде Python, автоматически определяют, какого типа переменная, но в языке вроде C тебе нужно явно объявить тип переменной. Значение переменной хранится по какому-то адресу в памяти. Указатели — это переменные, значение которых является адресом памяти другой переменной, что обозначается этим амперсандом. Так что на самом деле указатель — это просто кусок памяти, указывающий на другой кусок памяти. Поскольку адрес памяти — это просто число, ты можешь прибавлять и вычитать из него, чтобы перемещаться по отдельным байтам памяти. Это называется арифметикой указателей. В некоторых низкоуровневых языках, вроде C, тебе нужно вручную выделять и освобождать память, когда она больше не используется. Всё это происходит в куче — части памяти, которая может динамически расти и сжиматься по требованию программы, что даёт больше контроля, но делает невероятно лёгким полное разрушение твоего кода. Ты можешь обратиться к памяти, которой не должно существовать, что известно как ошибка сегментации. Но также, если есть кусок памяти, который больше не используется, а ты забыл его освободить или у тебя больше нет способа к нему обратиться, эта память становится непригодной. Это называется утечкой памяти и может заставить программу замедлиться и в конце концов упасть. Чтобы избежать этого беспорядка, высокоуровневые языки, вроде Python, имеют встроенные сборщики мусора, которые управляют памятью за тебя. Разные типы данных занимают разное количество памяти. Целые числа чаще всего занимают 4 байта памяти, один символ — чаще всего 1 байт памяти, а строка — это просто несколько байтов символов с нулевым символом, сигнализирующим о конце строки. Хранение нескольких элементов в непрерывном куске памяти, как здесь, — это идея массива. В более общем смысле это список элементов одного типа данных, каждый из которых имеет числовой индекс, чаще всего начинающийся с 0. Поскольку элементы находятся рядом друг с другом в памяти, зная адрес первого элемента, ты можешь быстро обратиться к любому элементу массива с помощью арифметики указателей. Массивы — это то, что известно как структура данных, то есть просто способ организации данных, чтобы с ними было легче работать. Извлечение значений из массива происходит молниеносно, но размер массива часто фиксируется при его создании, поэтому, когда он полон, ты не можешь ничего добавить, а если ты используешь его не весь, это просто потраченная впустую память, поэтому более гибкий вариант — связный список. Он использует узлы, содержащие значение и указатель на следующий узел, что позволяет им быть разбросанными по памяти. Кроме того, он может динамически расти и сжиматься, так как ты можешь добавлять и удалять любой узел, и ты можешь переупорядочить его, просто переставляя указатели. Это здорово, но они могут быть непрактичными, так как у тебя нет способа добраться до последнего узла, кроме как пройти через каждый предыдущий. Но всё же и массивы, и связные списки полезны, так как позволяют создавать очереди и стеки. Стек следует принципу «последним пришёл — первым вышел», как когда берёшь блин из стопки. На практике просто представь указатель, который всегда указывает на элемент, добавленный в структуру последним, тогда ты можешь сделать pop, то есть удалить последний элемент, что сдвигает указатель назад. Очередь следует принципу «первым пришёл — первым вышел» и использует два указателя: один для первого добавленного элемента и один для последнего. Любой новый элемент добавляется после последнего указателя, который затем обновляется, а извлечение из очереди начинается с первого указателя. Ещё одна полезная структура данных — хеш-таблица, которая является просто набором пар ключ-значение. Она работает вроде массива, но использует хеш-функцию, чтобы взять ключ и назначить его индексу, где затем хранится его значение. Но иногда два разных ключа могут отображаться на один и тот же индекс, что называется коллизией. Есть разные способы справиться с этим, но один из них — создать связный список в этой позиции массива, что делает поиск этого значения немного медленнее, но всё же хеш-таблицы невероятно полезны, потому что ты можешь определить ключи, указывающие на каждое значение, и, поскольку они основаны на массивах, извлечение происходит молниеносно. Для многих задач может быть очень полезно представить отношения между разными точками данных как структуру данных. Если взять узлы связного списка, но позволить любому узлу указывать на любой другой узел, получится граф, где узлы соединены рёбрами, которые могут быть направленными, ненаправленными и даже нести вес, который может означать любую метрику, например расстояние или стоимость. Графы полезны для анализа групп внутри сетей или поиска кратчайшего пути между двумя точками, например в Google Maps. Есть два основных способа поиска по графу. Поиск в ширину начинается с одного узла и продвигается слой за слоем, пока впервые не найдёт целевой узел. Поиск в глубину исследует каждый отдельный путь полностью, пока не достигнет тупика, затем возвращается к последнему узлу с другим путём и продолжает оттуда таким же образом, пока не найдёт целевой узел. Граф, в котором любые два узла соединены ровно одним путём, называется деревом и представляет иерархию, например файловую систему на твоём компьютере. Дерево начинается с корня и ветвится на поддеревья, которые заканчиваются листовыми узлами. Родительские узлы могут иметь любое количество дочерних узлов, но чаще всего наиболее полезны бинарные деревья. Например, бинарное дерево, где все значения слева от любого узла меньше, а все значения справа больше, называется двоичным деревом поиска, что делает поиск конкретных значений супербыстрым. Если ты хочешь найти целевое значение, просто начни с корня. Если цель меньше этого узла, иди влево, если больше — вправо, и повторяй это, пока не найдёшь цель. То, что мы только что использовали, — это очень простой алгоритм, то есть просто набор инструкций, который решает задачу шаг за шагом. Самый простой способ написать алгоритм — в форме функции. Она принимает входные данные, что-то с ними делает и возвращает результат. Так же как и с переменными, ты можешь затем вызвать функцию по её имени и передать разные аргументы. При вызове функции вызов функции помещается в стек вызовов — кратковременную память, используемую для выполнения кода, и, как следует из названия, он основан на структуре данных стека, что означает «последним пришёл — первым вышел». Чтобы реализовать алгоритмы, тебе часто приходится сравнивать два значения, что можно делать с помощью операторов, вроде больше или равно, и логических выражений, таких как and, or и not. Такие выражения просты, они могут быть истинными или ложными, что является возможными значениями логического типа данных и позволяет писать условные операторы. Если какое-то условие истинно, сделай это, иначе сделай то. Логические значения также можно использовать для циклов по определённым частям кода. Один способ — с помощью цикла while. Пока это условие истинно, этот код будет выполняться. Другой способ — с помощью цикла for, который может перебирать каждый элемент внутри структуры данных, вроде массива, но также может выполняться заданное число итераций, установив начальное значение, увеличивая его после каждой итерации и задавая верхнюю границу условием. Функции также могут вызывать сами себя, что известно как рекурсия. Это полезно, когда задачу можно разбить на меньшие идентичные задачи, например вычислить 5 факториал, который равен просто 5 умножить на 4 факториал, который равен просто 4 умножить на... Но по умолчанию рекурсивная функция будет просто вызывать себя бесконечно. Это означает, что она продолжает помещать всё больше вызовов функций в стек вызовов, пока память стека не будет превышена — переполнение стека. Это не оптимально. Чтобы остановить это, нужно добавить базовое условие в рекурсивную функцию, которое определяет, когда остановиться. Только тогда вызовы функций будут выполняться, не ломая твой ПК. Рекурсия — это круто, но она может быть довольно дорогой по времени и памяти. Поэтому, чтобы минимизировать объём необходимых вычислений, прошлые результаты можно сохранять в кэше, чтобы, если они снова встретятся, компьютеру не приходилось пересчитывать их с нуля. Это называется мемоизацией. Говоря о производительности, чтобы судить, насколько хорош алгоритм, можно посмотреть на временную и пространственную сложность, то есть сколько времени или памяти требуется для его выполнения. Это измеряется в нотации «большое О», которая описывает связь между ростом размера входных данных и количеством операций, необходимых для выполнения алгоритма. Например, добавление 1 к каждому числу внутри массива — это O , потому что количество операций увеличивается линейно по мере роста массива. Важно не точное количество операций, а скорее тенденция при стремлении размера входных данных к бесконечности. Видишь ли, что-то вроде n факториал растёт гораздо быстрее, чем любая линейная функция. Так что пока временная сложность представляет собой какую-то линейную зависимость, она упрощается до O , и то же самое касается любой другой группы. При написании алгоритма всегда есть разные подходы. Подход грубой силы — просто проверять каждый элемент, пока мы не найдём цель в списке. Но если ты хочешь, чтобы твоя программа работала быстрее садовой улитки, нужен более изощрённый подход, вроде «разделяй и властвуй». Например, в двоичном поиске ты повторно проверяешь средний элемент, чтобы увидеть, с какой стороны находится цель, и продолжаешь искать в этой половине, пока не найдёшь её. Кроме того, есть разные подходы к написанию кода в целом, которые называются парадигмами программирования. Декларативное программирование описывает, что делает код, но не то, как именно компьютер должен это делать, тогда как императивное программирование явно описывает, как компьютер должен достичь результата с помощью подробных инструкций. Расширением императивного программирования является объектно-ориентированное программирование, где можно определять классы как чертежи для объектов, которые являются отдельными единицами, состоящими из данных в форме свойств и поведения в форме методов. Чтобы запрограммировать класс, ты начинаешь с определения свойств как переменных и методов как функций. После инкапсуляции свойств и методов в классе ты можешь создать экземпляр объекта и использовать точечную нотацию для работы с его свойствами и методами. Классы упрощают организацию и повторное использование кода, потому что ты можешь определять подклассы, которые наследуют свойства и поведение суперкласса, но также могут их расширять и переопределять. Например, подкласс резиновой уточки может реализовать кряканье как писк. В результате резиновые уточки могут рассматриваться как объекты класса утки, но вести себя иначе при вызове кряканья, что является концепцией полиморфизма. Но для некоторых задач ни одна из этих традиционных парадигм не сработает. Допустим, ты хочешь научить компьютер распознавать, на каком из этих изображений пчела. Проблема в том, что ты не можешь по-настоящему описать, как выглядит пчела, с помощью кода. Здесь на помощь приходит машинное обучение, то есть обучение компьютера выполнять задачу без явного программирования его для этой задачи. Сначала тебе нужно много данных, которые можно разделить на обучающие данные и тестовые данные. Затем ты выбираешь алгоритм, который может менять свои параметры со временем, например нейронную сеть, где веса можно обновлять для достижения другого результата. Передавая в этот алгоритм множество обучающих данных, ты можешь построить модель, точность которой затем можно проверить с помощью тестовых данных. Если она не совсем правильная, модель может со временем улучшаться, сравнивая выход с тем, каким он должен был быть, фиксируя разницу в функции ошибки и подстраивая свои параметры, чтобы минимизировать разницу. Но как бы футуристично, передово, молниеносно и оптимизированно это ни было, если ты хочешь, чтобы люди действительно пользовались приложением, которое ты написал, тебе, вероятно, стоит знать об интернете. Это сеть компьютеров со всего мира, соединённых проводами. Буквально, интернет — это просто куча толстых кабелей, проложенных по дну океана, вместе с такими объектами, как интернет-провайдеры, которые соединяют тебя с пунктом назначения. Эти компьютеры общаются с помощью набора интернет-протоколов. Каждый компьютер в сети имеет уникальный IP-адрес, и два компьютера могут затем передавать данные с помощью протокола управления передачей. Он разбивает сообщения на кучу пакетов, отправляет их через сеть проводов, а затем принимающая сторона собирает сообщение обратно. Если у тебя плохое интернет-соединение, ты мог столкнуться с потерей пакетов, то есть когда некоторые из этих пакетов теряются по пути. Если интернет — это аппаратное обеспечение, то веб — это программное обеспечение, которым можно пользоваться через браузер. Каждая страница в вебе имеет URL. Когда ты вводишь его в свой браузер, он ищет IP-адрес сервера, на котором размещён этот сайт, с помощью системы доменных имён, которая похожа на словарь, сопоставляющий доменные имена с IP-адресами реальных серверов. После подключения к нему через TCP твой браузер, называемый клиентом, использует протокол передачи гипертекста, чтобы отправить HTTP-запрос на сервер, который затем даёт ответ, в идеале содержащий содержимое веб-страницы. Настоящий сайт чаще всего состоит из трёх частей. HTML-файл содержит всё содержимое сайта и по сути является просто набором элементов, которыми могут быть текст, ссылки, кнопки и так далее. CSS-файл управляет визуалом и делает сайт красивым. Но сайт бесполезен, если нажатие на красиво выглядящие кнопки ничего не делает, поэтому язык вроде JavaScript добавляет функциональность. Но иногда что-то может пойти не так. С каждым HTTP-ответом приходит код ответа, который несёт информацию о статусе ответа. Например, 200 означает «OK», а всё, что начинается с 4, — это ошибка, самая известная из которых — 404, страница не найдена. HTTP-запросы могут нести разные методы, например get, post, put и delete, то есть получать, добавлять, обновлять и удалять информацию. Они часто используются интерфейсами прикладного программирования, которые соединяют два приложения и позволяют им взаимодействовать друг с другом. Например, хранить и извлекать данные из базы данных. Самый распространённый тип базы данных — реляционная база данных, которая использует таблицы для хранения данных. Столбцы таблицы содержат разные атрибуты, а строки представляют отдельные точки данных. Кроме того, каждая таблица имеет один уникальный атрибут, называемый первичным ключом. Внешний ключ — это первичный ключ другой таблицы, устанавливающий связь между ними. В этом случае каждая книга связана с автором. С помощью языка вроде SQL ты можешь писать операторы для работы с данными из этих таблиц. Ты мог бы найти названия и авторов всех книг, название которых начинается с H, но для этого нам нужно соединить таблицу авторов с таблицей книг по совпадающему ключу, чтобы объединить два атрибута из разных таблиц в один, что даст нам этот результат. Эти операторы полезны, но нужно быть осторожным, иначе ты можешь просто удалить всю базу данных одной строкой кода. Но не волнуйся, такого никогда не случалось. За каждой страницей входа стоит база данных с именами пользователей и паролями. Когда пользователь пытается войти, SQL-запрос часто используется, чтобы проверить, совпадает ли ввод пользователя с записью в базе данных. Это хорошо. Но коварный злоумышленник мог бы ввести что-то вроде этого, что меняет запрос, преждевременно завершая строку и комментируя остальное, что означает, что пока это имя пользователя существует в базе данных, доступ разрешён. Это называется атакой SQL-инъекцией, и это один из самых простых способов, которыми хакеры попадают туда, куда им не положено. Слышать об этих концепциях — одно, но чтобы действительно их выучить, нужно увидеть их в действии и применить самому, что как раз и можно сделать с Brilliant, у которого есть тысячи интерактивных уроков по всему: от математики и науки о данных до программирования и ИИ. Они закрепляют знания с помощью визуальных уроков и интерактивных задач, что не только весело и развивает интуитивные навыки решения проблем, но и доказано в шесть раз эффективнее, чем просто просмотр часов лекций. Я знаю, что находить время для изучения новых навыков может быть сложно, но Brilliant делает это настолько простым. Ты можешь построить ценные знания с нуля всего за пару минут в день, с короткими уроками с любого устройства, где угодно и когда угодно. Ты пройдёшь путь от основ науки о данных до анализа реальных наборов данных из Spotify буквально за мгновение, что можно дополнить курсами по основам математики и программированию на Python, чтобы построить один из самых востребованных наборов навыков нашего времени. Лучшая часть? Ты можешь попробовать всё, что предлагает Brilliant, бесплатно в течение целых 30 дней, посетив brilliant.org slash wackyscience. Ты также получаешь 20% скидки на годовую премиум-подписку. Спасибо Brilliant за спонсирование этого видео.

Создано 30 янв.

Обновлено 9 авг.

Опубликован 30 янв.

прокси разрешены

Опубликованные чаты