А в какой момент остановиться? " метка" (пробелы), "метkа" (латинская k), "мтека" (опечатка), "label" (другой язык), "мeткa" (латинские e, a), "метка" (unicode zero-width space). На мой взгляд будет лучше прикладному приложению рекомендовать (например с помощью autocomplete) пользователю использовать уже существующее похожее имя, чем требовать от системы считать какие-то разные имена одинаковыми.
Интересно, почему отображение "гексаграмма <-> номер" именно такое? Современные читатели Хабра естественным образом предложили бы интерпретацию 57, 42, 30, 32 вместо 25, 64, 28, 23 для картинки из этого поста.
Потому что LLM выдаёт не строку текста, а распределение токенов на каждую итерацию, и из этого распределения случайным образом выбирает очередной токен. Получить разные результаты можно даже подавая на вход одни и те же данные (если, конечно, не считать состояние ГПСЧ ещё одним входом).
В отличие от традиционной математики тут нет аксиом, нагло постулирующих истинность каких-то утверждений без существенных на то оснований (аксиомы выбора, исключения третьего и т.п.).. Доказательством в конструктивной математике считается алгоритм получения свидетельства истинности
А что является критерием "наглости"? Для проверки истинности ведь нужны хоть какие-то аксиомы - какие тогда пройдут этот фильтр?
С malloc(0)==NULL случай интересный, это implementation-defined поведение, которому есть разумное объяснение.
Бывает полезно, когда malloc(0) возвращает то же, что и malloc(1) - это позволяет написать обобщённый код, одновременно выделяющий память под структуру (в том числе нулевого размера) и использующий указатель в качестве уникального идентификатора в какой-то другой структуре данных.
Потому что на вход получает "исходник" (строку типа "11 11 1 - + 4 * 2 /"), а на выходе - скомпилированный wasm-модуль с единственной экспортированной функцией "посчитай", которая кладёт на стек числа и выполняет арифметические операции в нужном порядке.
Если использовать простые (запоминает отображение публичного ключа пользователя на его внешние IP:port) сервисы по условиям задачи можно, то есть WireGuard и nat-hole-punching - берём две машины за NAT и иногда (скажем раз в час) запускаем на них nat-puch-client - инструкция есть в README.
В случае, если своего сервера нет, можно использовать (вместо "1.2.3.4" в README) публичный сервер demo.wireguard.com - никакой существенной нагрузки это не создаст, сервер получает запрос по UDP и отвечает на него, передавая за раз около одной сотни байт.
CGI, в особенности вместе с Shell, опасен слишком широкими возможностями для манипуляции окружением снаружи. Тяжело заранее узнать, не будет ли одна из программ, вызываемых CGI-скриптом, каким-то неожиданным для разработчика образом интерпретировать переменные окружения.
gdb очень полезен вместе с awk или perl. Например, собрать все стеки, когда возникает какое-то событие, а потом каким-нибудь хитрым образом их поделить на классы. Или сгенерировать с их помощью скрипт для gdb, чтобы воспроизвести нужное состояние.
Но ведь если аналогичный комплект разработки расширений положить для Node.js и Python (чтобы npm и pip могли при установке пакетов что-то дособрать), то и они сильно распухнут, особенно в случае Windows.
Если пытаться более честно сравнить, то будет вот так:
$ docker run --rm alpine:latest apk add perl
...
OK: 45 MiB in 17 packages
$ docker run --rm alpine:latest apk add nodejs
...
OK: 66 MiB in 28 packages
$ docker run --rm alpine:latest apk add python3
...
OK: 49 MiB in 32 packages
Если "словарь" понимается в узком смысле, как справочник слов для перевода с одного языка на другой, то самое популярное применение - структура для хранения записей с множеством атрибутов, способная выдать весь кортеж целиком по значению ключевого поля, например вытащить всю информацию о пользователе по его ID.
Без map пришлось бы либо хранить в векторе всегда отсортированные по ключу пары (и тогда поиск по конкретному ключу займёт O(log(N)) времени, где N - длина вектора), затрачивая существенное время (O(N) на сдвиг) на вставку, либо вставлять как попало (O(1)) и делать полный пересбор (O(N)), пока не найдём нужный элемент.
map позволяет получить амортизированную сложность O(1) как на вставку, так и на поиск.
компилятор обычно генерирует машинный код, а не ассемблерную программу
Скорее всего тут недостаточно контекста, и всё зависит от того, что понимается под терминами "компилятор" и "программа".
Самый обычный (поставляется вместе с ОС) GCC 13.3.0 на моей машине при выполнении "gcc hello.c" ведёт себя так (это можно проверить с помощью strace -f или gcc -v):
Запускает компилятор "cc1", который читает с диска hello.c и записывает временный файл на языке ассемблера в $TMPDIR со случайным именем с суффиксом ".s".
Запускает ассемблер "as", который читает временный файл из п. 1 и записывает новый временный объектный файл в $TMPDIR со случайным именем с суффиксом ".o".
Запускает обёртку "collect2", которая запускает компоновщик "ld".
ld собирает программу из crt*.o и файла, полученного в п. 2, порождая динамически (с использованием загрузчика ld-linux-aarch64.so.1) слинкованный (с libc.so.6) исполняемый файл с именем a.out.
Являются ли компилятором "gcc" и/или (только) "cc1"? Является ли ассемблерной программой файл .s из п.1?
Чем операционная семантика отличается от денотационной, и они обе - от синтаксиса.
Если не секрет, то как вы объясняете это, чтобы студент понял, не заставляя написать компилятор? И сколько времени на это уходит?
А в какой момент остановиться? " метка" (пробелы), "метkа" (латинская k), "мтека" (опечатка), "label" (другой язык), "мeткa" (латинские e, a), "метка" (unicode zero-width space). На мой взгляд будет лучше прикладному приложению рекомендовать (например с помощью autocomplete) пользователю использовать уже существующее похожее имя, чем требовать от системы считать какие-то разные имена одинаковыми.
Именно так, для горизонтальной прокрутки. Если покрутить второе колесо вверх - фрейм будет прокручиваться влево, а вниз - вправо.
Интересно, почему отображение "гексаграмма <-> номер" именно такое? Современные читатели Хабра естественным образом предложили бы интерпретацию 57, 42, 30, 32 вместо 25, 64, 28, 23 для картинки из этого поста.
Потому что LLM выдаёт не строку текста, а распределение токенов на каждую итерацию, и из этого распределения случайным образом выбирает очередной токен. Получить разные результаты можно даже подавая на вход одни и те же данные (если, конечно, не считать состояние ГПСЧ ещё одним входом).
А что является критерием "наглости"? Для проверки истинности ведь нужны хоть какие-то аксиомы - какие тогда пройдут этот фильтр?
С malloc(0)==NULL случай интересный, это implementation-defined поведение, которому есть разумное объяснение.
Бывает полезно, когда malloc(0) возвращает то же, что и malloc(1) - это позволяет написать обобщённый код, одновременно выделяющий память под структуру (в том числе нулевого размера) и использующий указатель в качестве уникального идентификатора в какой-то другой структуре данных.
Потому что на вход получает "исходник" (строку типа "11 11 1 - + 4 * 2 /"), а на выходе - скомпилированный wasm-модуль с единственной экспортированной функцией "посчитай", которая кладёт на стек числа и выполняет арифметические операции в нужном порядке.
Если использовать простые (запоминает отображение публичного ключа пользователя на его внешние IP:port) сервисы по условиям задачи можно, то есть WireGuard и nat-hole-punching - берём две машины за NAT и иногда (скажем раз в час) запускаем на них nat-puch-client - инструкция есть в README.
В случае, если своего сервера нет, можно использовать (вместо "1.2.3.4" в README) публичный сервер demo.wireguard.com - никакой существенной нагрузки это не создаст, сервер получает запрос по UDP и отвечает на него, передавая за раз около одной сотни байт.
Прошло время, и вечность eternalhost закончилась - их сайт отвечает 502.
Когда-то можно было делать вот так:
И вот так:
CGI, в особенности вместе с Shell, опасен слишком широкими возможностями для манипуляции окружением снаружи. Тяжело заранее узнать, не будет ли одна из программ, вызываемых CGI-скриптом, каким-то неожиданным для разработчика образом интерпретировать переменные окружения.
На тот момент, когда он его выкинул, их могло быть на несколько центов.
awk уже есть в busybox, а под perl может не хватать флеша.
gdb очень полезен вместе с awk или perl. Например, собрать все стеки, когда возникает какое-то событие, а потом каким-нибудь хитрым образом их поделить на классы. Или сгенерировать с их помощью скрипт для gdb, чтобы воспроизвести нужное состояние.
Но ведь если аналогичный комплект разработки расширений положить для Node.js и Python (чтобы npm и pip могли при установке пакетов что-то дособрать), то и они сильно распухнут, особенно в случае Windows.
Если пытаться более честно сравнить, то будет вот так:
На всех модемах, которые у меня были, она была по-умолчанию включена.
В GCC есть https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html (и часть из них есть в Clang), в Rust есть https://doc.rust-lang.org/std/intrinsics/fn.add_with_overflow.html
Зависит от того, что такое "словарь" - ведь в самом общем случае это то же самое, что и map.
Из интересных (на мой взгляд) применений - content-addressable storage.
Если "словарь" понимается в узком смысле, как справочник слов для перевода с одного языка на другой, то самое популярное применение - структура для хранения записей с множеством атрибутов, способная выдать весь кортеж целиком по значению ключевого поля, например вытащить всю информацию о пользователе по его ID.
I2P в таком сценарии может ещё использоваться для обхода NAT и firewall, за которыми находится VPN-сервер.
Без map пришлось бы либо хранить в векторе всегда отсортированные по ключу пары (и тогда поиск по конкретному ключу займёт O(log(N)) времени, где N - длина вектора), затрачивая существенное время (O(N) на сдвиг) на вставку, либо вставлять как попало (O(1)) и делать полный пересбор (O(N)), пока не найдём нужный элемент.
map позволяет получить амортизированную сложность O(1) как на вставку, так и на поиск.
Скорее всего тут недостаточно контекста, и всё зависит от того, что понимается под терминами "компилятор" и "программа".
Самый обычный (поставляется вместе с ОС) GCC 13.3.0 на моей машине при выполнении "gcc hello.c" ведёт себя так (это можно проверить с помощью strace -f или gcc -v):
Запускает компилятор "cc1", который читает с диска hello.c и записывает временный файл на языке ассемблера в $TMPDIR со случайным именем с суффиксом ".s".
Запускает ассемблер "as", который читает временный файл из п. 1 и записывает новый временный объектный файл в $TMPDIR со случайным именем с суффиксом ".o".
Запускает обёртку "collect2", которая запускает компоновщик "ld".
ld собирает программу из crt*.o и файла, полученного в п. 2, порождая динамически (с использованием загрузчика ld-linux-aarch64.so.1) слинкованный (с libc.so.6) исполняемый файл с именем a.out.
Являются ли компилятором "gcc" и/или (только) "cc1"? Является ли ассемблерной программой файл .s из п.1?
Если не секрет, то как вы объясняете это, чтобы студент понял, не заставляя написать компилятор? И сколько времени на это уходит?