Duodyadic тайлы - это разновидности квадратных функциональных блоков, которые принимают два входа, один с их верхней стороны и один с их левой стороны, и имеют два выхода, один с правой стороны и один с нижней стороны. Каждый из их выходов является отдельной функцией обоих их входов.
Например, если #
представляет собой общую плитку, правый выход R
является функцией f
входов T
и L
, а нижний выход B
другой функции g
от T
и L
:
T
L#R R = f(T, L)
B B = g(T, L)
(Плитки называются «дуэт», поскольку есть две функции, и «двоичный», поскольку обе функции имеют два аргумента .)
Плитки могут затем быть собраны вместе в сетке, выходы одной плитки идут непосредственно на входы соседних плиток. Вот, например, правый вывод левого #
переходит в левый ввод правого #
:
AB D = f(f(A, C), B)
C##D E = g(A, C)
EF F = g(f(A, C), B)
Вы можете себе представить, что при наличии набора двенадцатиперстных плиток, каждая из которых имеет определенную функциональность, могут быть созданы сложные (и потенциально полезные) композиции.
В этой задаче мы будем интересоваться только традиционным набором из двенадцати логически-ориентированных мозаичных элементов, где все входы и выходы являются однобитовыми двоичными числами (нулями или единицами). Мы будем использовать отдельный символ ASCII для обозначения каждого типа плитки.
Плитка символов и их отношения ввода-вывода являются следующими:
( T
для верхнего ввода, L
для левого ввода, R
для правого вывода, B
для нижнего вывода.)
- Ноль:
0
или(пробел) →
R = 0
,B = 0
- Один:
1
→R = 1
,B = 1
- Крест:
+
→R = L
,B = T
- Зеркало:
\
→R = T
,B = L
- Только сверху:
U
→R = T
,B = T
- Осталось только:
)
→R = L
,B = L
- Не:
!
→R = not L
,B = not T
- И:
&
→R = L and T
,B = L and T
- Или:
|
→R = L or T
,B = L or T
- Xor:
^
→R = L xor T
,B = L xor T
Вызов
Напишите программу или функцию, которая принимает прямоугольную сетку символов, 0 1+\U)!&|^
которая представляет собой «схему», созданную с использованием десяти логических основанных на дуодиках плиток. Вам также нужно взять две строки 0
's 1
' и 's'; один будет левым входным столбцом, а второй - верхней строкой ввода. Ваша программа / функция должна напечатать / вернуть нижний выходной ряд и правый выходной столбец (также в 0
's 1
' и 's).
Например, в этой сетке
+++
+++
все входы текут прямо через сетку к выходам
ABC
D+++D
E+++E
ABC
поэтому вход 010
/ 01
будет иметь выход 010
/ 01
:
010
0+++0
1+++1
010
Точный вывод вашей программы будет [bottom output row]\n[right output column]
или [bottom output row]/[right output column]
:
010
01
или
010/01
Если вы написали функцию, вы могли бы вернуть две строки в кортеже или списке (или все равно вывести их).
Детали
- Возьмите три ввода как строки любым приемлемым способом (предпочтительно в сетке порядка, в верхней строке, в левом столбце): командная строка, текстовый файл, sdtin, функция arg.
- Можно предположить, что длина входных строк и столбцов будет соответствовать размерам сетки и будет содержать только
0
«и1
». - Ваша сетка должна использовать правильные символы (
0 1+\U)!&|^
). Помните об этом0
изначите одно и то же.
Тестовые случаи
(Прочтите I / O как top
/ left
→ bottom
/ right
.)
Nand:
&!
00
/ 0
→ 01
/ 1
00
/ 1
→ 01
/ 1
10
/ 0
→ 01
/ 1
10
/ 1
→ 11
/0
Все:
1111
1\+\
1+\+
1\+\
Любой ввод должен привести к 1111
/ 1111
.
Xor от Nand: (обратите внимание на колонку конечных пробелов)
\)+\
U&!&
+! !
\&!&
!
00000
/ 00000
→ 00000
/ 00000
00000
/ 10000
→ 00010
/ 00000
10000
/ 00000
→ 00010
/ 00000
10000
/ 10000
→ 00000
/00000
Зигзаг:
+++\00000000
000\!!!!\000
00000000\+++
Первый бит левого входа становится последним битом правого выхода. Все остальное есть 0
.
000000000000
/ 000
→ 000000000000
/ 000
000000000000
/ 100
→ 000000000000
/001
Распространение:
)))
UUU
U+U
U+U
UUU
Первый бит левого входа поступает на все выходы.
000
/ 00000
→ 000
/ 00000
000
/ 10000
→ 111
/11111
Вот пастбина из всех тестовых случаев 1 × 1 сетки.
счет
Самая короткая подача в байтах побеждает.
Бонус: Какие крутые "схемы" вы можете сделать?
PS Не утруждайте себя поиском "двенадцатиперстной плитки". Я придумал их вчера; D
Если вы хотите обсудить расширение этой идеи на полноценный язык программирования, заходите в этот чат .
источник
Ответы:
Пиф, 122
Вид монстра. Использует просто рекурсию, ничего необычного, как динамическое программирование.
Онлайн демонстрация .
Ввод осуществляется следующим образом: сначала сетка (без экранирования, без дополнительных символов), а затем две строки ввода, например (зигзаг)
источник
Mathematica,
331276270267264262252250 байтовЭто
Unicode-символ для частного использования, который Mathematica использует в качестве надстрочного индексаT
, т.е. это оператор транспонирования.Вот более читаемая версия:
Это безымянная функция, которая принимает три строки для сетки, верхний и левый входы и печатает нижний и правый выходы.
объяснение
Давайте пройдем этот шаг за шагом (я постараюсь не предполагать никаких знаний Mathematica). Вы вроде как должны прочитать код обратно на фронт. Базовый алгоритм просто просматривает строки, вычисляя каждую функцию и сохраняя результаты
f
для последующего доступа к ним.Обработка ввода
Вот это немного:
Это просто разбивает сетку на вложенный список символов (обратите внимание, что я определил
h
в качестве псевдонимаCharacter
где-то в коде), а затем добавляет строку и столбец с входными данными. Это работает, потому что1
0
они также являются именами плиток с постоянными функциями, так что фактическое их размещение имеет тот же эффект и ввод входных данных вручную. Поскольку эти функции являются технически, они будут получать свой вклад извне сетки, но, поскольку они являются постоянными функциями, это не имеет значения. Верхний левый угол получает,0
но это довольно произвольно, так как результаты этой плитки никогда не используются.Также обратите внимание на транспонирование. Добавление столбцов занимает больше символов, чем добавление строк, поэтому я переставляю сетку после добавления верхней строки. Это означает, что сверху / снизу и слева / справа меняются местами основные части программы, но они полностью заменяемы, поэтому это не имеет значения. Мне просто нужно убедиться, что результаты возвращены в правильном порядке.
Решение сетки
(Этот раздел немного устарел. Будет исправлено, когда я действительно буду уверен, что закончил играть в гольф.)
Далее мы
MapIndexed
перебираем внутренний уровень этого вложенного списка. Это вызывает анонимную функцию, предоставленную в качестве первого аргумента для каждого символа в сетке, а также дает ей список с текущими двумя координатами. Сетка пересекается по порядку, поэтому мы можем безопасно рассчитать каждую ячейку на основе предыдущих.Мы используем переменные
r
(ight) иb
(ottom) в качестве таблиц поиска для результатов каждой ячейки. Наша анонимная функция имеет текущие координаты#2
, поэтому мы получаем входные данные для любой ячейки сОбратите внимание, что в первой строке и столбце будут доступны неопределенные значения
r
иb
. Mathematica на самом деле не имеет проблем с этим и просто вернет вам ваши координаты, но мы все равно откажемся от этого результата, поскольку все плитки в этой строке / столбце являются постоянными функциями.Теперь эта вещь:
Это гольф-форма
Которая, в свою очередь, является функцией, которая с учетом двух входов мозаики возвращает Ассоциацию (вы бы назвали ее хэш-картой или таблицей на других языках), которая содержит все возможные результаты мозаики для этих двух входов. Чтобы понять, как реализованы все функции, вам нужно знать, что к первому аргументу такой функции можно получить доступ,
#
а ко второму -#2
. Кроме того,##
дает вам последовательность обоих аргументов, которые можно использовать для "сплат" аргументов.0
: это просто, мы просто возвращаем константу{0, 0}
и также назначаем ееz
для использования в будущем (например, в космическом тайле).1
: по сути справедливо{1,1}
, но сz
этим сокращается до1+z
. Мы также сохраняем этоo
, потому что это пригодится для всех тайлов, где оба выхода идентичны.+
: Здесь мы используем последовательность.{##}
так же, как{#,#2}
и пропускает оба входа без изменений.\
Мы поменяем два аргумента{#2,#}
.U
Теперь мы можем использоватьo
.o#2
означает,{1,1}*#2
что мы просто помещаем верхний аргумент в оба вывода.)
Аналогично для левого аргументаo#
.!
: Побитовое не раздражает в Mathematica, но так как мы только когда - либо ,0
и1
мы можем просто вычесть оба входа из1
(таким образом , переворачивая их) и передать их на:1-{##}
.&
Это довольно изящно. Сначала мы заметим, что поразрядно и для0
и1
идентично умножению. Кроме того, такo##
же, какo*#*#2
.|
: Опять же, мы используем эквивалентную функцию. Побитовый или такой же, какMax
в этом случае, поэтому мы применяемMax
к входным аргументам и умножаем результат на{1,1}
.^
: Самое короткое, что я нашел для xor - это взять разницу и возвести ее в квадрат (для обеспечения позитивности), так что мы получилиo(#-#2)^2
.После завершения этой функции и возврата полной ассоциации мы используем символ текущей ячейки, чтобы извлечь интересующий нас элемент и сохранить его в
r
иb
. Обратите внимание, что это также возвращаемое значение анонимной функции, используемой вMapIndexed
, поэтому отображение фактически даст мне сетку всех результатов.Обработка вывода
MapIndexed
возвращает трехмерную сетку, где первое измерение соответствует горизонтальной координате сетки (запомните предыдущее преобразование), второе измерение соответствует вертикальной координате сетки, а третье указывает, есть ли у нас нижний или левый вывод. Обратите внимание, что это также содержит строку ввода и столбец, от которого нам нужно избавиться. Таким образом, мы получаем доступ к нижнему выводу нижнего ряда с помощьюи последний вывод правой колонки с
Обратите внимание, что
2;;
это диапазон от второго до последнего элемента.Наконец, мы применяем
Print
к обоим из них (используя@@@
в качестве синтаксического сахара для второго уровняApply
), который просто печатает все свои аргументы вплотную (и поскольку он применяется к двум отдельным выражениям, между нижней и нижней строкой будет новая строка) правильный вывод).источник
C
332309272270266259247225 байтПосмотреть результаты онлайн здесь!
Это определяет функцию
void f(char*, char*, char*)
, которая должна принимать плату в качестве первого входа, затем верхний ряд ввода, а затем левый ряд ввода.Вот что я использовал для проверки:
Таким образом, введя 2-битный множитель Sp3000:
Мы получаем:
С другой стороны, учитывая наполовину сумматор Sp3000, я бы хотел увидеть полный сумматор ...Один из вас, ребята, сделал это! Я не думаю, что система стоит сама по себе как язык программирования, но это было очень интересно. Это похоже на отличную цель для метагольфа, хотя!Краткое объяснение:
Вот развернутый, прокомментированный код:
Мы перебираем
c
, слева направо (затем сверху вниз),t
каждый раз перезаписывая входные данные и выталкивая самый правый выход, который помещается вl
строку. Мы можем представить себе это , как заменить верхний рядc
с1
«s и0
» S итеративно и отслеживание битов, которые выталкиваются справа.Вот более визуальная последовательность строка за строкой:
Это очевидно усложняется с разными символами и размерами, но основная идея верна. Это работает только потому, что данные никогда не перемещаются вверх или влево.
источник
f
наf(c,t,l)char*c,*t,*l
(не беспокойтесь о типе возвращаемого значения).f(c,t,l)char*c,*t,*l;
. Не компилируйте в режиме C11, так как неявное правило int, которое позволяет нам отбрасывать возвращаемый тип, было удалено в этой ревизии.*l
? Он компилируется в режиме C99 на моей машине.Python 2, 316 байт
Эта функция строит 10 лямбда-функций тайла, затем выполняет итерации по сетке, обновляя логические состояния. Окончательные вертикальные и горизонтальные логические состояния затем печатаются.
Нежелательный код, включая тесты:
test.txt
Файл ( в том числе 2 других тестов по Sp3000):Тестовый вывод:
источник
Python 2,
384338325 байтСерьезно, CH, если это уже не игрушка, вы должны начать обзванивать некоторые фабрики игрушек.
Больше играли в гольф и намного менее эффективны сейчас, но все еще не догнали CarpetPython. Входные данные
f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010")
, выходные данные - это кортеж из двух строк. Убедитесь, что на доске нет завершающего символа новой строки, который сломает вещи.Тестовая программа
Вы также можете проверить все возможные случаи с
test_all()
.Дополнительные тестовые случаи
Половина сумматора
Вот половинный сумматор, который добавляет верхние левые биты, выводя
<input bit> <carry> <sum>
:тесты:
Выход должен быть одинаковым, даже если второй / третий биты входов изменены.
Сдвиг вправо
Учитывая
abc / def
, это выводыfab / cde
:тесты:
3-битный сортировщик
Сортирует первые три бита сверху в последние три бита снизу. Правильный вывод - мусор.
тесты:
2-битный на 2-битный множитель
Принимает 1-й / 2-й бит вершины в качестве первого числа и 3-й / 4-й бит вершины в качестве второго числа. Выходы на последние четыре бита снизу. Правильный вывод - мусор.
Изменить: Гольф из колонки и двух рядов.
тесты:
источник
R
524517Вероятно, сейчас есть много возможностей, чтобы уменьшить это, но это было действительно интересно сделать. Есть две функции. Функция d является рабочим, а f является компаратором.
Функция d вызывается с 3 строками, Gates, Top и Left. Ворота помещаются в матрицу, определяемую шириной.
Немного отформатирован
Некоторые тесты
источник