Рассказваю, как залипнуть на N часов и не пожалеть об этом:
https://www.decisionproblem.com/paperclips/index2.html
Игра основана на статье шведского философа Ника Бострома проИИ, который максимизирует число сделанных скрепок (можно еще почитать тут на русском или коротко на английской Вики). (Предупреждаю, статьи могут стать спойлером для самой игры!)
В самой игре вам предстоитиграть за такой ИИ и превратить всю Вселенную в скрепки .
С компьютера можно играть прямо из браузера, а с телефона сайт предлагает скачать приложение; лучше смотреть с компьютера.
(Кстати, ссылку на игру я честно подсмотрел в канале у @markysha)
https://www.decisionproblem.com/paperclips/index2.html
Игра основана на статье шведского философа Ника Бострома про
В самой игре вам предстоит
С компьютера можно играть прямо из браузера, а с телефона сайт предлагает скачать приложение; лучше смотреть с компьютера.
(Кстати, ссылку на игру я честно подсмотрел в канале у @markysha)
Интересная статья про то, почему эффект Даннинга-Крюгера может быть ошибочным:
https://www.psychologytoday.com/us/blog/how-do-you-know/202012/dunning-kruger-isnt-real
Оригинальное утверждение заключалось в следующем: менее компетентные люди способны завышать представления о своих способностях, а более компетентные люди — наоборот, занижать.
В статье автор берет оригинальный график из статьи Даннинга и Крюгера, но предлагает иную модель: а именно, что все люди в среднем завышают свои способности (но со случайным разбросом). После чего он моделирует свое предположение с помощью скрипта на R, и результат симуляции оказывается близким к графику из оригинального эксперимента.
https://www.psychologytoday.com/us/blog/how-do-you-know/202012/dunning-kruger-isnt-real
Оригинальное утверждение заключалось в следующем: менее компетентные люди способны завышать представления о своих способностях, а более компетентные люди — наоборот, занижать.
В статье автор берет оригинальный график из статьи Даннинга и Крюгера, но предлагает иную модель: а именно, что все люди в среднем завышают свои способности (но со случайным разбросом). После чего он моделирует свое предположение с помощью скрипта на R, и результат симуляции оказывается близким к графику из оригинального эксперимента.
— О. Ну что же, в физике никто из нас не разбирается, поэтому поговорить о ней нам, я думаю, не удастся.
— Наоборот, — ответил я. — Поговорить о физике нам не удастся именно потому, что кое-кто из нас в ней разбирается. А обсуждать можно лишь то, о чем никто ничего не знает. Мы можем поговорить о погоде, можем — об общественных проблемах, о психологии, о международных финансах, — не о перемещении золота, тут все-таки нужно хоть что-то понимать, — для любого общего разговора годится лишь та тема, в которой никто ничего не смыслит.
Ричард Фейнман, «Вы, конечно, шутите, мистер Фейнман»
— Наоборот, — ответил я. — Поговорить о физике нам не удастся именно потому, что кое-кто из нас в ней разбирается. А обсуждать можно лишь то, о чем никто ничего не знает. Мы можем поговорить о погоде, можем — об общественных проблемах, о психологии, о международных финансах, — не о перемещении золота, тут все-таки нужно хоть что-то понимать, — для любого общего разговора годится лишь та тема, в которой никто ничего не смыслит.
Ричард Фейнман, «Вы, конечно, шутите, мистер Фейнман»
Как расширить размер стека
Иногда в олимпиадных задачах не хватает стека, и надо бы увеличить его размер. Есть много разных способов. Например, для MSVC действует такой:
Иногда в олимпиадных задачах не хватает стека, и надо бы увеличить его размер. Есть много разных способов. Например, для MSVC действует такой:
#pragma comment(linker, "/STACK:16777216")Можно еще вручную выделить массив и переместить на него стек, используя ассемблер. Код ниже работает на GCC для amd64 (тестировался на GNU/Linux, хотя скорее всего будет работать и под Windows):
extern "C" {
void main2();
// размер стека — 16 МБ. Если нужно больше, можно
// поменять размер массива(но alignas не трогать!)
alignas(16) char stack[16777216];
}
void main2() {
// здесь основной код
}
int main() {
asm(
// сохраняем старые rsp и rbp
"pushq %rbp\n"
"movq %rsp, %rbp\n"
// перемещаем rsp на конец созданного
// нами массива; теперь он будет стеком
"leaq stack(%rip), %rsp\n"
"addq $16777216, %rsp\n"
// зовем main2() с основным кодом
"callq main2\n"
// возвращаем все на место
"movq %rbp, %rsp\n"
"popq %rbp"
);
return 0;
}
О том, почему формулировать задания сто́ит предельно четко. Или о том, как не надо работать с заказчиком. Или о том, почему не стоит доверять работу троллям. В общем:
https://27bslash6.com/missy.html
https://27bslash6.com/missy.html
27Bslash6
Missing Missy
"I'm extremely emotional over this and was up all night in tears."
Худшая файловая система в мире
Познакомьтесь. Это EvilFS, который работает через FUSE:
https://pastebin.com/B9KSe0Z0
Инструкция по применению:
- желательно запускать на GNU/Linux
- установите
- после запуска скрипта создастся папка рядом со скриптом. Зайдите в нее из командной строки и попробуйте прочитать файлы в ней
- не получилось? Поздравляю, вы застряли :D
- хотите убить процесс, читающий файл, с помощью
К счастью, выпутаться из неприятной ситуации возможно: достаточно просто убить сам процесс EvilFS, тогда у использующих ее процессов произойдет разрыв соединения, и их можно будет завершить.
Как это работает?
Все просто. EvilFS реализуется через FUSE — это возможность создавать файловые системы полностью в userspace. Процесс EvilFS как раз создает такую файловую систему и монтирует ее, а в ходе работы обрабатывает все запросы в нее.
Так вот: на запрос
Но почему процесс нельзя убить, пока он пытается открыть плохой файл? Здесь вступает в дело понятие uninterruptible sleep (a.k.a. непробудный сон). Он происходит тогда, когда процесс завис в системном вызове, который нельзя прервать (т.к. не все системные вызовы умеют возвращать
Продолжение следует...
Познакомьтесь. Это EvilFS, который работает через FUSE:
https://pastebin.com/B9KSe0Z0
Инструкция по применению:
- желательно запускать на GNU/Linux
- установите
libfuse2
из системного пакетного менеджера и pyfuse
через pip
- запустите скрипт- после запуска скрипта создастся папка рядом со скриптом. Зайдите в нее из командной строки и попробуйте прочитать файлы в ней
- не получилось? Поздравляю, вы застряли :D
- хотите убить процесс, читающий файл, с помощью
SIGKILL
? Поздравляю, его убить нельзя :DК счастью, выпутаться из неприятной ситуации возможно: достаточно просто убить сам процесс EvilFS, тогда у использующих ее процессов произойдет разрыв соединения, и их можно будет завершить.
Как это работает?
Все просто. EvilFS реализуется через FUSE — это возможность создавать файловые системы полностью в userspace. Процесс EvilFS как раз создает такую файловую систему и монтирует ее, а в ходе работы обрабатывает все запросы в нее.
Так вот: на запрос
open()
(т.е. открыть файл) EvilFS просто начинает висеть, подвешивая и того, кто пытается файл открыть. Т.е. мы не можем прочитать файл, потому что его открытие зависает.Но почему процесс нельзя убить, пока он пытается открыть плохой файл? Здесь вступает в дело понятие uninterruptible sleep (a.k.a. непробудный сон). Он происходит тогда, когда процесс завис в системном вызове, который нельзя прервать (т.к. не все системные вызовы умеют возвращать
EINTR
). Например, open()
прервать нельзя. Во время непробудного сна процесс не принимает никакие сигналы (даже SIGKILL
!), то есть, его нельзя убить. Понятно, что зависнуть в open()
'е в естественных условиях — дело редкое, но возможное в случае сетевых ФС или медленного диска. А вот в случае с FUSE такое зависание нетрудно воспроизводится в домашних условиях.Продолжение следует...
Еще более злая файловая система 😈📁
Думали, что хуже EvilFS ничего нет? Есть, конечно! Знакомьтесь, EvilFSv2:
https://pastebin.com/y3PrJvyu
Инструкция по применению аналогичная. Но, в отличие от своего менее коварного предшественника, EvilFSv2 содержит три файла:
Более того, EvilFSv2 не ждет, пока пользователь прочитает
Как же убить EvilFSv2? Выхода нет?
Оказывается, есть. Достаточно лишь сделать
Думали, что хуже EvilFS ничего нет? Есть, конечно! Знакомьтесь, EvilFSv2:
https://pastebin.com/y3PrJvyu
Инструкция по применению аналогичная. Но, в отличие от своего менее коварного предшественника, EvilFSv2 содержит три файла:
a.txt
, b.txt
и c.txt
. При этом, если открыть c.txt
, то сама EvilFSv2 попытается сделать open('evil_fs/a.txt')
, что приведет к попаданию процесса EvilFSv2 в состояние uninterruptible sleep. Это означает, что любые попытки завершить EvilFSv2 тщетны и напрасны. Вот такой вот Уроборос.Более того, EvilFSv2 не ждет, пока пользователь прочитает
c.txt
и повесит ФС на самой себе, а действует проактивно: форкается и в форке пытается этот самый c.txt
прочесть.Как же убить EvilFSv2? Выхода нет?
Оказывается, есть. Достаточно лишь сделать
for FILE in /sys/fs/fuse/connections/*/abort; doПравда, при этом отмонтируются все остальные основанные на FUSE файловые системы, но тем не менее с задачей завершить EvilFSv2 мы справились :)
echo 1 >$FILE
done
Если кому-то хотелось подробно разобраться, как работает линкер, то вот, на мой взгляд, самая толковая и подробная статья:
https://maskray.me/blog/2021-06-20-symbol-processing
https://maskray.me/blog/2021-06-20-symbol-processing
MaskRay
Symbol processing
UNDER CONSTRUCTION (COFF, Mach-O) Symbol processing is a major step in a linker. In most binary formats, the linker maintains a global symbol table and performs symbols resolution for each input file
We pretend not to understand Russian, sorry
Ссылка на сам issue: https://github.com/ton-blockchain/ton/issues/31
Ссылка на сам issue: https://github.com/ton-blockchain/ton/issues/31
Какое максимальное число допустимых вариантов хода может быть в шахматной позиции?
Ответ — 218:
https://www.chessprogramming.org/Encoding_Moves#Move_Index
(см. также диаграммы выше)
FEN этих позиций:
-
Ответ — 218:
https://www.chessprogramming.org/Encoding_Moves#Move_Index
(см. также диаграммы выше)
FEN этих позиций:
-
R6R/3Q4/1Q4Q1/4Q3/2Q4Q/Q4Q2/pp1Q4/kBNN1KB1 w - - 0 1
- 3Q4/1Q4Q1/4Q3/2Q4R/Q4Q2/3Q4/1Q4Rp/1K1BBNNk w - - 0 1
Больше позиций с 218 ходами (кроме этих двух + отражения и смена цвета), насколько мне известно, не существует.Сколько юристов потребуется, чтобы заменить лампочку?
Такое количество, которое будет сочтено необходимым для своевременного и эффективного выполнения поставленной задачи в рамках нижеследующего соглашения: Первая сторона, также известная как «Юрист», и вторая сторона, также известная как «Лампочка», настоящим образом заключают соглашение, согласно которому вторая сторона (Лампочка) будет снята с занимаемой позиции в результате невыполнения ранее согласованных обязательств, а именно, освещение, иллюминация и иная подсветка территории от входной (северной) двери, через входной проем, заканчивающейся в зоне внутри основной жилой зоны, обозначенной началом ковра, причем любое дополнительное освещение осуществляется по желанию второй стороны (Лампочки) и не требуется в соответствии с вышеупомянутым соглашением между сторонами.
Вышеупомянутая операция по снятию с позиции включает, но не ограничивается, следующими этапами:
1. Первая сторона (Юрист) должна с возвышением или без возвышения, по своему выбору, с помощью стула, стремянки, лестницы или любого другого средства возвышения, схватить вторую сторону (Лампочку) и повернуть вторую сторону (Лампочку) против часовой стрелки, этот пункт не подлежит обсуждению.
2. По достижении точки, где вторая сторона (Лампочка) становится отделенной от третьей стороны («Патрон»), первая сторона (Юрист) имеет возможность распорядиться второй стороной (Лампочкой) в соответствии со всеми применимыми государственными законами.
3. После отделения и утилизации первая сторона (Юрист) имеет возможность начать установку четвертой стороны («Новая лампочка»). Установка должна происходить в порядке, обратном описанному в первом шаге этого же документа, при этом следует обратить внимание на то, что вращение должно происходить по часовой стрелке, этот пункт также не подлежит обсуждению.
Примечание: Вышеописанные действия могут быть выполнены, по желанию стороны первой части (Юриста), любым или всеми уполномоченными им лицами, с целью получения максимально возможной прибыли пятой стороной, также известной как «Компания».
Оригинал можно найти по ссылке (также см. коммент к этому посту). Перевода я не нашел, поэтому пришлось мне самому переводить лапками. Любые исправления неточностей приветствуются :)
Такое количество, которое будет сочтено необходимым для своевременного и эффективного выполнения поставленной задачи в рамках нижеследующего соглашения: Первая сторона, также известная как «Юрист», и вторая сторона, также известная как «Лампочка», настоящим образом заключают соглашение, согласно которому вторая сторона (Лампочка) будет снята с занимаемой позиции в результате невыполнения ранее согласованных обязательств, а именно, освещение, иллюминация и иная подсветка территории от входной (северной) двери, через входной проем, заканчивающейся в зоне внутри основной жилой зоны, обозначенной началом ковра, причем любое дополнительное освещение осуществляется по желанию второй стороны (Лампочки) и не требуется в соответствии с вышеупомянутым соглашением между сторонами.
Вышеупомянутая операция по снятию с позиции включает, но не ограничивается, следующими этапами:
1. Первая сторона (Юрист) должна с возвышением или без возвышения, по своему выбору, с помощью стула, стремянки, лестницы или любого другого средства возвышения, схватить вторую сторону (Лампочку) и повернуть вторую сторону (Лампочку) против часовой стрелки, этот пункт не подлежит обсуждению.
2. По достижении точки, где вторая сторона (Лампочка) становится отделенной от третьей стороны («Патрон»), первая сторона (Юрист) имеет возможность распорядиться второй стороной (Лампочкой) в соответствии со всеми применимыми государственными законами.
3. После отделения и утилизации первая сторона (Юрист) имеет возможность начать установку четвертой стороны («Новая лампочка»). Установка должна происходить в порядке, обратном описанному в первом шаге этого же документа, при этом следует обратить внимание на то, что вращение должно происходить по часовой стрелке, этот пункт также не подлежит обсуждению.
Примечание: Вышеописанные действия могут быть выполнены, по желанию стороны первой части (Юриста), любым или всеми уполномоченными им лицами, с целью получения максимально возможной прибыли пятой стороной, также известной как «Компания».
Оригинал можно найти по ссылке (также см. коммент к этому посту). Перевода я не нашел, поэтому пришлось мне самому переводить лапками. Любые исправления неточностей приветствуются :)
Как восстановить файл, если кто-то держит на него открытый файловый дескриптор
Как известно, файл можно удалить, пока кто-то его открыл и из него читает. В этом случае уже открытый файловый дескриптор все еще доступен после удаления файла, и из него можно спокойно читать.
Можно попытаться и восстановить доступ к удаленному файлу: найти его в
Известно, что ссылка на открытый файл в
Как известно, файл можно удалить, пока кто-то его открыл и из него читает. В этом случае уже открытый файловый дескриптор все еще доступен после удаления файла, и из него можно спокойно читать.
Можно попытаться и восстановить доступ к удаленному файлу: найти его в
/proc/<pid>/fd/<fd>
и скопировать. Но можно ли обойтись без копирования, а просто восстановить хардлинк на него в файловой системе?Известно, что ссылка на открытый файл в
/proc
отображается как символьная ссылка, но на самом деле символьной ссылкой не является. Так, для открытого удаленного файла stat
будет выглядеть примерно так:$ stat /proc/42002/fd/3Теперь попробуем создать хардлинк. Сначала попробуем воспользоваться простой командой
Файл: /proc/42002/fd/3 -> /home/gepardo/tmp/q.txt (deleted)
Размер: 64 Блоков: 0 Блок В/В: 1024 символьная ссылка
Устройство: 00h/00d Инода: 000000 Ссылки: 1
Доступ: (0500/lr-x------) Uid: ( 1000/ gepardo) Gid: ( 1000/ gepardo)
Доступ: 2022-11-03 20:46:09.224688879 +0300
Модифицирован: 2022-11-03 20:46:02.440682242 +0300
Изменён: 2022-11-03 20:46:02.440682242 +0300
Создан: -
ln
:$ ln -T /proc/42002/fd/3 w.txtНе получилось. Но мы непременно попробуем еще в следующем посте :)
ln: не удалось создать жёсткую ссылку 'w.txt' => '/proc/42002/fd/3': Неверная ссылка между устройствами
Как восстановить файл, если кто-то держит на него открытый файловый дескриптор (часть II)
Напомню, что в предыдущем посте мы пытались восстановить удаленный файл, не копируя его. У нас не получилось, но мы пробуем еще.
Пробуем. В Linux есть системный вызов
https://pastebin.com/tkyY2abT
Увы, не работает: программа выдает
> ENOENT An attempt was made to link to a /proc/self/fd/NN file corresponding to a file that has been deleted.
Вариант с
https://pastebin.com/vVz3zcR0
Так что, к сожалению, остается единственный способ — копировать.
Напомню, что в предыдущем посте мы пытались восстановить удаленный файл, не копируя его. У нас не получилось, но мы пробуем еще.
Пробуем. В Linux есть системный вызов
linkat()
. Он поддерживает флаги AT_EMPTY_PATH
и AT_SYMLINK_FOLLOW
, которые позволяют создать хардлинк на файл по файловому дескриптору на него (в том числе по ссылке в /proc/<pid>/fd
). На StackOverflow показывают пример, как можно сделать хардлинк по файловому дескриптору:fd = open("/tmp", O_TMPFILE | O_RDWR, 0600);Попробуем так же:
// write something to the file here
// fchown() / fchmod() it
linkat(fd, "", AT_FDCWD, "/tmp/test", AT_EMPTY_PATH);
https://pastebin.com/tkyY2abT
Увы, не работает: программа выдает
linkat: No such file or directory
. Впрочем, man
явно предупреждает, что ничего не выйдет, и среди ошибок упоминает> ENOENT An attempt was made to link to a /proc/self/fd/NN file corresponding to a file that has been deleted.
Вариант с
AT_SYMLINK_FOLLOW
тоже ничего не дает:https://pastebin.com/vVz3zcR0
Так что, к сожалению, остается единственный способ — копировать.