Программирование игр и головоломок - [12]

Шрифт
Интервал

делится на p, то наибольший общий делитель (НОД) чисел a>i+pa>i и n отличен от 1[9].

Построим последовательность Полларда для n = 22879:

a>1 = 2

a>2 = 3

a>3 = 8

a>4 = 63

a>5 = 3968

a>6 = 4271

a>7 = 6877

a>8 = 2235

a>9 = 7602

a>10 = 20928

a>11 = 8486

a>12 = 11982

НОД чисел a>12a>4 и n = 22879 есть 137, делитель числа n.

Если мы способны сказать, становится ли данная последовательность периодической (головоломка 1), то мы располагаем быстрым методом определения, имеет ли данное число делитель. Можете играть. Это не такая уж простая программа…

Есть тест на простоту числа, основанный на так называемой малой теореме Ферма: если n — простое, причем число n не является делителем a, то

a>n−1 = 1 по модулю n.

Представим n в виде n = 2>sm + 1. Назовем число n сильно псевдопростым по основанию a, если выполнено одно из следующих двух условий:

либо a>m = 1 по модулю n,

либо a>m2r = n − 1 по модулю n = 2>sm + 1 для некоторого r, 0 ≤ r < s.

Очень мало сильно псевдопростых чисел, не являющихся простыми; так

2047 = 23 * 89 — сильно псевдопросто по основанию 2,

1373653 = 829 * 1657 — по основанию 2 и 3,

25326001 = 2251 * 11251 — по основанию 2, 3 и 5,

3215031751 = 151 * 751 * 28351 — по основанию 2, 3, 5 и 7.

Метод интересен, потому что a>n вычисляется за время, растущее не быстрее, чем ln n. Это утверждение вытекает из соотношений:

а>0 = 1, а>1 = а,

a>2n = (а * а)>n, a>2n+1 = (a * a)>n * а.

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

Кстати: знаете ли вы две универсальные конструкции в информатике? Первая — «известно, что…». Вторая — «это и нужно сделать…».

Таинственные программы

Я надеялся не приводить в этой книге никаких готовых программ. Программирую не я, а вы. И я не очень люблю смотреть, как подростки копируют программу, набирая ее на клавиатуре и при этом не отдавая себе отчета в том, что она делает и как устроена. Но сказать, что делает та или иная программа, может оказаться настоящей головоломкой, Программы, которые мы будем обсуждать, написаны на некотором воображаемом языке[10]. Вам придется по крайней мере сделать усилие, чтобы перевести их на ваш обычный язык: Бейсик, LSE или Паскаль. Условная команда записывается в виде

>ЕСЛИ условие ТО последовательность команд

>КОНЕЦ_ЕСЛИ

(последовательность команд выполняется тогда и только тогда, когда условие истинно)

или

>ЕСЛИ условие ТО последовательность команд

>  ИНАЧЕ последовательность команд

>КОНЕЦ_ЕСЛИ

(если условие истинно, то выполняется последовательность команд, заключенная между ТО и ИНАЧЕ, в противном случае выполняется та последовательность команд, которая расположена между ИНАЧЕ и КОНЕЦ_ЕСЛИ).

В обоих случаях КОНЕЦ_ЕСЛИ играет роль закрывающей скобки, связанной с открывающей скобкой ЕСЛИ. Мы будем использовать цикл

>ПОКА условие ВЫПОЛНЯТЬ

>  последовательность команд

>ВЕРНУТЬСЯ

Последовательность команд, содержащаяся между ВЫПОЛНЯТЬ и ВЕРНУТЬСЯ, повторяется, ПОКА условие истинно.

* Головоломка 17. Для забавы. Вот легко понимаемая программа. Здесь n и b — два натуральных числа и b нечетно (это существенно)

>ПРОЧЕСТЬ n, b

>ПОКА n > b ВЫПОЛНЯТЬ

>  ЕСЛИ n четно ТО n := n/2

>  ИНАЧЕ n := nb

>  КОНЕЦ_ЕСЛИ

>ВЕРНУТЬСЯ

>СООБЩИТЬ ЕСЛИ n = 0 ТО 'ДА'

>ИНАЧЕ 'НЕТ' КОНЕЦ_ЕСЛИ

Вы можете попробовать выполнить ее вручную для

n = 2>77 − 3, b = 7.

Забавно, не правда ли? Несмотря на свою исключительную» простоту, эта программа, кажется, новая…

*** Головоломка 18. Посерьезнее. Эта — несомненно более трудная. И тоже неопубликованная. Боюсь, что вы можете избаловаться… На вход программы подается n — нечетное натуральное число.

>ПРОЧЕСТЬ n

>q := (n − 1)/4; p := целая_часть (q)

>ЕСЛИ qp ТО СООБЩИТЬ 'НЕТ';

>КОНЕЦ_РАБОТЫ КОНЕЦ ЕСЛИ

>ЕСЛИ нечетное p ТО СООБЩИТЬ 'НЕТ';

>КОНЕЦ_РАБОТЫ КОНЕЦ_ЕСЛИ

>a := 4; b := 1

>ПОКА p ≥ a ВЫПОЛНЯТЬ

>p := p/2

>ЕСЛИ нечетное p ТО p := pa/2 − b;

>b := ab КОНЕЦ ЕСЛИ a := a + a ВЕРНУТЬСЯ

>ЕСЛИ p = 0 ТО СООБЩИТЬ b;

>КОНЕЦ РАБОТЫ КОНЕЦ_ЕСЛИ

>ЕСЛИ p + 2*b = a ТО СООБЩИТЬ ab;

>КОНЕЦ РАБОТЫ КОНЕЦ_ЕСЛИ

>ЕСЛИ p = 4 * (ab) ТО СООБЩИТЬ 2 * ab;

>КОНЕЦ РАБОТЫ КОНЕЦ_ЕСЛИ

>СООБЩИТЬ 'НЕТ'; КОНЕЦ_РАБОТЫ

Я не запрещаю вам перевести эту программу на ваш любимый язык, а затем испытать ее для различных значений n. Есть маленький шанс, что вы угадаете, на что она способна. Это не очевидно!

** Головоломка 19. Вклад Жака Гебенстрейта. Я обязан Жаку Гебенстрейту следующей программой. Она была предложена в том виде, в каком я ее привожу, без какого-либо комментария (это было сделано без злого умысла с его стороны: сам он получил не больше от того, кто дал ему эту программу).

>ПРОЧЕСТЬ a, b; p : = max (a, b); q := min (a, b)

>ПОКА q > eps ВЫПОЛНЯТЬ

>  r := (q/p)²; s := r/(r + 4)

>  p := (2 * s + 1) * p; q := s * q

>ВЕРНУТЬСЯ

>результат := p

Как вам кажется, что вычисляет эта программа?

3. Игры без стратегии

Общие предложения

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


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.