Неравенство Таппера, рисующее само себя
В 2001 году в материалах конференции СИГГРАФ (SIGGRAPH) Джеф Таппер (Jeff Tupper) опубликовал неравенство, которое способно нарисовать само себя на двумерном бинарном холсте. Образ неравенства (нижнняя часть картинки) представляет собой двухцветный рисунок.
Ремарка: нижние полуквадратные скобки в неравенстве обозначают функцию floor(.) — округление до меньшего ближайшего целого; mod(a, b) — это остаток от целочисленного деления a на b.
Неравенство изображает себя, при условии
0 ≤ x < 106,
n ≤ y < n + 17,
где n -- это 543-значное число:
n = 960 939 379 918 958 884 971 672 962 127 852 754 715 004 339 660 129 306 651 505 519 271 702 802 395 266 424 689 642 842 174 350 718 121 267 153 782 770 623 355 993 237 280 874 144 307 891 325 963 941 337 723 487 857 735 749 823 926 629 715 517 173 716 995 165 232 890 538 221 612 403 238 855 866 184 013 235 585 136 048 828 693 337 902 491 454 229 288 667 081 096 184 496 091 705 183 454 067 827 731 551 705 405 381 627 380 967 602 565 625 016 981 482 083 418 783 163 849 115 590 225 610 003 652 351 370 343 874 461 848 378 737 238 198 224 849 863 465 033 159 410 054 974 700 593 138 339 226 497 249 461 751 545 728 366 702 369 745 461 014 655 997 933 798 537 483 143 786 841 806 593 422 227 898 388 722 980 000 748 404 719
Давайте разберемся, откуда взялось это число, и как оно помогает рисовать неравенство.
Прежде всего заметим, что мы рисуем на дискретном холсте размером 105 на 17 и, меняя x и y, мы пробегаем каждый пиксель этого холста.
Введем переменную k = 17. Тогда, неравенство перепишется так.
Обозначим
ix=floor(x),
iy=floor(y).
Тогда mod(iy,k) меняется от 0 to 16.
А показатель степени при двойке k*ix + mod(iy,k) меняется от 0 до 105*17-1. То есть это индекс, последовательно указывающий на каждый пиксель (ix, iy):
index=k*ix + mod(iy,k).
В числителе записано floor(y/k). Это некоторое целое число B. Когда мы делим его на 2^index, мы сдвигаем биты B вправо (к меньшим значениям) на index позиций. То есть B / 2^index последовательно перебирает все биты B.
Когда мы берем модуль по основанию 2 от полученного значения
mod(B / 2^index, 2)
мы, всего лишь, определяем, четно ли полученное число или нечетно.
Таким образом вся формула всего лишь определяет, есть или нет бит в каждой позиции числа B.
Алгоритм рисования, перебирает координаты каждой точки дискретного холста 105*17, определят, если или нет бит в заданной позиции числа B, и рисует пиксель, когда бита нет (и не рисует, когда он есть).
То есть число n кодирует битовый образ картинки, умноженный на 17.
За столь подробное объяснение спасибо Avitzur.
— Получается, что в числе n мы можем закодировать любую картинку? — Да, так и есть. При этом формула останется той же.
Напоследок замечу, что формулу Таппера можно считать далеким аналогом современных нейросетей, рисующих картинки по запросу. Принцип действия у них похожий. У Таппера рисунок закодирован в одном числе, а у нейросетей, в огромном множестве параметров.
Вы можете самостоятельно поэкспериментировать с преобразование бинарного рисунка в число на странице:
https://tuppers-formula.ovh/
А на Розетском-коде выложены реализации формулы Таппера на разных языках программирования.