Izgara Tabanlı Dijital Mantık (Duodyadik Fayans)


33

Duodyadik fayanslar , biri üst taraftan diğeri sol taraftan olmak üzere iki girişi alan ve biri sağ tarafta diğeri de alt tarafta olmak üzere iki çıkışa sahip kare fonksiyon bloklarıdır . Çıkışlarının her biri girişlerinin her ikisinin de ayrı bir işlevidir.

Örneğin, #genel bir karo temsil sağ çıktı Rbir fonksiyondur fgirdilerin Tve Lve alt çıkış Bbaşka işlevidir garasında Tve L:

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

(Her iki fonksiyonun da iki argümanı olduğundan, iki fonksiyon olduğundan çini "ikili" olarak adlandırılır .)

Fayanslar daha sonra bir ızgarada bir araya getirilebilir, bir karonun çıktıları doğrudan komşu karoların girdilerine girer. Örneğin, solun sağ çıktısı sağın #sol girişine gider #:

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

Her biri belirli işlevselliğe sahip, karmaşık (ve potansiyel olarak faydalı) kompozisyonlar yapılabilecek bir duodyadik fayans seti verildiğini hayal edebilirsiniz.

Bu mücadelede, yalnızca tüm girdi ve çıktıların tek bitli ikili sayılar (sıfırlar veya sıfırlar) olduğu geleneksel on mantık tabanlı duodyadik karo kümesiyle ilgileneceğiz. Her bir döşeme türünü belirtmek için ayrı bir ASCII karakteri kullanacağız.

Döşeme karakterleri ve giriş-çıkış ilişkileri aşağıdaki gibidir:
( Tüst giriş, Lsol giriş, Rsağ çıkış, Balt çıkış için.)

  1. Sıfır: 0veya (boşluk) → R = 0,B = 0
  2. Bir: 1R = 1,B = 1
  3. Çapraz: +R = L,B = T
  4. Ayna: \R = T,B = L
  5. Sadece üst: UR = T,B = T
  6. Yalnızca sol: )R = L,B = L
  7. Değil: !R = not L,B = not T
  8. Ve: &R = L and T,B = L and T
  9. Veya: |R = L or T,B = L or T
  10. Xor: ^R = L xor T,B = L xor T

Meydan okuma

0 1+\U)!&|^On mantık tabanlı duodyadik fayans kullanılarak yapılan bir "devreyi" temsil eden karakterlerin dikdörtgen bir ızgarasına giren bir program veya fonksiyon yazın . Ayrıca iki 0s dizesini de almanız gerekir 1; Biri sol giriş sütunu, diğeri üst giriş satırı olacaktır. Programınızın / işlevinizin alt çıktı satırını ve sağ çıktı sütununu (aynı zamanda 0's ve 1s) yazdırması / döndürmesi gerekir .

Örneğin, bu ızgarada

+++
+++

tüm girişler ızgara boyunca doğrudan çıkışlara akar

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

bir giriş, böylece 010/ ' 01çıkışına sahip olacaktır 010/ 01:

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

Programın kesin çıkış olurdu [bottom output row]\n[right output column]ya [bottom output row]/[right output column]:

010
01

veya

010/01

Bir işlev yazdıysanız, iki dizeyi bir dizgede veya listede geri döndürebilirsiniz (veya yine de bunları yazdırabilirsiniz).

ayrıntılar

  • Üç girdiyi herhangi bir makul şekilde dizge olarak alın (tercihen sıralı sırayla, üst sıra, sol sütun): komut satırı, metin dosyası, sdtin, function arg.
  • Giriş satırının ve sütun uzunluklarının ızgara boyutlarıyla eşleşeceğini ve yalnızca 0's ve 1' ler içereceğini varsayabilirsiniz .
  • Kılavuzunuz uygun karakterleri ( 0 1+\U)!&|^) kullanmalıdır. Bunu hatırla 0ve aynı şeyi kastet.

Test Kılıfları

(G / Ç'yi top/ leftbottom/ olarak okuyun right)

NAND:

&!

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

Hepsi:

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

Herhangi bir giriş 1111/ ile sonuçlanmalıdır 1111.

Nand'dan Xor: (sondaki boşlukların sütununa dikkat edin)

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

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

Zig zag:

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

Sol girişin ilk biti sağ çıktının son biti olur. Diğer her şey 0.

000000000000/ 000000000000000/ 000
000000000000/ 100000000000000/001

Yayılma:

)))
UUU
U+U
U+U
UUU

Sol girişin ilk biti tüm çıkışlara gider.

000/ 00000000/ 00000
000/ 10000111/11111

İşte 1 × 1 grid test durumlarının pastebin.

puanlama

Bayt cinsinden en kısa gönderme kazanır.

Bonus: Hangi serin "devreleri" yapabilirsiniz?

PS Googling "duodyadic fayans" rahatsız etmeyin. Onları dün uydurdum; D
Bu fikri tam teşekküllü bir programlama diline genişletmeyi tartışmak istiyorsanız, bu sohbet odasına gelin .


11
Serin bir meydan okuma için +1 ama aynı zamanda gerçekten harika olan duodyadik fayansları icat ettiğiniz için.
Alex A.

3
+1 Bunu google yapmak gerçekten işe yaramaz: goo.gl/zuqfdW . Güzel meydan okuma!
BrainSteel

Onlarla birlikteyim. Döşemelerinize programlama dili olarak bu golf mücadelesinden çok daha fazla ilgi duyuyorum. Not: 16 tane kiremit vardır, bu yüzden diğer altının harfleri / isimleri gelirken temiz olur.
Sparr

Farklı yönlerden çıktı / girdi blokları olması ilginç olurdu, çünkü aksi halde her şey aşağı doğru bir yönde aktığından mandal yapamazsınız.
Sp3000,

2
T / B'yi U (p) / D (own) olarak değiştirebilirsiniz, böylece F / B'yi Rubik Küpü notasyonu ile aynı şekilde kullanabilirsiniz. . . tritriadic küpler?
Soham Chowdhury

Yanıtlar:


8

Pyth, 122

Bir tür canavar. Basitçe özyinelemeyi kullanır, dinamik programlama gibi hoş bir şey değil.

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

Çevrimiçi gösteri .

Giriş şu şekildedir: İlk önce ızgara (kaçış yok, fazladan sembol yok) ve sonra iki giriş satırı, örn. (Zig zag)

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

8

Mathematica, 331 276 270 267 264 262 252 250 bayt

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

Mathematica bir üst simge olarak kullandığı özel kullanım Unicode karakter Tyani o aktarılması operatörü var.

İşte daha okunabilir bir versiyon:

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

Bu, ızgara, üst ve sol girişler için üç dizeyi alan ve alt ve sağ çıktıları basan adsız bir işlevdir.

açıklama

Şimdi bu adımdan geçelim (Herhangi bir Mathematica bilgisini almamaya çalışacağım). Kodu tekrar öne doğru okuman gerekiyor. Temel algoritma, sadece her bir işlevi hesaplayan ve sonuçları ftakip eden döşemeler tarafından erişilecek sonuçları depolayan satırları tarar.

Giriş işleme

Bu biraz:

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

Bu yalnızca ızgarayı iç içe geçmiş bir karakter listesine ayırır ( koddaki hbir yer için takma ad olarak tanımladığımı unutmayın Character) ve sonra girişlerle birlikte bir satır ve sütun hazırlar . Bu eserler, çünkü 1ve 0bu yüzden aslında elle de girdi besleyen aynı etkiye sahiptir üzerine koyarak, aynı zamanda sabit fonksiyonlu karoların isimleridir. Bunlar fonksiyon olduklarından teknik olarak girişlerini ızgara dışından alacaklardır, ancak önemli olmayan sürekli fonksiyonlar. Sol üst köşe bir alır 0ancak bu, bu döşemenin sonuçları hiç kullanılmadığı için oldukça keyfidir.

Ayrıca yer değiştirmeye dikkat edin. Sütun eklemek, satır eklemekten daha fazla karakter alır, bu nedenle üst satırı ekledikten sonra ızgarayı dönüştürürüm. Bu, programın ana kısmı için üst / alt ve sol / sağ değiştirildiği anlamına gelir, ancak bunlar tamamen değiştirilebildiğinden önemli değildir. Sonuçları doğru sırayla döndürdüğümden emin olmam gerekiyor.

Izgarayı çözme

(Bu bölüm biraz modası geçmiş. Golfü bitirdiğimden emin olduğumda düzeltecektir.)

Ardından MapIndexed, bu iç içe listenin iç düzeyini geçiyoruz. Bu, ızgaradaki her karakter için ilk argüman olarak sağlanan adsız işlevi çağırır, ayrıca geçerli iki koordinatla birlikte bir liste verir. Izgara sırayla hareket eder, böylece öncekilere göre her bir hücreyi güvenle hesaplayabiliriz.

Her hücrenin sonuçları için (ıght r) ve b(ottom) değişkenlerini arama tabloları olarak kullanıyoruz. Anonim fonksiyonumuz içinde mevcut koordinatlar var #2, bu yüzden girişleri olan herhangi bir hücreye girdiler.

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

Not birinci satır ve sütun bu irade erişim değerlerini tanımlanmamış olduğunu rve b. Mathematica'nın bununla gerçekten bir sorunu yok ve bunun yerine size koordinatlarınızı geri vereceğiz, ancak bu sonucu yine de atacağız, çünkü o satır / sütundaki tüm döşemeler sabit işlevlerdir.

Şimdi bu şey:

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

Bir golf şeklidir

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

Sırasıyla, iki karo girdisi verildiğinde, bu iki girdi için olası tüm karo sonuçlarını içeren bir İlişkilendirme (diğer dillerdeki bir hashpa veya tablo olarak adlandırırsınız) döndüren bir işlevdir. Tüm işlevlerin nasıl uygulandığını anlamak için, böyle bir işlevin ilk argümanına #ve ikincisi ile erişilebileceğini bilmeniz gerekir #2. Ayrıca, ##size argümanları "uyarmak" için kullanılabilecek her iki argüman dizisini verir.

  • 0: basittir, sadece bir sabit döndürür {0, 0}ve bunu zdaha sonra kullanmak üzere tahsis ederiz (örn. uzay döşemesinde).
  • 1: aslında sadece {1,1}, ama buna sahip zolmak kısaltılmıştır 1+z. Bunu da kaydederiz o, çünkü her iki çıktının aynı olduğu tüm döşemeler için kullanışlı olacaktır.
  • +: Burada diziden faydalanıyoruz. {##}aynıdır {#,#2}ve her iki girişi de değişmeden geçer.
  • \: İki argümanı değiştiriyoruz {#2,#}.
  • U: Şimdi faydalanabiliriz o. o#2demek oluyor {1,1}*#2ki en üst argümanı her iki çıktının içine koyduk.
  • ): Sol argüman için Dengi olarak: o#.
  • !: Bitwise değil Mathematica can sıkıcı, ama biz sadece hiç var çünkü 0ve 1biz sadece her iki girdileri çıkarabilir 1(böylece onları tersini) ve bunları geçmektedir: 1-{##}.
  • &: Bu oldukça şık. İlk önce bitsel olarak ve bunun için 0ve 1çarpma ile aynı olduğunu fark ettik . Ayrıca, o##aynıdır o*#*#2.
  • |: Yine eşdeğer bir fonksiyon kullanıyoruz. Bitsel veya Maxbu durumda olduğu gibi aynı , bu nedenle Maxgiriş bağımsız değişkenlerine uygulanır ve sonucu çarpılır {1,1}.
  • ^: Xor için bulduğum en kısa fark, farkı bulmak ve kareyi almak (pozitifliği sağlamak için), bu yüzden aldık o(#-#2)^2.

Bu fonksiyon tamamlanıncaya ve getiri biz ilgilendiğiniz eleman çıkarıp depolamak için geçerli hücrenin karakterini kullanmak tam dernek sonra rve b. Bunun aynı zamanda kullanılan adsız fonksiyonun döndürdüğü değer olduğuna dikkat edin MapIndexed, bu nedenle haritalama bana tüm sonuçların bir ızgarasını verecektir.

Çıkış işleme

MapIndexedbirinci boyutun yatay ızgara koordinatına tekabül ettiği (önceki aktarımı hatırlayın), ikinci boyut dikey ızgara koordinatına karşılık gelir ve üçüncüsü alt ya da sol çıktımız olup olmadığını gösterir. Bunun ayrıca kurtulmamız gereken giriş satırı ve sütunu içerdiğini unutmayın. Böylece alt sıranın alt çıktısına erişiriz.

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

ve son sütunun sağ çıktısı

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

Bu 2;;, ikinci ile son eleman arasındaki bir aralıktır.

Son olarak, tüm argümanlarını arka arkaya basan ( ikinci seviye için sözdizimsel şeker olarak Printkullananlar) her ikisine de başvuruyoruz (ve iki ayrı ifadeye uygulandığından, alt ve sağ çıktı).@@@Apply


8

C, 332 309 272 270 266 259 247 225 bayt

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

Sonuçları burada online olarak görüntüleyin !

Bu void f(char*, char*, char*), tahtayı ilk giriş, sonra üst giriş satırı ve ardından sol giriş satırı olarak alması gereken bir işlevi tanımlar .

İşte test etmek için kullandığım şey:

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

Böylece, Sp3000's 2 bit çarpanı girerek:

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

Biz alırız:

00001001
11111111

Başka bir kayda göre, Sp3000'in yarı toplayıcı aklında, tam bir toplayıcı görmek istiyorum ... Sizlerden biri yaptı! Sistemin bir programlama dili olarak durduğunu sanmıyorum, ama çok ilginçti. Bu metagolf için mükemmel bir hedef gibi gözüküyor!

Kısa Bir Açıklama:

İşte çözülmüş, yorumlanmış kod:

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

Biz iterate üzerinde c, yeniden yazma, (daha sonra yukarıdan aşağıya) soldan sağa tölçüm girişlerini her zaman ve içine itti bir en sağdaki çıkışı dışarı iterek ldize. Biz üst satırı değiştirmek gibi bu hayal cile 1'ler ve 0' iteratif s ve sağda dışarı itilir bit takip edilmesi sağlanmaktadır.

İşte daha görsel bir dizi, satır satır:

 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.

Bu açıkçası farklı semboller ve boyutlarla daha da karmaşıklaşıyor, ancak ana fikir geçerli. Bu sadece işe yarar, çünkü veri asla akmaz veya kalmaz.


Golf oynamak için çok fazla potansiyel var! Başlığını değiştirerek başlayın fiçin f(c,t,l)char*c,*t,*l(dönüş türü umurunda değildir).
FUZxxl

@ FUZxxl Birisi sohbette bundan bahsetti, ama ben işe yaramadı. Bu davranış standart mı? LLVM bu çizgiyle en az 2 hata atar.
BrainSteel

Üzgünüm. Olmalıydı f(c,t,l)char*c,*t,*l;. C11 modunda derlemeyin, çünkü dönüş tipini düşürmemize izin veren açık int kuralı bu revizyona bırakılmıştır.
FUZxxl

@ FUZxxl C99'da da başarısız görünüyor. Aslında, derleyiciyi kurduğum her mod bu kodu reddetti.
BrainSteel

Hemen noktalı virgül eklediniz mi *l? Makinemde C99 modunda derliyor.
FUZxxl

7

Python 2, 316 bayt

Bu işlev 10 fayans lambda işlevi oluşturur, ardından mantık durumlarını güncelleyerek ızgarayı yineler. Son dikey ve yatay mantık durumları daha sonra yazdırılır.

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)

Testleri de içeren kodlanmamış kod:

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(SP3000 tarafından 2 diğer testler de dahil) dosyası:

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

Test çıkışı:

------------------
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 bayt

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

Cidden CH, eğer bu bir oyuncak değilse, bazı oyuncak fabrikalarını çalmaya başlamalısın.

Artık daha golf oynadı ve daha az verimli, ancak yine de CarpetPython'a yetişmedi. Gibi giriş f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010"), çıkış iki dizenin bir demet. Tahtanın yine de yeni bir çizgisi olmadığından emin olun, bu da işleri kıracak.

Test programı

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

Ayrıca tüm olası durumları ile test edebilirsiniz test_all().

Ekstra test durumları

Yarı toplayıcı

İşte en üst soldaki bitleri ekleyen ve çıktısını alan yarım bir toplayıcı <input bit> <carry> <sum>:

+))
U&+
U+^

Testler:

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

Girdilerin ikinci / üçüncü bitleri değişmiş olsa bile çıktı aynı olmalıdır.

Sağa kaydırma

Verilen abc / def, bu çıktılar fab / cde:

\\\
\++
\++

Testler:

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

3-bit sıralayıcı

İlk üç biti, son üç bite dönüştürür. Sağ çıktı önemsiz.

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

Testler:

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 bitlik 2 bit çarpanı

İlk sayı olarak ilk 1 / 2., ikinci sayı olarak da 3. / 4. sırada yer alır. Son dört bit bitine çıktı verir. Sağ çıktı önemsiz.

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

Düzenleme: Bir sütun ve iki satır attı.

Testler:

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

Şu anda bunu azaltmak için muhtemelen çok fazla yer var, ama bu gerçekten ilginçti. İki fonksiyon var. D işlevi işçidir ve f karşılaştırıcıdır.

D işlevi 3 karakter, Gates, Top ve Left ile çağrılır. Gates, genişlik tarafından belirlenen bir matrise yerleştirilir.

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

Biraz biçimlendirilmiş

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

Bazı testler

> 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.