Logika Digital Berbasis Grid (Ubin Duodyadic)

33

Ubin duodadik adalah jenis blok fungsi persegi yang mengambil dua input, satu dari sisi atas dan satu dari sisi kiri, dan memiliki dua output, satu di sisi kanan dan satu di sisi bawah. Setiap output mereka adalah fungsi terpisah dari kedua input mereka.

Misalnya, jika #mewakili ubin generik, output yang tepat Radalah fungsi finput Tdan L, dan output bawah Badalah fungsi lain gdari Tdan L:

 T
L#R         R = f(T, L)
 B          B = g(T, L)

(Ubin disebut "duo" karena ada dua fungsi, dan "diad" karena kedua fungsi memiliki dua argumen .)

Ubin kemudian dapat dikomposisikan bersama pada sebuah grid, output dari satu ubin langsung ke input ubin tetangga. Di sini misalnya, output kanan dari kiri #masuk ke input kiri kanan #:

 AB         D = f(f(A, C), B)
C##D        E = g(A, C)
 EF         F = g(f(A, C), B)

Anda dapat membayangkan bahwa diberikan satu set ubin duodadik, masing-masing dengan fungsi spesifik, komposisi kompleks (dan berpotensi bermanfaat) dapat dibuat.

Dalam tantangan ini, kita hanya akan memusatkan perhatian pada perangkat tradisional dari sepuluh petak duodyadic berbasis logika , di mana semua input dan output adalah bilangan biner bit-tunggal (nol atau yang). Kami akan menggunakan karakter ASCII terpisah untuk menunjukkan setiap jenis ubin.

Karakter ubin dan hubungan input-outputnya adalah sebagai berikut:
( Tuntuk input atas, Luntuk input kiri, Runtuk output kanan, Buntuk output bawah.)

  1. Nol: 0atau (spasi) → R = 0,B = 0
  2. Satu: 1R = 1,B = 1
  3. Salib: +R = L,B = T
  4. Cermin: \R = T,B = L
  5. Hanya di atas: UR = T,B = T
  6. Hanya yang tersisa: )R = L,B = L
  7. Tidak: !R = not L,B = not T
  8. Dan: &R = L and T,B = L and T
  9. Atau: |R = L or T,B = L or T
  10. Xor: ^R = L xor T,B = L xor T

Tantangan

Tulis sebuah program atau fungsi yang mengambil dalam kotak persegi panjang dari karakter 0 1+\U)!&|^yang mewakili "sirkuit" yang dibuat menggunakan sepuluh ubin duodyadic berbasis logika. Anda juga perlu mengambil dua string 0'dan 1'; satu akan menjadi kolom input kiri dan satu akan menjadi baris input atas. Program / fungsi Anda perlu mencetak / mengembalikan baris output bawah dan kolom output kanan (juga di 0's dan 1' s).

Misalnya, di kotak ini

+++
+++

semua input mengalir lurus melintasi grid ke output

 ABC
D+++D
E+++E
 ABC

jadi input dari 010/ 01akan memiliki output 010/ 01:

 010
0+++0
1+++1
 010

Keluaran pasti dari program Anda adalah [bottom output row]\n[right output column]atau [bottom output row]/[right output column]:

010
01

atau

010/01

Jika Anda menulis suatu fungsi, Anda dapat mengembalikan dua string dalam sebuah tuple atau daftar (atau masih mencetaknya).

Detail

  • Ambil tiga input sebagai string dengan cara yang masuk akal (lebih disukai di kisi pesanan, baris atas, kolom kiri): baris perintah, file teks, sdtin, function arg.
  • Anda dapat mengasumsikan panjang baris dan kolom input akan cocok dengan dimensi kisi dan hanya akan berisi 0'dan 1'.
  • Kisi Anda harus menggunakan karakter yang tepat ( 0 1+\U)!&|^). Ingat itu 0dan maksudkan hal yang sama.

Uji Kasus

(Baca I / O sebagai top/ leftbottom/ right.)

Nand:

&!

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

Semua yang:

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

Setiap input harus menghasilkan 1111/ 1111.

Xor dari Nand: (perhatikan kolom spasi tambahan)

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

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

Zig zag:

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

Bit pertama dari input kiri menjadi bit terakhir dari output kanan. Yang lainnya adalah 0.

000000000000/ 000000000000000/ 000
000000000000/ 100000000000000/001

Perambatan:

)))
UUU
U+U
U+U
UUU

Bit pertama dari input kiri menuju ke semua output.

000/ 00000000/ 00000
000/ 10000111/11111

Berikut adalah pastebin dari semua kotak uji 1 × 1.

Mencetak gol

Pengajuan terpendek dalam byte menang.

Bonus: "sirkuit" keren apa yang bisa Anda buat?

PS Jangan ganggu Googling "ubin duodyadic". Saya mengarangnya kemarin; D
Jika Anda ingin mendiskusikan perluasan ide ini menjadi bahasa pemrograman yang lengkap, datanglah ke ruang obrolan ini .

Hobi Calvin
sumber
11
Memberi +1 untuk tantangan keren tetapi juga karena Anda menemukan ubin duodyadic, yang BENAR-BENAR keren.
Alex A.
3
+1 Ini benar-benar tidak berguna untuk google ini: goo.gl/zuqfdW . Tantangan yang bagus!
BrainSteel
Saya bersama mereka. Saya jauh lebih tertarik pada ubin Anda sebagai bahasa pemrograman daripada tantangan golf khusus ini. PS: Ada 16 ubin yang memungkinkan, jadi menghasilkan huruf / nama untuk enam lainnya akan rapi.
Sparr
Akan menarik untuk memiliki blok yang output / input dari arah yang berbeda, karena jika tidak, Anda tidak dapat membuat kait karena semuanya mengalir ke arah kanan bawah.
Sp3000
2
Anda dapat mengubah T / B ke U (p) / D (sendiri), sehingga kita bisa memiliki F / B secara analog dengan notasi Rubik's Cube, dan kemudian. . . kubus tritriadik?
Soham Chowdhury

Jawaban:

8

Pyth, 122

Agak monster. Hanya menggunakan rekursi, tidak ada yang mewah seperti pemrograman dinamis.

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

Demonstrasi online .

Input dengan cara berikut: Pertama grid (tidak ada yang melarikan diri, tidak ada simbol tambahan) dan kemudian dua baris input, misalnya (Zig zag)

+++\00000000
000\!!!!\000
00000000\+++
000000000000
100
Jakube
sumber
8

Mathematica, 331 276 270 267 264 262 252 250 byte

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

Ini adalah karakter Unicode penggunaan pribadi yang digunakan Mathematica sebagai superscript T, yaitu operator transposisi.

Ini adalah versi yang lebih mudah dibaca:

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

Ini adalah fungsi tanpa nama yang mengambil tiga string untuk input grid, atas dan kiri dan mencetak output bawah dan kanan.

Penjelasan

Mari kita lalui langkah demi langkah ini (saya akan mencoba untuk tidak mengasumsikan pengetahuan Mathematica). Anda perlu membaca kode kembali ke depan. Algoritma dasar hanya menyapu garis komputasi setiap fungsi dan menyimpan hasilnya funtuk diakses oleh ubin berikutnya.

Pemrosesan input

Itu sedikit ini:

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

Ini hanya membagi kisi-kisi menjadi daftar karakter yang bersarang (perhatikan bahwa saya mendefinisikan hsebagai alias untuk Charactersuatu tempat dalam kode) dan kemudian menambahkan baris dan kolom dengan input. Ini berfungsi, karena 1dan 0juga nama-nama ubin fungsi konstan, jadi sebenarnya menempatkan mereka pada efek yang sama seperti memberi makan input secara manual. Karena ini adalah fungsi mereka secara teknis akan mengambil input dari luar grid, tetapi karena mereka adalah fungsi konstan yang tidak masalah. Sudut kiri atas mendapat 0tetapi ini cukup sewenang-wenang karena hasil ubin itu tidak pernah digunakan.

Perhatikan juga transposisi. Menambahkan kolom membutuhkan lebih banyak karakter daripada menambahkan baris, jadi saya mengubah urutan grid setelah menambahkan baris atas. Ini berarti bahwa bagian atas / bawah dan kiri / kanan ditukar untuk bagian utama dari program, tetapi mereka benar-benar dapat ditukar sehingga tidak masalah. Saya hanya perlu memastikan untuk mengembalikan hasil dalam urutan yang benar.

Memecahkan grid

(Bagian ini sedikit ketinggalan jaman. Akan diperbaiki setelah aku benar-benar yakin sudah selesai bermain golf.)

Selanjutnya, kita menabrak MapIndexedbagian dalam daftar bersarang ini. Ini memanggil fungsi anonim yang disediakan sebagai argumen pertama untuk setiap karakter dalam kisi, juga memberikan daftar dengan dua koordinat saat ini. Kisi dilewati secara berurutan, sehingga kami dapat dengan aman menghitung setiap sel berdasarkan yang sebelumnya.

Kami menggunakan variabel r(ight) dan b(ottom) sebagai tabel pencarian untuk hasil setiap sel. Fungsi anonim kami memiliki koordinat saat ini #2, jadi kami mendapatkan input dengan sel apa pun

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

Perhatikan bahwa pada baris dan kolom pertama ini akan mengakses nilai rdan b. Mathematica tidak benar-benar memiliki masalah dengan itu dan hanya akan memberikan Anda kembali koordinat Anda sebagai gantinya, tetapi kami membuang hasil ini, karena semua ubin di baris / kolom itu adalah fungsi konstan.

Sekarang ini:

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

Adalah bentuk golf

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

Yang pada gilirannya adalah fungsi yang, mengingat dua input ubin, mengembalikan Asosiasi (Anda akan menyebutnya hashmap atau tabel dalam bahasa lain), yang berisi semua hasil ubin yang mungkin untuk kedua input ini. Untuk memahami, bagaimana semua fungsi diimplementasikan, Anda perlu tahu bahwa argumen pertama dari fungsi tersebut dapat diakses dengan #dan yang kedua dengan #2. Selanjutnya, ##memberi Anda urutan kedua argumen yang dapat digunakan untuk "memerciki" argumen.

  • 0: mudah, kami hanya mengembalikan konstanta {0, 0}dan juga menetapkan ini zuntuk penggunaan di masa mendatang (misalnya di ubin ruang).
  • 1: pada dasarnya adil {1,1}, tetapi memiliki zini disingkat menjadi 1+z. Kami juga menyimpan ini o, karena akan berguna untuk semua ubin di mana kedua output identik.
  • +: Di sini kita menggunakan urutan. {##}adalah sama dengan {#,#2}dan melewati kedua input melalui tidak berubah.
  • \: Kami menukar dua argumen {#2,#},.
  • U: Sekarang kita bisa memanfaatkan o. o#2berarti {1,1}*#2jadi kami hanya menempatkan argumen teratas di kedua output.
  • ): Analog untuk argumen kiri: o#.
  • !: Bitwise tidak menjengkelkan di Mathematica, tapi karena kami hanya pernah memiliki 0dan 1, kita hanya dapat mengurangi kedua input dari 1(demikian pembalik mereka) dan meneruskannya: 1-{##}.
  • &: Yang ini cukup bagus. Pertama kita perhatikan bahwa bitwise dan untuk 0dan 1identik dengan perkalian. Selanjutnya, o##sama dengan o*#*#2.
  • |: Sekali lagi, kami menggunakan fungsi yang setara. Bitwise atau sama seperti Maxdalam kasus ini, jadi kami menerapkan Maxargumen input dan mengalikan hasilnya menjadi {1,1}.
  • ^: Yang terpendek yang saya temukan untuk xor adalah untuk mengambil perbedaan dan mengujinya (untuk memastikan positif), jadi kami punya o(#-#2)^2.

Setelah fungsi ini selesai dan mengembalikan asosiasi penuh, kami menggunakan karakter sel saat ini untuk mengeluarkan elemen yang kami minati dan menyimpannya di rdan b. Perhatikan bahwa ini juga merupakan nilai balik dari fungsi anonim yang digunakan MapIndexed, sehingga pemetaan sebenarnya akan memberi saya kisi dari semua hasil.

Pemrosesan output

MapIndexedmengembalikan kotak 3D, di mana dimensi pertama berkorespondensi dengan koordinat grid horizontal (ingat transposisi sebelumnya), dimensi kedua berkorespondensi dengan koordinat grid vertikal dan yang ketiga menunjukkan apakah kita punya output bawah atau kiri. Perhatikan bahwa ini juga berisi baris dan kolom input yang harus kita singkirkan. Jadi kita mengakses output bawah baris bawah dengan

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

dan output kanan kolom terakhir dengan

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

Perhatikan bahwa 2;;rentang dari elemen kedua ke elemen terakhir.

Terakhir, kami berlaku Printuntuk keduanya (menggunakan @@@sebagai sintaksis gula untuk tingkat kedua Apply), yang hanya mencetak semua argumennya secara berurutan (dan karena itu diterapkan pada dua ekspresi terpisah, akan ada garis baru antara bawah dan output yang benar).

Martin Ender
sumber
8

C, 332 309 272 270 266 259 247 225 byte

#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;}}

Lihat hasil online di sini!

Ini mendefinisikan fungsi void f(char*, char*, char*), yang harus menggunakan papan sebagai input pertama, lalu baris input atas, dan kemudian baris input kiri.

Inilah yang saya gunakan untuk mengujinya:

#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;
}

Jadi, dengan memasukkan pengali 2-bit Sp3000:

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

Kita mendapatkan:

00001001
11111111

Pada catatan lain, dengan setengah penambah Sp3000 dalam pikiran, saya ingin melihat penambah penuh ... Salah satu dari kalian melakukannya! Saya tidak berpikir sistem berdiri sendiri sebagai bahasa pemrograman, tetapi ini sangat menarik. Ini sepertinya target yang sangat bagus untuk metagolf!

Penjelasan Singkat:

Berikut kode yang terurai, yang dikomentari:

/* 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 */        
}

Kami beralih c, kiri ke kanan (kemudian atas ke bawah), menulis ulang tinput setiap kali dan mendorong output paling kanan yang dimasukkan ke dalam lstring. Kita dapat membayangkan ini sebagai mengganti baris atas cdengan 1dan dan 0iteratif, dan melacak bit yang didorong keluar di sebelah kanan.

Berikut urutan yang lebih visual, baris demi baris:

 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.

Ini jelas menjadi lebih rumit dengan berbagai simbol dan ukuran, tetapi ide sentralnya tetap berlaku. Ini hanya berfungsi karena data tidak pernah mengalir ke atas atau ke kiri.

BrainSteel
sumber
Banyak potensi untuk bermain golf! Mulailah dengan mengubah tajuk fmenjadi f(c,t,l)char*c,*t,*l(jangan peduli tentang jenis pengembalian).
FUZxxl
@FUZxxl Seseorang menyebut ini di obrolan, tetapi saya tidak bisa membuatnya berfungsi. Apakah standar perilaku ini? LLVM melempar setidaknya 2 kesalahan dengan garis itu.
BrainSteel
Maaf. Seharusnya begitu f(c,t,l)char*c,*t,*l;. Jangan mengkompilasi dalam mode C11, karena aturan int implisit yang memungkinkan kita untuk menjatuhkan tipe kembali telah dijatuhkan dalam revisi itu.
FUZxxl
@ FuZxxl Tampaknya gagal di C99, juga. Faktanya, setiap mode yang saya atur kompilernya telah menolak kode itu.
BrainSteel
Apakah Anda menambahkan titik koma setelahnya *l? Ini mengkompilasi dalam mode C99 pada mesin saya.
FUZxxl
7

Python 2, 316 byte

Fungsi ini membangun 10 fungsi lambda ubin, kemudian beralih melalui kisi, memperbarui status logika. Keadaan akhir vertikal dan horizontal kemudian dicetak.

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)

Kode ungolfed termasuk tes:

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

The test.txtberkas (termasuk 2 tes lain dengan 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

Output tes:

------------------
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
Ksatria Logika
sumber
7

Python 2, 384 338 325 byte

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

Serius CH, jika ini bukan mainan Anda harus mulai menelepon beberapa pabrik mainan.

Lebih banyak bermain golf dan jauh lebih efisien sekarang, tetapi masih belum menyusul CarpetPython. Input like f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010"), output adalah tuple dari dua string. Pastikan papan tidak memiliki baris tambahan, yang akan merusak segalanya.

Program uji

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")

Anda juga dapat menguji semua kemungkinan kasus dengan test_all().

Kasus uji ekstra

Setengah penambah

Inilah setengah penambah yang menambahkan bit kiri atas, menghasilkan <input bit> <carry> <sum>:

+))
U&+
U+^

Tes:

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

Output harus sama bahkan jika bit input kedua / ketiga diubah.

Pergeseran kanan

Diberikan abc / def, ini output fab / cde:

\\\
\++
\++

Tes:

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

Penyortir 3-bit

Mengurutkan tiga bit pertama dari atas ke dalam tiga bit terakhir dari bagian bawah. Output yang tepat adalah sampah.

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

Tes:

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

Pengganda 2-bit demi 2-bit

Mengambil bit 1/2 atas sebagai angka pertama, dan bit 3/4 atas sebagai angka kedua. Output ke empat bit terakhir dari bagian bawah. Output yang tepat adalah sampah.

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

Sunting: Keluar kolom dan dua baris.

Tes:

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
Sp3000
sumber
1

R, 524 517

Mungkin ada banyak ruang untuk mengurangi ini saat ini, tetapi ini benar-benar menarik untuk dilakukan. Ada dua fungsi. Fungsi d adalah pekerja dan f adalah pembanding.

Fungsi d disebut dengan 3 string, Gates, Top dan Left. Gerbang dimasukkan ke dalam matriks yang ditentukan oleh lebar.

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)}

Diformat sedikit

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)
}

Beberapa tes

> 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
MickyT
sumber