Задний план
Пифагорейский треугольник - это прямоугольный треугольник, где длина каждой стороны является целым числом (то есть длина стороны образует тройку Пифагора ):
Используя стороны этого треугольника, мы можем прикрепить еще два неконгруэнтных пифагорейских треугольника следующим образом:
Мы можем продолжить эту схему по своему усмотрению, если только два треугольника не перекрываются, а соединительные стороны имеют одинаковую длину:
Вопрос в том, сколько неконгруэнтных пифагорейских треугольников мы можем разместить в данном пространстве?
Вход
В качестве входных данных вы получите два целых числа, W
а H
через аргументы функции - STDIN, строки или что угодно. Целые числа могут быть получены как десятичные, шестнадцатеричные, двоичные, унарные (удачи, Retina ) или любое другое целочисленное основание. Вы можете предположить, чтоmax(W, H) <= 2^15 - 1
.
Выход
Ваша программа или функция должна рассчитать список непересекающихся связанных неконгруэнтных пифагорейских треугольников и вывести список наборов по три координаты каждый, где координаты в наборе образуют один из пифагорейских треугольников при соединении линиями. Координаты должны быть действительными числами в нашем пространстве ( x
должны быть в интервале [0, W]
и y
должны быть в интервале[0, H]
), а расстояние должно быть точным с точностью до станка. Порядок треугольников и точный формат каждой координаты не важен.
Должна быть возможность «идти» от одного треугольника к любому другому, только переступая через связанные границы.
Используя приведенную выше диаграмму в качестве примера, позвольте нашему вводу быть W = 60
,H = 60
.
Наш результат может быть следующим списком координат:
(0, 15), (0, 21), (8, 15)
(0, 21), (14.4, 40.2), (8, 15)
(0, 15), (8, 0), (8, 15)
(8, 0), (8, 15), (28, 15)
(8, 15), (28, 15), (28, 36)
(28, 15), (28, 36), (56, 36)
Теперь 6 треугольников, безусловно, не лучшее, что мы можем сделать, учитывая наше пространство. Вы можете сделать лучше?
Правила и оценки
Ваша оценка за это испытание - это количество треугольников, которые ваша программа генерирует с учетом ввода
W = 1000, H = 1000
. Я оставляю за собой право изменить этот ввод, если я подозреваю, что кто-то жестко запрограммировал этот случай.Вы не можете использовать встроенные функции, которые вычисляют пифагорейские тройки, и вы не можете жестко закодировать список из более чем двух пифагорейских троек (если вы жестко закодировали свою программу, чтобы всегда начинаться с (3, 4, 5) треугольника, или какого-либо подобного начального обстоятельства, что хорошо).
Вы можете написать свою заявку на любом языке. Читаемость и комментирование приветствуются.
Вы можете найти список пифагорейских троек здесь .
Стандартные лазейки запрещены.
источник
Ответы:
Python 3, 109
Это был, конечно, обманчиво сложный вызов. Много раз я писал код, в котором я сомневался в своих базовых геометрических способностях. При этом я очень доволен результатом. Я не прикладывал усилий к тому, чтобы придумать сложный алгоритм размещения треугольников, и вместо этого мой код просто промахивается, всегда размещая наименьшее, которое он может найти. Я надеюсь, что смогу улучшить это позже, или мой ответ будет отвергать других, чтобы найти лучший алгоритм! В общем, очень веселая проблема, и она дает несколько интересных картинок.
Вот код:
Вот график вывода для
W = 1000
иH = 1000
с 109 треугольниками:Вот
W = 10000
иH = 10000
с 724 треугольниками:Вызовите
matplotlib_graph()
функцию после,build_all_triangles()
чтобы построить график треугольников.Я думаю, что код работает достаточно быстро: на
W = 1000
иH = 1000
это занимает 0,66 секунды, а наW = 10000
иH = 10000
это занимает 45 секунд, используя мой дерьмовый ноутбук.источник
С ++, 146 треугольников (часть 1/2)
Результат как изображение
Описание алгоритма
При этом используется поиск в ширину пространства решений. На каждом этапе он начинается со всех уникальных конфигураций
k
треугольников, которые вписываются в коробку, и создает все уникальные конфигурацииk + 1
треугольников, перечисляя все варианты добавления неиспользуемого треугольника в любую из конфигураций.Алгоритм в основном настроен на поиск абсолютного максимума с исчерпывающей BFS. И это делает это успешно для меньших размеров. Например, для ящика 50x50 он находит максимум примерно за 1 минуту. Но для 1000x1000 пространство для решения слишком велико. Чтобы это прекратилось, я урезаю список решений после каждого шага. Количество сохраняемых решений задается аргументом командной строки. Для вышеуказанного решения было использовано значение 50. Это привело к продолжительности работы около 10 минут.
Схема основных шагов выглядит следующим образом:
Одним из важнейших аспектов всей схемы является то, что конфигурации обычно создаются несколько раз, и нас интересуют только уникальные конфигурации. Таким образом, нам нужен уникальный ключ, который определяет решение, которое должно быть независимым от порядка треугольников, используемых при создании решения. Например, использование координат для ключа не будет работать вообще, поскольку они могут быть совершенно разными, если мы пришли к одному решению в нескольких заказах. Я использовал набор индексов треугольников в глобальном списке, а также набор объектов «соединителей», которые определяют, как соединяются треугольники. Таким образом, ключ кодирует только топологию, независимо от порядка построения и положения в 2D-пространстве.
В то время как больше аспект реализации, другая часть, которая не совсем тривиальна, решает, вписывается ли и как все это в данную коробку. Если вы действительно хотите раздвинуть границы, очевидно, необходимо, чтобы вращение вписывалось в рамку.
Я постараюсь добавить некоторые комментарии к коду в части 2 позже, на случай, если кто-то захочет погрузиться в детали того, как все это работает.
Результат в официальном текстовом формате
Код
Смотрите часть 2 для кода. Это было разбито на 2 части, чтобы обойти ограничения размера поста.
Код также доступен на PasteBin .
источник
C ++, 146 треугольников (часть 2/2)
Продолжение с части 1. Это было разбито на 2 части, чтобы обойти ограничения размера поста.
Код
Комментарии будут добавлены.
источник