Arvi the Hacker (Арви Хэкер) ([info]arvi) wrote,
@ 2008-02-04 18:33:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
Магический квадрат 2008 года (математика и гигагерцы).
      1   2   3   4         1   2   3   4
  +----------------     +----------------
 1|   1   2  15  16    1|  16   1  15   2
 2|  12  14   3   5    2|   5   8  10  11
 3|  13   7  10   4    3|   4  13   3  14
 4|   8  11   6   9    4|   9  12   6   7

Любопытно, экспериментировал ли кто-нибудь с магическим квадратом недавно, на гигагерцовых машинках? У меня получается, что если кодировать задачу по поиску всех магических квадратов в лоб, то даже при некоторых интеллектуальных ограничениях перебора им решаются лишь квадраты 3x3 (мгновенно, все 8 поворотов и отражений одного квадрата) и 4x4 (если написать перебор на чистом FreePascal'е, все 7040 вариантов на 1,8ГГц машинке получаются меньше, чем за 20 секунд). На врезке справа приведены два полученных магических квадрата 4x4, а именно №0 и №7039. В принципе, можно влёгкую переписать проверку IsMagic на ассемблере. Это увеличит скорость ещё в несколько раз и поможет сделать время счёта для 5x5 разумным, но большие квадраты требуют алгоритмических резервов.

      1   2   3   4   5
  +--------------------
 1|   1   2  13  24  25
 2|   6  18  17   4  20
 3|  21  16  15  10   3
 4|  23   7  11  19   5
 5|  14  22   9   8  12

Это я к тому, что в понедельник мне приснилась задачка по вычислению магического квадрата 10x10. Будто я лет на 10-15 моложе и снова сдаю вступительный в МГУ. Или сессию, пересдачу. Или ещё куда-то, что явно связано с Университетом. Лиц не помню. Помню лишь ощущение, что люди, передавшие задание мне лично, были спокойны, доброжелательны и уверены, что я справлюсь. И вот та программка, которая уже часами в фоне щёлкает 5x5 (первый её результат дан слева), использует обычный перебор с простейшими эвристиками из тех, которые я придумал во сне для более требовательной задачи.

Кто-нибудь ещё возился с такими (и большими) квадратами? Даже 80-символьный экран позволяет отображать квадраты 19x19, а ведь 80 символов в строке сейчас далеко не предел… Вначале я думал, что при современных гигагерцах/гигабайтах любые отображаемые квадраты должны щёлкаться, как орешки — даже брутфорсом. Что основная проблема (в том числе по быстродействию) будет с выводом квадратов. Ан нет, компьютеры всё ещё слабы и даже задачка 5x5 по-прежнему бросает вызов.

P.S. Погуглил. Хе-хе. Даже если моя программка найдёт все решения 5x5, пусть без отражений и поворотов, винчестер всё равно переполнится быстрее. Новый вариант тратит на поиск магического квадрата меньше 10 секунд, десятки тысяч их уже найдены. Все квадраты будут найдены лет через 70, но на всякий случай освобожу гигабайтик-другой уже сейчас… :-)

      1   2   3   4   5   6   7   8   9  10
  +----------------------------------------
 1|   3   0   7   4  51  48  95  92  99  96
 2|   1   2   5   6  49  50  93  94  97  98
 3|  23  20  71  68  67  64  15  12  79  76
 4|  21  22  69  70  65  66  13  14  77  78
 5|  83  80  63  60  56  59  39  36  11   8
 6|  81  82  61  62  57  58  37  38   9  10
 7|  88  91  24  27  43  40  72  75  16  19
 8|  89  90  25  26  41  42  73  74  17  18
 9|  52  55  84  87  32  35  28  31  44  47
10|  54  53  86  85  34  33  30  29  46  45

P.P.S. Применив к любому квадрату 5x5 из найденных LUX-метод Конвея (упомянутый алгоритмический резерв), получаем требуемый магический квадрат 10x10. Справа расположен квадрат, полученный из первого магического квадрата 5x5. Кстати, во сне на построение магического квадрата 10x10 отводился день (было утро, моё решение отдадут на проверку следующим утром). Мне ещё тогда было ясно, что задание несложное и суток для него достаточно. Действительно, уложился без особой спешки и теперь могу спать спокойно. :-))) Более того, моя программа эти магические квадраты 10x10 уже печёт сотнями (к утру их было больше 300Кб). Жаль лишь, что полный перебор (пока?) долгий и не дал результата.

А вообще-то задание интересное и напоминает второе задание вступительного 1998 года, про Тупого Сержанта. Всем советую. Возможно, действительно буду использовать магический квадрат в качестве вступительного для старших учеников — при составлении заданий 1998 года я об этом задумывался, но в то время счёл излишне сложным.




(34 comments) - (Post a new comment)


[info]moonwalker72
2008-02-04 08:43 pm UTC (link)
В каждой строке/столбце есть как минимум одно простое число.

(Reply to this) (Thread)


[info]arvi
2008-02-04 08:53 pm UTC (link)

Могу замылить список всех магических квадратов 4x4 для проверки этого предположения. Какие-то жалкие 900Кб, пустяки по меркам 2008 года. :-)

(Reply to this) (Parent)(Thread)

(Screened Post)

[info]arvi
2008-02-04 09:58 pm UTC (link)
Выслал.

(Reply to this) (Parent)


(Anonymous)
2008-02-04 09:22 pm UTC (link)
Только если считать единицу простым. иначе не верно для 3 на 3

(Reply to this) (Parent)


[info]arbinada
2008-02-05 09:41 am UTC (link)
Я секунд 20 врубался, что (X, Y, N, L, M и D) - это ограничения на число переменных и не мог понять, в чем сложность задачки :)))

(Reply to this) (Thread)


[info]arvi
2008-02-05 07:02 pm UTC (link)

Сложность в том, что не все из кандидатов знают, что умеют программировать. Многие просто боятся и ломаются. :-) Кроме того задание было зашифровано. И часть народу отсеялась на расшифровке. То есть смогли понять задание, но не смогли выполнить.

(Reply to this) (Parent)


[info]ramendik
2008-02-10 01:29 am UTC (link)
Почитал задания по ссылке 1998. В одном не понял, как это _принципиально_ можно сделать:


1. Без использования дополнительной памяти (переменных, массивов,
стека..) поменять местами содержимое двух целых переменных, X и Y.
Разрешено использовать только команды присваивания, арифметические и
логические операции, стандартные функции, кусочек сыра.

1*. Проделайте тоже самое, используя команды присваивания и лишь одну
операцию.

Ну, 1 решается тривиально в две строки - причём операции, стандартные функции и кусочек сыра там для отвода глаз, и похоже есть аж два варианта (через арифметику и через логику, но через логику я не проверял).

Непонятно мне 1* - как в _одну_ операцию присвоить значения _двум_ переменным способом, не зависящим от языка? XCHG - это конечно хорошо, но это только ассемблер и не на любом процессоре.

(Reply to this) (Thread)


[info]arvi
2008-02-10 10:51 am UTC (link)

В две строки — это интересно. Я умею лишь в три оператора (в первом переменные смешиваются, во втором-третьем расфасовываются). А 1* сложно именно потому, что через логику не пробовал.

(Reply to this) (Parent)(Thread)


[info]ramendik
2008-02-10 11:09 am UTC (link)
Да, тут спутал - не в две, а в три строки, забыл про расфасовку первой переменной.

Через логику те же три строки повторяются успешно, но даже в логике как ты присвоишь двум ячейкам памяти значение в одной операции? Разумеется без ассемблера и без C-specific вариантов.

(Reply to this) (Parent)

Дошло теперь!
[info]ramendik
2008-02-10 11:13 am UTC (link)
Дошло, что "одна операция" - это не "одна строка", а "один вид операции". Формулировку не так прочёл. В правильном прочтении формулировки решение тут же и нашлось.

(Reply to this) (Parent)(Thread)

Re: Дошло теперь!
[info]arvi
2008-02-10 11:15 am UTC (link)

Именно! Оператор это statement, а операция это operation.

Но задание со звёздочкой, конечно, предназначалось для самых опытных кандидатов. Фактически в конце 90-х я собирал людей, которые были вдали от Школы, но котором нравилась идея, что у хэкеров должна быть своя школа.

(Reply to this) (Parent)


[info]lesarexu
2008-07-11 10:25 am UTC (link)
Даны два возрастающих массива целых чисел x и y. Найти количество общих элементов в этих массивах (т.

(Reply to this) (Parent)


[info]ramendik
2008-02-10 01:45 am UTC (link)
Да, потерял я хватку в когда-то любимой теории чисел.

Надо бы проверить - верно ли, что существует не более одного магического квадрата с заданными обеими диагоналями. Если это так - перебор можно сократить весьма заметно (и автоматом отсечь отражения и повороты). Но проверить мне чего-то не удаётся. Нельзя ли хотя бы на твоей уже получившейся базе проверить? Просто если это по твоей базе кажется так - есть смысл искать доказательство, а нет - облом.

(Reply to this) (Thread)


[info]arvi
2008-02-10 10:55 am UTC (link)

Если это нужно для экспериментов, могу послать на email базу всех квадратов 4x4 и 20000 первых квадратов 5x5. Буду рад, если это даст результаты, позволяющие ускорить нахождение магических квадратов.

(Reply to this) (Parent)(Thread)


[info]ramendik
2008-02-10 11:14 am UTC (link)
А в каком они формате?

(Reply to this) (Parent)(Thread)


[info]arvi
2008-02-10 11:16 am UTC (link)

В текстовом, конечно. По строчке на квадрат. Должны даже из Бейсика читаться с помощью INPUT#, хотя пока не проверял.

(Reply to this) (Parent)(Thread)


[info]ramendik
2008-02-10 11:30 am UTC (link)
Тогда zip и шли. Мыло прежнее.

(Reply to this) (Parent)(Thread)


[info]arvi
2008-02-10 11:37 am UTC (link)

Хорошо. Сейчас убегаю на день рожденья. А вечером попытаюсь вспомнить мыло, и пошлю на него zip-архив.

(Reply to this) (Parent)


[info]ramendik
2008-02-10 11:40 am UTC (link)
Да, вышли, подалуйста, ещё и код твоей программы перебора. Хотя б паскаль вспомню, а то задача явно не для питона :)

(Reply to this) (Parent)(Thread)


[info]arvi
2008-02-10 05:46 pm UTC (link)

Всё, тексты отправил. Правильное мыло вспомнил? Программы пока не публикую, хочу дать другим неповторимую возможность начать с чистого листа. Позже мы сможем обогатить друг друга подходами и эвристиками, которые нашли независимо.

Питон хорош тем, что в условиях конкуренции заставит найти достойный алгоритм. Из этих соображений я специально сейчас не использую ассемблер, хотя задача целочисленная и типично ассемблерная.

(Reply to this) (Parent)(Thread)


[info]ramendik
2008-02-10 06:28 pm UTC (link)
Не, Питон по-моему это слишком, особенно если задача всё-таки тестировать brute force. Хотя и ассемблер не нужен - я бы сказал, что при современном компиляторе и правильном коде он бы и не должен давать преимущество. (Регистров на всё не хватит, а арифметику компилятор должен сделать хорошо).

(Reply to this) (Parent)(Thread)


[info]arvi
2008-02-10 06:54 pm UTC (link)

Если в алгоритме присутствует функция IsMagic(), окончательная проверка квадрата на магичность, ассемблер может её убыстрить. Такая проверка ложится в регистры. Более того, даже в кэш процессора. Возможно, что MMX-команды сделают её практически мгновенной.

Выигрыш по быстродействию умножается на число проверяемых квадратов.

(Reply to this) (Parent)(Thread)


[info]ramendik
2008-02-10 07:08 pm UTC (link)
А, понял. Но в моём предполагаемом алгоритме функция IsMagic() отсутствует. Если и строки, и столбцы, и диагонали относятся к моему списку последовательностей, и двух одинаковых чисел нет - а квадраты будут строитьься именно так - то квадрат уже магический.

(Reply to this) (Parent)


[info]ramendik
2008-02-10 12:15 pm UTC (link)
Я решил не заморачиваться доказательствами про диагонали. Я компьютерщик, а не математик, и в твоей постановке задачи мне интересно наиболее эффективно использовать современные увеличившиеся возможности по "brute force".

Я хочу использовать не только гигагерцы процессора, но и гигабайты ОЗУ. Вычислить все возможные последовательности, могущие быть строками, столбцами и диагоналями, настроить вокруг ещё кучу вспомогательных индексов и из результата строить квадраты. Заодно потребуется существенно меньше места для хранения результатов - каждый квадрат NxN будет храниться в виде N индексов, обозначающих номера его строк в уже построенной полной базе. Это и проблему вывода решает.

Задача-максимум пока что - взять да и вычислить все квадраты 5x5. И не за лет 70, а за N ночей. Возможно ли - пока не знаю.

(Reply to this) (Parent)(Thread)


[info]arvi
2008-02-10 06:01 pm UTC (link)

Кстати, идея блестящая! Вычислить всевозможные последовательности не потребует большого времени. Более того, их можно заранее залить в файл другой программой, экономя время отладки.

«Ключи» же, в случае 5x5, займут 25 бит (меньше машинного слова) и проверять две последовательности на совместимость можно будет простым AND'ом. Квадрат 10x10 потребует 13-байтных ключей, то есть несильно расширит 10-байтный буфер, отпущенный на запись последовательности. Вот диагональную совместимость, боюсь, придётся рассчитывать каждый раз заново, для каждого квадрата-кандидата. Кстати, чему там у нас равняется Цэ из ста по десять? :)

(Reply to this) (Parent)(Thread)


[info]ramendik
2008-02-10 06:25 pm UTC (link)
Про 25 бит понял, хотя на первом этапе я не буду так тщательно паковать. А вот про AND не понял. И про Цэ тоже не понял :)

(Reply to this) (Parent)(Thread)


[info]arvi
2008-02-10 06:43 pm UTC (link)

AND двух 25-битных ключей проверяет, есть ли в двух соответствующих последовательностях общие числа. Если биты 5 установлены и там, и там, значит число 5 присутствует в обоих и эти последовательности нельзя одновременно использовать в одном квадрате.

Возможно, я зря всё это говорю заранее. Но сам я этого алгоритма пока не реализовал.

C из n по k это количество наборов из n объектов (в случае чисел от 1 до 25 — n=25) по k (скажем, если в строчке пять клеточек — k=5).

(Reply to this) (Parent)


[info]ramendik
2008-02-10 06:30 pm UTC (link)
Зато вот всякими хэшами надо будет что ли заморочиться. Метод, который по ка что складывается, предполагает задачу типа "быстро найти все последовательности, у которых первые три числа такие-то" имеется в виду - когда база уже готова).

(Reply to this) (Parent)(Thread)


[info]arvi
2008-02-10 06:48 pm UTC (link)

Интересная идея, спасибо. Если заранее построить дерево последовательностей, это действительно может сильно сократить прямой перебор. Я пока не реализовал парочку своих эвристик, но эта в мой алгоритм ложится.

(Reply to this) (Parent)


[info]arvi
2008-02-10 06:37 pm UTC (link)

Как раз тут подкинули программу для вычисления C(n,k) на «Электронике МК-152». Благо она под рукой, есть возможность вычислить. Це из двадцати пяти по пять равно 53130, из ста по десять равно 1,7310309[4564]x1013.

Понятно, что последовательностей с заданной суммой будет намного меньше.

(Reply to this) (Parent)(Thread)


[info]ramendik
2008-02-10 07:15 pm UTC (link)
Всего-то 53130? Это меньше 65535. Количество с заданной суммой вряд ли меньше 255, поэтому уже не очень важно.

Всё, кажется задача 5x5 таки брутфорсится через недавно пришеший мне в голову "суперхэш", скоро прикину.

(Reply to this) (Parent)(Thread)


[info]arvi
2008-02-10 08:09 pm UTC (link)

Да, меньше. Чтож, буду постепенно дорабатывать свой перебор и ждать с нетерпением твою версию.

Ещё, кстати, цифрки. Математики обещают 275.305.224 магических квадратов 5x5, что при 87 символах на квадрат даёт конечный текстовый файл в 22Гб с хвостиком (в восемь раз больше, если учитывать повороты и отражения). Немного напрягает, но вполне доступно современной технике. Главное, хорошо жмётся! :-)

По квадратам 6x6 и более статистика пока неизвестна, здесь мы будем первыми.

(Reply to this) (Parent)


[info]ramendik
2008-02-10 07:38 pm UTC (link)
Так. По первым прикидкам всё довольно-таки интересно. База последовательностей занимает около 100 мегабайт, индекс, позволяющий мнгновенно находить все последовательности с такими-то первыми числами - ещё примерно столько же, т.е. всё это спокойненько живёт в ОЗУ.

Я ещё подумаю про оптимизацию алгоритма (но строго в рамках понятия brute force, т.е. без математического исследования задачи). И посмотрю, как это удастся реализовать. Если 5x5 и справду делается полным перебором за единицы-десятки часов на домашней машине - то на суперкомпьтере сделается 10x10. К тому же мой алгоритм параллелизируется просто "на раз" хоть на тыщу процессоров вообще без связи между ними (если ОЗУ не жалко всю базу и весь индекс копировать - но с учётом того, что они read only, можно их таки делать общими) и без сложности кодирования.

(Reply to this) (Thread)


[info]arvi
2008-02-10 08:00 pm UTC (link)
> Если 5x5 и справду делается полным перебором за единицы-десятки
> часов на домашней машине - то на суперкомпьтере сделается 10x10.

Я бы не был так уверен, когда речь идёт о Гамма-функции. :-) Здесь играет роль даже не экспонента, а факториал. Причём верхней границей является факториал квадрата числа! Всё-таки 100!≈10158, а это не шутки.

> параллелизируется просто "на раз" хоть на тыщу процессоров
> вообще без связи между ними

Это-то как раз очевидно. Но увеличение числа компьютеров даёт лишь линейный рост быстродействия.

(Reply to this) (Parent)


(34 comments) - (Post a new comment)

Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…