В игре Tetris есть 7 типов кирпичей или Tetr i minoes , которые математически известны как tetr o minoes, потому что все они сделаны с 4 квадратными сегментами:
Они имеют имена I, J, L, O, S, T и Z, которые соответствуют их приблизительным формам. С учетом поворотов на 90 ° в общей сложности насчитывается 19 уникальных фигур:
I
I
I
I
IIII
J
J
JJ
JJJ
J
JJ
J
J
J
JJJ
L
L
LL
L
LLL
LL
L
L
LLL
L
OO
OO
SS
SS
S
SS
S
TTT
T
T
TT
T
T
TTT
T
TT
T
ZZ
ZZ
Z
ZZ
Z
Вызов
Напишите прямоугольный блок кода, который действует как базовый сегмент, из которого сделаны эти 19 фигур. Когда этот код организован в одну из фигур, должна быть сформирована программа, которая выводит одну заглавную букву, связанную с этой формой. Это должно работать для всех 19 фигур.
Ведущие пустые области, присутствующие в некоторых из 19 фигур, полностью заполнены пробелами ( ). Конечные пустые области не заполнены ничем (поэтому программы не всегда точно прямоугольные).
пример
Предположим, это был ваш блок кода:
ABC
123
Тогда любое расположение блока в части S Tetris будет программой, которая печатает S
:
ABCABC
123123
ABCABC
123123
ABC
123
ABCABC
123123
ABC
123
(Обратите внимание, что все начальные пустые пробелы заполнены пробелами и что ни в одной строке нет пробелов.)
Та же самая идея относится ко всем 6 другим частям и их соответствующим вращениям.
Заметки
- Все 19 финальных программ должны выполняться на одном языке программирования.
- При желании вы можете добавить один завершающий символ новой строки во все программы (не только некоторые, все или ни одного).
- Ваш кодовый блок может содержать любые символы (включая пробелы), которые не являются символами конца строки .
- Выведите письмо на стандартный вывод (или ближайшую альтернативу вашего языка) с дополнительным завершающим переводом строки.
счет
Представление, кодовый блок которого имеет наименьшую площадь (ширину и высоту), выигрывает. По сути, это означает, что выигрывает самый короткий код, поэтому он помечен как code-golf . Tiebreaker идет на самый высокий голос .
ABC\n123
Пример имеет площадь 3 × 2 = 6.
отрывок
С учетом блока кода этот фрагмент сгенерирует все 19 программ:
<script>function drawShape(X,n,v){for(var t="",e=0;e<v.length;e++)for(var l=0;l<n.length;l++){for(var r=0;r<v[e].length;r++)t+="X"===v[e][r]?n[l]:X[l];t+="\n"}return t}function go(){var X=document.getElementById("input").value;if(0!=X.length){var n=X.replace(/./g," ").split("\n");X=X.split("\n");for(var v="I (v1):|I (v2):|J (v1):|J (v2):|J (v3):|J (v4):|L (v1):|L (v2):|L (v3):|L (v4):|O:|S (v1):|S (v2):|T (v1):|T (v2):|T (v3):|T (v4):|Z (v1):|Z (v2):".split("|"),t="X\nX\nX\nX|XXXX| X\n X\nXX|XXX\n X|XX\nX\nX|X\nXXX|X\nX\nXX| X\nXXX|XX\n X\n X|XXX\nX|XX\nXX| XX\nXX|X\nXX\n X|XXX\n X|X\nXX\nX| X\nXXX| X\nXX\n X|XX\n XX| X\nXX\nX".split("|"),e="",l=0;l<v.length;l++)e+=v[l]+"\n\n"+drawShape(n,X,t[l].split("\n"))+"\n";e=e.substring(0,e.length-2),document.getElementById("output").value=e}}</script><style>html *{font-family: monospace;}</style>Code Block:<br><textarea id='input' rows='8' cols='64'>ABC
123</textarea><br><button type='button' onclick='go()'>Go</button><br><br>All 19 Programs:<br><textarea id='output' rows='24' cols='64'></textarea>
источник
Ответы:
<> <(Рыба) - 12 * 32 = 384
Я планировал пойти на более элегантное решение, но я каким-то образом закончил с этим, что довольно грубо:
Это довольно просто, он проверяет код в квадрате 3x3 для текста и использует результаты, чтобы увидеть, какой тетримино соответствует форме кода. Я еще не приложил много усилий, чтобы сыграть в гольф.
Попробуйте код здесь (после использования фрагмента, чтобы придать ему форму тетримино)
Пример кода в форме Z (v1) здесь
источник
C (gcc) ,
26x20 = 52025x19 = 47523x17 = 391Недавно мне сообщили об атрибутах функций GNU и, что наиболее интересно, об
constructor
атрибуте, который позволяет более кратко реализовать то, что я делал, более окольным путем в моем более раннем подходе к этой проблеме.Суть идеи та же, что и раньше: создайте строку и найдите ее в списке, чтобы определить, в каком блоке тетриса выложен код. Это делается путем вызова функций, каждая из которых добавляет символ в строку. Осложнение было и остается, что количество функций варьируется.
Определение функции с помощью
attribute((constructor(x)))
делает так, чтобы функция запускалась до того,main()
как была введена, с необязательным,x
являющимся приоритетом (ниже означает, что она запускается раньше). Это устраняет необходимость в указателях функций, что позволяет нам удалять макрос, некоторые объявления и цепочку вызовов.Использование
__LINE__
для приоритета ненадежно, поскольку уровни приоритета 0-100 зарезервированы. Тем не менее, это не приводит к ошибкам, а только к предупреждениям, которых много в гольфе, так что еще?Это помогло бы сбрить еще один столбец, чтобы вообще не использовать приоритеты, но порядок выполнения, похоже, не определен. (В этом случае они меняются местами, но другие тесты не дают результатов.)
Пример L v2 здесь
Старый, более портативный, подход
Одна из моих любимых проблем, которую я решил на этом сайте.
Я начал с того, что подумал, что каждый блок будет как-то определять свои собственные координаты. С строками легко
__LINE__
работать, а количество горизонтально смежных блоков можно найти, используя длину строкового литерала, например, так:Возьмите длину полученной строки и разделите на правильное число, и вы получите ширину. К сожалению, этот метод невидит любое пустое пространство перед блоком. Я до сих пор подозреваемые строка будет решением, так как пробельные имеет смысл только вне строк очень редко, в таких вещах , как
a+++b
против прогнозаa+ ++b
. Я кратко обдумал что-то подобное, но не смог придумать ничего полезного. Другой возможностью было бы позволить идентификаторам «склеиваться» там, где встречались блоки:Я не удивлюсь, если это все еще может сделать интересное решение.
Несмотря на свою простоту, мне потребовалось довольно много времени, чтобы найти решение для строки, основанное на этом фрагменте блока:
Если фрагмент не имеет горизонтальных соседей, символ новой строки во второй строке экранируется обратной косой чертой, создавая строку длиной 2. Однако, если у него есть сосед, обратная косая черта вместо этого будет выходить из знака кавычки в начале строки. 2 следующего блока:
Это создаст строку "\" "длиной 5.
Что еще более важно, это также позволяет обнаруживать пустое пространство перед блоком:
Снова, новая строка экранируется, и пробел слева от пустого блока включается в результирующую строку "" длиной 6.
Всего в строке есть семь разных конфигураций блоков, о которых нам нужно беспокоиться, и все они создают строки уникальной длины:
Конечные блоки, конечно, не будут иметь такой короткой длины, но принцип будет одинаковым независимо от размера блока. Это также имеет преимущество в том, что отдельный механизм для определения ширины не нужен. Добавляя символ, соответствующий длине этой строки, в строку результатов, каждая из 19 конфигураций дает уникальную строку, которую нужно сравнивать только с подходящим списком после запуска всех блоков.
Как только это было отсортировано, следующая большая проблема заключалась в том, как «посетить» каждый ряд блоков. В C мы очень ограничены тем, что можно сделать вне функций. Нам тоже нужно
main()
появиться, но только один раз. Последнее легко достигается некоторыми#define
s, но если мы хотим, чтобы код последующих блоков был внутриmain()
, проблема в том, как узнать, когда ставить заключительную закрывающую фигурную скобку. В конце концов, мы не знаем, сколько строк блоков будет фактически использовано. Таким образом, мы должны бытьmain()
статичными, а остальное - динамичным.Если другие блочные строки должны быть автономными, они должны быть функциями, но мы должны убедиться, что каждая функция имеет уникальное имя, а также достаточно предсказуемое, чтобы его можно было вызывать
main()
. Нам также нужен механизм для того, чтобы знать, какие функции на самом деле должны быть вызваны. Генерация уникальных имен решается с помощью вспомогательных макросов:Вызов
F
создаст идентификатор, имя которого начинается с f и заканчивается номером строки.A
делает то же самое, но с префиксом as, который используется для второй части решения - указателей на функции. Мы объявляем четыре таких указателя:Поскольку они объявлены как глобальные переменные, для них удобно установить значение NULL. Позже каждый блок-ряд будет иметь следующий фрагмент кода:
Сначала будет объявлена функция, определен соответствующий указатель на функцию для указания на эту функцию (мы можем определить глобальные переменные только один раз, но более раннее объявление не считается как определение, даже если оно инициализировалось в NULL), а затем определим фактическую функция. Это позволяет
main()
вызывать любой указатель на функцию, который не равен NULL (a17 никогда не будет NULL):В результате будет построена строка
r
, которую затем ищут в таблице строк, и, если она найдена, выводится соответствующая буква.Единственная оставшаяся хитрость заключается в том, что список строк для сравнения сокращался всякий раз, когда можно было избежать неоднозначности или можно было бы совмещать перекрывающиеся строки.
Пример L v2 здесь
источник
код операции x86 (.com),
8682 байтаTester:
Источник:
Запустите в win7dos, где init AX = 0, SI = 100, BX = 0 Ссылки
источник
mov bx, 100h
в начале.