Цифровая логика на основе сетки (Duodyadic Tiles)


33

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для нижнего вывода.)

  1. Ноль: 0или (пробел) → R = 0,B = 0
  2. Один: 1R = 1,B = 1
  3. Крест: +R = L,B = T
  4. Зеркало: \R = T,B = L
  5. Только сверху: UR = T,B = T
  6. Осталось только: )R = L,B = L
  7. Не: !R = not L,B = not T
  8. И: &R = L and T,B = L and T
  9. Или: |R = L or T,B = L or T
  10. 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/ leftbottom/ right.)

Nand:

&!

00/ 001/ 1
00/ 101/ 1
10/ 001/ 1
10/ 111/0

Все:

1111
1\+\
1+\+
1\+\

Любой ввод должен привести к 1111/ 1111.

Xor от Nand: (обратите внимание на колонку конечных пробелов)

\)+\ 
U&!& 
+! ! 
\&!& 
   ! 

00000/ 0000000000/ 00000
00000/ 1000000010/ 00000
10000/ 0000000010/ 00000
10000/ 1000000000/00000

Зигзаг:

+++\00000000
000\!!!!\000
00000000\+++

Первый бит левого входа становится последним битом правого выхода. Все остальное есть 0.

000000000000/ 000000000000000/ 000
000000000000/ 100000000000000/001

Распространение:

)))
UUU
U+U
U+U
UUU

Первый бит левого входа поступает на все выходы.

000/ 00000000/ 00000
000/ 10000111/11111

Вот пастбина из всех тестовых случаев 1 × 1 сетки.

счет

Самая короткая подача в байтах побеждает.

Бонус: Какие крутые "схемы" вы можете сделать?

PS Не утруждайте себя поиском "двенадцатиперстной плитки". Я придумал их вчера; D
Если вы хотите обсудить расширение этой идеи на полноценный язык программирования, заходите в этот чат .


11
+1 за крутой вызов, но еще и потому, что вы изобрели плитки с дуодьядами, которые ДЕЙСТВИТЕЛЬНО круты.
Алекс А.

3
+1 Это действительно бесполезно гуглить это: goo.gl/zuqfdW . Отличный вызов!
BrainSteel

Я с ними. Меня гораздо больше интересуют ваши плитки в качестве языка программирования, чем в этом конкретном соревновании по гольфу. PS: есть 16 возможных плиток, поэтому придумывать буквы / имена для остальных шести было бы аккуратно.
Спарр

Было бы интересно иметь блоки, которые выводят / вводят с разных направлений, потому что иначе вы не сможете сделать защелку, поскольку все течет в направлении вниз-вправо.
Sp3000

2
Вы можете изменить T / B на U (p) / D (собственный), чтобы мы могли иметь F / B аналогично нотации Кубика Рубика, а затем. , , тритриадические кубики?
Сохам Чоудхури

Ответы:


8

Пиф, 122

Вид монстра. Использует просто рекурсию, ничего необычного, как динамическое программирование.

D:NGHR@Cm+d[1HG&GH|GHxGH0),[GH!G)[HG!H)x"+\\!1U)&|^"N#aYw)M:@@YGH?hgGtHHv@eYG?egtGHGv@ePYHjkm+0egtleYklePYjkm+0hgbtlePYleY

Онлайн демонстрация .

Ввод осуществляется следующим образом: сначала сетка (без экранирования, без дополнительных символов), а затем две строки ввода, например (зигзаг)

+++\00000000
000\!!!!\000
00000000\+++
000000000000
100

8

Mathematica, 331 276 270 267 264 262 252 250 байтов

Print@@@{#[[2;;,-1,2]],#[[-1,2;;,1]]}&@MapIndexed[h=Characters;({r@#2,b@#2}=<|##|>&@@Thread[h@"0 1+\\)U!&|^"->{0,0,1,i={##},{#2,#},##,1-i,1##,Max@i,(#-#2)^2}]&[r[#2-{1,0}],b[#2-{0,1}]]@#{1,1})&,Join[h@{"0"<>#3},h@StringSplit[#2<>"
"<>#,"
"]],{2}]&

Это Unicode-символ для частного использования, который Mathematica использует в качестве надстрочного индекса T, т.е. это оператор транспонирования.

Вот более читаемая версия:

Print @@@ {#[[2 ;;, -1, 2]], #[[-1, 2 ;;, 1]]} &@
  MapIndexed[h = Characters;
   (
     {r@#2, b@#2} = <|##|> & @@ Thread[
            h@"0 1+\\)U!&|^" -> {
              0,
              0,
              1,
              i = {##},
              {#2, #},
              ##,
              1 - i,
              1 ##,
              Max@i,
              (# - #2)^2
              }] & [
          r[#2 - {1, 0}],
          b[#2 - {0, 1}]
          ] @ # {1, 1}
     ) &,
   Join[
    h@{"0" <> #3},
    h@StringSplit[#2 <> "\n" <> #, "\n"]\[Transpose]
   ],
   {2}] &

Это безымянная функция, которая принимает три строки для сетки, верхний и левый входы и печатает нижний и правый выходы.

объяснение

Давайте пройдем этот шаг за шагом (я постараюсь не предполагать никаких знаний Mathematica). Вы вроде как должны прочитать код обратно на фронт. Базовый алгоритм просто просматривает строки, вычисляя каждую функцию и сохраняя результаты fдля последующего доступа к ним.

Обработка ввода

Вот это немного:

Join[
  h@{"0" <> #3},
  h@StringSplit[#2 <> "\n" <> #, "\n"]\[Transpose]
]

Это просто разбивает сетку на вложенный список символов (обратите внимание, что я определил hв качестве псевдонима Characterгде-то в коде), а затем добавляет строку и столбец с входными данными. Это работает, потому что10 они также являются именами плиток с постоянными функциями, так что фактическое их размещение имеет тот же эффект и ввод входных данных вручную. Поскольку эти функции являются технически, они будут получать свой вклад извне сетки, но, поскольку они являются постоянными функциями, это не имеет значения. Верхний левый угол получает, 0но это довольно произвольно, так как результаты этой плитки никогда не используются.

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

Решение сетки

(Этот раздел немного устарел. Будет исправлено, когда я действительно буду уверен, что закончил играть в гольф.)

Далее мы MapIndexedперебираем внутренний уровень этого вложенного списка. Это вызывает анонимную функцию, предоставленную в качестве первого аргумента для каждого символа в сетке, а также дает ей список с текущими двумя координатами. Сетка пересекается по порядку, поэтому мы можем безопасно рассчитать каждую ячейку на основе предыдущих.

Мы используем переменные r(ight) и b(ottom) в качестве таблиц поиска для результатов каждой ячейки. Наша анонимная функция имеет текущие координаты #2, поэтому мы получаем входные данные для любой ячейки с

r[#2 - {1, 0}],
b[#2 - {0, 1}]

Обратите внимание, что в первой строке и столбце будут доступны неопределенные значения rи b. Mathematica на самом деле не имеет проблем с этим и просто вернет вам ваши координаты, но мы все равно откажемся от этого результата, поскольку все плитки в этой строке / столбце являются постоянными функциями.

Теперь эта вещь:

<|##|> & @@ Thread[
  h@"0 1+\\U)!&|^" -> {
     z = {0, 0}, z, o = 1 + z, {##}, ...
  }] &

Это гольф-форма

<|"0" -> (z = {0, 0}), " " -> z, "1" -> (o = 1 + z), "+" -> {##}, ... |> &

Которая, в свою очередь, является функцией, которая с учетом двух входов мозаики возвращает Ассоциацию (вы бы назвали ее хэш-картой или таблицей на других языках), которая содержит все возможные результаты мозаики для этих двух входов. Чтобы понять, как реализованы все функции, вам нужно знать, что к первому аргументу такой функции можно получить доступ, #а ко второму - #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;;,-1,2]]

и последний вывод правой колонки с

#[[-1,2;;,1]]

Обратите внимание, что 2;;это диапазон от второго до последнего элемента.

Наконец, мы применяем Printк обоим из них (используя @@@в качестве синтаксического сахара для второго уровня Apply), который просто печатает все свои аргументы вплотную (и поскольку он применяется к двум отдельным выражениям, между нижней и нижней строкой будет новая строка) правильный вывод).


8

C 332 309 272 270 266 259 247 225 байт

#define C(x)*c-x?
i,k,T,L,m;f(c,t,l)char*c,*t,*l;{while(L=l[i]){for(k=0;T=t[k];c++)L=C(49)C(43)C(92)C(85)C(41)C(33)C(38)C('|')C(94)T=48:(T^=L-48):(T|=L):(T&=L):(T^=1,L^1):(T=L):T:(m=T,T=L,m):L:(T=49),t[k++]=T;c++;l[i++]=L;}}

Посмотреть результаты онлайн здесь!

Это определяет функцию void f(char*, char*, char*), которая должна принимать плату в качестве первого входа, затем верхний ряд ввода, а затем левый ряд ввода.

Вот что я использовал для проверки:

#include "stdio.h"
int main() {
    char buf[1024],top[33],left[33];
    /* Copy and paste an example circuit as the first input,
       and put a 'Q' immediately after it. 
       Note that the Q is never touched by the function f, and is used
       solely as a delimiter for input. */
    scanf("%[^Q]Q ",buf);
    /* Then enter your top inputs */
    scanf("%[01]%*[^01]", top);
    /* Then your left ones */
    scanf("%[01]", left);
    /* OUTPUT: Bottom\nRight */
    f(buf, top, left);
    return 0;
}

Таким образом, введя 2-битный множитель Sp3000:

UUUU))))
UU++)))&
UUU+)  U
UU++&))U
U++&+)^U
U)&\&)UU
   U+^UU
   \&UUUQ
11110000
00000000

Мы получаем:

00001001
11111111

С другой стороны, учитывая наполовину сумматор Sp3000, я бы хотел увидеть полный сумматор ... Один из вас, ребята, сделал это! Я не думаю, что система стоит сама по себе как язык программирования, но это было очень интересно. Это похоже на отличную цель для метагольфа, хотя!

Краткое объяснение:

Вот развернутый, прокомментированный код:

/* We define the first half of the ?: conditional operator because, well,
   it appears over and over again. */
#define C(x)*c-x?
/* i,k are counting variables
   T,L are *current* top and left inputs */
i,k,T,L,m;
f(c,t,l)char*c,*t,*l;{
    /* The outer loop iterates from top to bottom over l and c */
    while(L=l[i]){
        /* Inner loop iterates from left to right over t and c */
        for(k=0;T=t[k];c++)
            /* This line looks awful, but it's just a bunch of character
            comparisons, and sets T and L to the output of the current c */
            L=C(49)C(43)C(92)C(85)C(41)C(33)C(38)C('|')C(94)T=48:(T^=L-48):(T|=L):(T&=L):(T^=1,L^1):(T=L):T:(m=T,T=L,m):L:(T=49),
            /* Write our output to our input, it will be used for the next row */
            t[k++]=T;
        c++; /*Absorbs the newline at the end of every row */
        /* Keep track of our right-most outputs, 
        and store them in the handy string passed to the function. */
        l[i++]=L;
    }
    /* Bottom output is now stored entirely in t, as is right output in l */        
}

Мы перебираем c, слева направо (затем сверху вниз), tкаждый раз перезаписывая входные данные и выталкивая самый правый выход, который помещается в lстроку. Мы можем представить себе это , как заменить верхний ряд cс 1«s и 0» S итеративно и отслеживание битов, которые выталкиваются справа.

Вот более визуальная последовательность строка за строкой:

 111                                  
1&+^  =>  110 ->0  =>     ->0  =>     0 Thus, "01" has been written to l,
1+&+     1+&+         110 ->1         1
                                  110   And "110" is stored currently in t.

Это очевидно усложняется с разными символами и размерами, но основная идея верна. Это работает только потому, что данные никогда не перемещаются вверх или влево.


Большой потенциал для игры в гольф! Начните с изменения заголовка fна f(c,t,l)char*c,*t,*l(не беспокойтесь о типе возвращаемого значения).
FUZxxl

@FUZxxl Кто-то упомянул об этом в чате, но я не смог заставить его работать. Это стандартное поведение? LLVM выдает как минимум 2 ошибки с этой строкой.
BrainSteel

Сожалею. Должно было быть f(c,t,l)char*c,*t,*l;. Не компилируйте в режиме C11, так как неявное правило int, которое позволяет нам отбрасывать возвращаемый тип, было удалено в этой ревизии.
FUZxxl

@FUZxxl В C99, похоже, тоже ничего не получается. Фактически, каждый режим, в котором я установил компилятор, отклонял этот код.
BrainSteel

Вы добавили точку с запятой сразу после *l? Он компилируется в режиме C99 на моей машине.
FUZxxl

7

Python 2, 316 байт

Эта функция строит 10 лямбда-функций тайла, затем выполняет итерации по сетке, обновляя логические состояния. Окончательные вертикальные и горизонтальные логические состояния затем печатаются.

def b(d,j,g):
 h=enumerate;e=dict((s[0],eval('lambda T,L:('+s[1:]+')'))for s in' 0,0#00,0#11,1#+L,T#\\T,L#UT,T#)L,L#!1-L,1-T#&T&L,T&L#|T|L,T|L#^T^L,T^L'.split('#'));j=list(j+'\n');g=list(g)
 for y,k in h(d.split('\n')):
  L=g[y]
  for x,c in h(k):T=j[x];L,B=e[c](int(T),int(L));j[x]=`B`
  g[y]=`L`
 print''.join(j+g)

Нежелательный код, включая тесты:

def logic(grid, top, left):
    loop = enumerate;
    func = dict((s[0], eval('lambda T,L:('+s[1:]+')')) for s in ' 0,0#00,0#11,1#+L,T#\\T,L#UT,T#)L,L#!1-L,1-T#&T&L,T&L#|T|L,T|L#^T^L,T^L'.split('#'));
    top = list(top+'\n');
    left = list(left)
    for y,row in loop(grid.split('\n')):
        L = left[y]
        for x,cell in loop(row) :
            T = top[x];
            L, B = func[cell](int(T), int(L));
            top[x] = `B`
        left[y] = `L`
    print ''.join(top + left)

import re
testset = open('test.txt', 'rt').read().strip()
for test in testset.split('\n\n'):
    if test.endswith(':'):
        print '------------------\n'+test
    elif re.match('^[01/\n]+$', test, re.S):
        for run in test.split():
            top, left = run.split('/')
            print 'test', top, left
            logic(grid, top, left)
    else:
        grid = test

test.txtФайл ( в том числе 2 других тестов по Sp3000):

Nand:

&!

00/0
00/1
10/0
10/1

All ones:

1111
1\+\
1+\+
1\+\

1001/1100

Xor from Nand (note the column of trailing spaces):

\)+\ 
U&!& 
+! ! 
\&!& 
   ! 

00000/00000
00000/10000
10000/00000
10000/10000

Half adder:

+))
U&+
U+^

000/000
000/100
100/000
100/100

Right shift:

\\\
\++
\++

001/110
010/101
101/100

Тестовый вывод:

------------------
Nand:
test 00 0
01
1
test 00 1
01
1
test 10 0
01
1
test 10 1
11
0
------------------
All ones:
test 1001 1100
1111
1111
------------------
Xor from Nand (note the column of trailing spaces):
test 00000 00000
00000
00000
test 00000 10000
00010
00000
test 10000 00000
00010
00000
test 10000 10000
00000
00000
------------------
Half adder:
test 000 000
000
000
test 000 100
001
101
test 100 000
101
001
test 100 100
110
110
------------------
Right shift:
test 001 110
000
111
test 010 101
101
010
test 101 100
010
110

7

Python 2, 384 338 325 байт

def f(G,T,L):
 def g(x,y):
  if x>-1<y:l=g(x-1,y)[1];t=g(x,y-1)[0];r=l,t,1-l,0,0,1,t,l,l&t,l|t,l^t;i="+\\!0 1U)&|^".index(G[y*-~W+x]);return((t,l,1-t)+r[3:])[i],r[i]
  return(int((y<0)*T[x]or L[y]),)*2
 H=G.count("\n")+1;W=len(G)/H;return eval('"".join(map(str,[g(%s]for _ in range(%s)])),'*2%('_,H-1)[0','W','W-1,_)[1','H'))

Серьезно, CH, если это уже не игрушка, вы должны начать обзванивать некоторые фабрики игрушек.

Больше играли в гольф и намного менее эффективны сейчас, но все еще не догнали CarpetPython. Входные данные f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010"), выходные данные - это кортеж из двух строк. Убедитесь, что на доске нет завершающего символа новой строки, который сломает вещи.

Тестовая программа

def f(G,T,L):
 def g(x,y):
  if x>-1<y:l=g(x-1,y)[1];t=g(x,y-1)[0];r=l,t,1-l,0,0,1,t,l,l&t,l|t,l^t;i="+\\!0 1U)&|^".index(G[y*-~W+x]);return((t,l,1-t)+r[3:])[i],r[i]
  return(int((y<0)*T[x]or L[y]),)*2
 H=G.count("\n")+1;W=len(G)/H;return eval('"".join(map(str,[g(%s]for _ in range(%s)])),'*2%('_,H-1)[0','W','W-1,_)[1','H'))


import itertools

G = r"""
+))
U&+
U+^
""".strip("\n")

def test(T, L):
    print f(G, T, L)

def test_all():
    W = len(G[0])
    H = len(G)

    for T in itertools.product([0, 1], repeat=len(G.split("\n")[0])):
        T = "".join(map(str, T))

        for L in itertools.product([0, 1], repeat=len(G.split("\n"))):
            L = "".join(map(str, L))

            print "[T = %s; L = %s]" % (T, L)
            test(T, L)
            print ""

test("000", "000")
test("000", "100")
test("100", "000")
test("100", "100")

Вы также можете проверить все возможные случаи с test_all() .

Дополнительные тестовые случаи

Половина сумматора

Вот половинный сумматор, который добавляет верхние левые биты, выводя <input bit> <carry> <sum>:

+))
U&+
U+^

тесты:

000 / 000  ->  000 / 000
000 / 100  ->  001 / 101
100 / 000  ->  101 / 001
100 / 100  ->  110 / 110

Выход должен быть одинаковым, даже если второй / третий биты входов изменены.

Сдвиг вправо

Учитывая abc / def, это выводы fab / cde:

\\\
\++
\++

тесты:

001 / 110 -> 000 / 111
010 / 101 -> 101 / 010
101 / 100 -> 010 / 110

3-битный сортировщик

Сортирует первые три бита сверху в последние три бита снизу. Правильный вывод - мусор.

UUU)))
UU)U U
U&UU U
U+|&)U
\UU++|
 \)&UU
  \+|U
   UUU

тесты:

000000 / 00000000 -> 000000 / 00000000
001000 / 00000000 -> 000001 / 11111111
010000 / 00000000 -> 000001 / 00001111
011000 / 00000000 -> 000011 / 11111111
100000 / 00000000 -> 000001 / 00001111
101000 / 00000000 -> 000011 / 11111111
110000 / 00000000 -> 000011 / 00001111
111000 / 00000000 -> 000111 / 11111111

2-битный на 2-битный множитель

Принимает 1-й / 2-й бит вершины в качестве первого числа и 3-й / 4-й бит вершины в качестве второго числа. Выходы на последние четыре бита снизу. Правильный вывод - мусор.

UUUU))))
UU++)))&
UUU+)  U
UU++&))U
U++&+)^U
U)&\&)UU
   U+^UU
   \&UUU

Изменить: Гольф из колонки и двух рядов.

тесты:

00000000 / 00000000 -> 00000000 / 00000000
00010000 / 00000000 -> 00000000 / 10000000
00100000 / 00000000 -> 00000000 / 00000000
00110000 / 00000000 -> 00000000 / 10000000
01000000 / 00000000 -> 00000000 / 00000000
01010000 / 00000000 -> 00000001 / 11111111
01100000 / 00000000 -> 00000010 / 00000000
01110000 / 00000000 -> 00000011 / 11111111
10000000 / 00000000 -> 00000000 / 00000000
10010000 / 00000000 -> 00000010 / 10000000
10100000 / 00000000 -> 00000100 / 00000000
10110000 / 00000000 -> 00000110 / 10000000
11000000 / 00000000 -> 00000000 / 00000000
11010000 / 00000000 -> 00000011 / 11111111
11100000 / 00000000 -> 00000110 / 00000000
11110000 / 00000000 -> 00001001 / 11111111

1

R 524 517

Вероятно, сейчас есть много возможностей, чтобы уменьшить это, но это было действительно интересно сделать. Есть две функции. Функция d является рабочим, а f является компаратором.

Функция d вызывается с 3 строками, Gates, Top и Left. Ворота помещаются в матрицу, определяемую шириной.

I=strtoi;S=strsplit;m=matrix;f=function(L,T,G){O=I(c(0,1,L,T,!L,!T,L&T,L|T,xor(L,T)));X=which(S(' 01+\\U)!&|^','')[[1]]==G);M=m(c(1,1,1,2,1,1,3,2,2,4,3,4,5,4,3,6,4,4,7,3,3,8,5,6,9,7,7,10,8,8,11,9,9),nrow=3);return(c(O[M[2,X]],O[M[3,X]]))};d=function(G,U,L){W=nchar(U);H=nchar(L);U=c(list(I(S(U,'')[[1]])),rep(NA,H));L=c(list(I(S(L,'')[[1]])),rep(NA,W));G=m((S(G,'')[[1]]),nrow=W);for(i in 1:H)for(n in 1:W){X=f(L[[n]][i],U[[i]][n],G[n,i]);L[[n+1]][i]=X[1];U[[i+1]][n]=X[2]};cat(U[[H+1]],' / ',L[[W+1]],sep='',fill=T)}

Немного отформатирован

I=strtoi;S=strsplit;m=matrix;
f=function(L,T,G){
    O=I(c(0,1,L,T,!L,!T,L&T,L|T,xor(L,T)));
    X=which(S(' 01+\\U)!&|^','')[[1]]==G);
    M=m(c(1,1,1,2,1,1,3,2,2,4,3,4,5,4,3,6,4,4,7,3,3,8,5,6,9,7,7,10,8,8,11,9,9),nrow=3);
    return(c(O[M[2,X]],O[M[3,X]]))
};
d=function(G,U,L){
    W=nchar(U);H=nchar(L);
    U=c(list(I(S(U,'')[[1]])),rep(NA,H));
    L=c(list(I(S(L,'')[[1]])),rep(NA,W));
    G=m((S(G,'')[[1]]),nrow=W);
    for(i in 1:H)
        for(n in 1:W){
            X=f(L[[n]][i],U[[i]][n],G[n,i]);
            L[[n+1]][i]=X[1];
            U[[i+1]][n]=X[2]
        };
    cat(U[[H+1]],' / ',L[[W+1]],sep='',fill=T)
}

Некоторые тесты

> d('&!','00','0')
01 / 1
> d('&!','00','1')
01 / 1
> d('&!','10','0')
01 / 1
> d('&!','10','1')
11 / 0
> d('\\)+\\ U&!& +! ! \\&!&    ! ','00000','00000')
00000 / 00000
> d('\\)+\\ U&!& +! ! \\&!&    ! ','00000','10000')
00010 / 00000
> d('\\)+\\ U&!& +! ! \\&!&    ! ','10000','00000')
00010 / 00000
> d('\\)+\\ U&!& +! ! \\&!&    ! ','10000','10000')
00000 / 00000
> d('+++\\00000000000\\!!!!\\00000000000\\+++','000000000000','100')
000000000000 / 001
> d('+++\\00000000000\\!!!!\\00000000000\\+++','000000000000','000')
000000000000 / 000
> d('+))U&+U+^','000','000')
000 / 000
> d('+))U&+U+^','000','100')
001 / 101
> d('+))U&+U+^','100','000')
101 / 001
> d('+))U&+U+^','100','100')
110 / 110
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.