Цифрова логіка на основі сітки (дуодіадичні плитки)


33

Дюодіадичні плитки - це різновиди квадратних функціональних блоків, які приймають два входи, один з їх верхньої та один з лівого боку, і мають два виходи, один з правого боку та один з нижньої. Кожен їх вихід є окремою функцією обох входів.

Наприклад, якщо #є загальну плитку, правий вихід 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; один буде лівим стовпчиком введення, а другий - верхнім рядком введення. Вашій програмі / функції потрібно надрукувати / повернути нижній рядок виводу та правий стовпець виводу (також у 01' 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.
  • Ви можете припустити, що вхідні рядки та довжини стовпців будуть відповідати розмірам сітки та міститимуть лише 0s та 1s.
  • Ваша сітка повинна використовувати відповідні символи ( 0 1+\U)!&|^). Пам'ятайте про це 0і означайте те саме.

Випробування

(Читати введення / виведення як 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

Zig zag:

+++\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 аналогічно позначенню Кубка Рубіка, а потім. . . тритриадні кубики?
Soham Chowdhury

Відповіді:


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

Демонстрація в Інтернеті .

Введення здійснюється таким чином: Спочатку сітка (без втечі, без зайвих символів), а потім два рядки введення, наприклад (Zig zag)

+++\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}] &

Це неназвана функція, яка бере три рядки для сітки, верхнього та лівого входів та друкує нижній і правий виходи.

Пояснення

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

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

Ось цей біт:

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

Це просто розбиває сітку на вкладений список символів (зауважте, що я визначив hпсевдонім Characterдесь у коді), а потім попередньо створює рядок та стовпець із введеннями. Це працює, тому що 1і 0це також назви плиток з постійною функцією, тому насправді розміщення їх має такий же ефект, як і подача входів вручну. Оскільки це функції, вони технічно прийматимуть свій внесок поза мережею, але оскільки це постійні функції, що не має значення. Лівий верхній кут отримує, 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повертає 3D-сітку, де перший вимір відповідає координаті горизонтальної сітки (згадайте попередню транспозицію), другий розмір відповідає вертикальній координаті сітки, а третій вказує, чи є у нас нижній чи лівий вихід. Зауважте, що це також містить вхідний рядок і стовпець, яких нам потрібно позбутися. Таким чином, ми отримуємо доступ до нижнього виходу нижнього ряду за допомогою

#[[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'))

Якщо це серйозно, якщо це вже не іграшка, ви повинні почати дзвонити на деякі фабрики іграшок.

Більш гольф і набагато менш ефективні зараз, але все ще не наздогнали 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.