Lưới dựa trên logic kỹ thuật số (gạch Duodyadic)


33

Gạch duodyadic là các loại khối chức năng vuông có hai đầu vào, một từ phía trên và một từ bên trái của chúng và có hai đầu ra, một ở phía bên phải và một ở phía dưới. Mỗi đầu ra của chúng là một chức năng riêng biệt của cả hai đầu vào của chúng.

Ví dụ: nếu #đại diện cho một ô chung, đầu ra bên phải Rlà một hàm fcủa các đầu vào TL, và đầu ra dưới cùng Blà một hàm khác gcủa TL:

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

(Các ô được gọi là "bộ đôi" vì có hai hàm và "dyadic" vì cả hai hàm có hai đối số .)

Các lát sau đó có thể được ghép lại với nhau trên một lưới, các đầu ra của một ô sẽ đi trực tiếp vào các đầu vào của các ô mà nó lân cận. Ví dụ ở đây, đầu ra bên phải của bên trái #đi vào đầu vào bên trái của bên phải #:

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

Bạn có thể tưởng tượng rằng được cung cấp một bộ gạch duodyadic, mỗi loại có chức năng cụ thể, các tác phẩm phức tạp (và có khả năng hữu ích) có thể được thực hiện.

Trong thử thách này, chúng ta sẽ chỉ quan tâm đến tập hợp mười ô ghép dựa trên logic truyền thống , trong đó tất cả các đầu vào và đầu ra là các số nhị phân một bit (số không hoặc số một). Chúng tôi sẽ sử dụng một ký tự ASCII riêng để biểu thị từng loại hình xếp.

Các ký tự gạch và quan hệ đầu vào-đầu ra của chúng như sau:
( Tdành cho đầu vào trên, Lcho đầu vào bên trái, Rcho đầu ra bên phải, Bcho đầu ra dưới cùng.)

  1. Không: 0hoặc (không gian) → R = 0,B = 0
  2. Một: 1R = 1,B = 1
  3. Chữ thập: +R = L,B = T
  4. Gương: \R = T,B = L
  5. Chỉ trên cùng: UR = T,B = T
  6. Chỉ còn lại: )R = L,B = L
  7. Không phải: !R = not L,B = not T
  8. Và: &R = L and T,B = L and T
  9. Hoặc: |R = L or T,B = L or T
  10. Xor: ^R = L xor T,B = L xor T

Thử thách

Viết chương trình hoặc hàm lấy trong một lưới hình chữ nhật gồm các ký tự 0 1+\U)!&|^đại diện cho một "mạch" được tạo bằng cách sử dụng mười ô xếp hình dựa trên logic. Bạn cũng cần phải có hai chuỗi 0's và 1'; một sẽ là cột đầu vào bên trái và một sẽ là hàng đầu vào hàng đầu. Chương trình / chức năng của bạn cần in / trả về hàng đầu ra dưới cùng và cột đầu ra bên phải (cũng trong 0's và 1').

Ví dụ, trong lưới này

+++
+++

tất cả các đầu vào chảy thẳng qua lưới đến đầu ra

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

vì vậy, một đầu vào của 010/ 01would have output 010/ 01:

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

Đầu ra chính xác của chương trình của bạn sẽ là [bottom output row]\n[right output column]hoặc [bottom output row]/[right output column]:

010
01

hoặc là

010/01

Nếu bạn đã viết một hàm, bạn có thể trả về hai chuỗi trong một tuple hoặc danh sách (hoặc vẫn in chúng).

Chi tiết

  • Lấy ba đầu vào dưới dạng chuỗi theo bất kỳ cách hợp lý nào (tốt nhất là trong lưới thứ tự, hàng trên cùng, cột bên trái): dòng lệnh, tệp văn bản, sdtin, hàm arg.
  • Bạn có thể giả sử chiều dài hàng và cột đầu vào sẽ khớp với kích thước lưới và sẽ chỉ chứa 0's và 1'.
  • Lưới của bạn phải sử dụng các ký tự thích hợp ( 0 1+\U)!&|^). Hãy nhớ điều đó 0 có nghĩa là điều tương tự.

Các trường hợp thử nghiệm

(Đọc I / O là top/ leftbottom/right .)

Không

&!

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

Tất cả những người:

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

Bất kỳ đầu vào sẽ dẫn đến 1111/ 1111.

Xor từ Nand: (lưu ý cột dấu cách)

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

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

Zig zag:

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

Bit đầu tiên của đầu vào bên trái trở thành bit cuối cùng của đầu ra bên phải. Mọi thứ khác là0 .

000000000000/ 000000000000000/ 000
000000000000/ 100000000000000/001

Lan truyền:

)))
UUU
U+U
U+U
UUU

Bit đầu tiên của đầu vào bên trái đi đến tất cả các đầu ra.

000/ 00000000/ 00000
000/ 10000111/11111

Đây là một pastebin của tất cả các trường hợp kiểm tra lưới 1 × 1.

Chấm điểm

Đệ trình ngắn nhất tính bằng byte thắng.

Tiền thưởng: Bạn có thể tạo ra những "mạch" thú vị nào?

PS Đừng bận tâm về "gạch duodyadic" của Google. Tôi đã thực hiện chúng ngày hôm qua; D
Nếu bạn muốn thảo luận mở rộng ý tưởng này thành ngôn ngữ lập trình chính thức, hãy đến với phòng chat này .


11
+1 cho một thử thách thú vị nhưng cũng bởi vì bạn đã phát minh ra gạch duodyadic, điều này thực sự tuyệt vời.
Alex A.

3
+1 Nó thực sự hoàn toàn vô dụng đối với google này: goo.gl/zuqfdW . Thử thách tốt đẹp!
BrainSteel 20/03/2015

Tôi với họ. Tôi quan tâm nhiều đến gạch của bạn như một ngôn ngữ lập trình hơn là trong thử thách golf cụ ​​thể này. PS: Có 16 ô có thể, do đó, việc đưa ra các chữ cái / tên cho sáu ô còn lại sẽ rất gọn gàng.
Sparr

Thật thú vị khi có các khối đầu ra / đầu vào từ các hướng khác nhau, bởi vì nếu không, bạn không thể thực hiện chốt vì mọi thứ đều chảy theo hướng xuống bên phải.
Sp3000 20/03/2015

2
Bạn có thể thay đổi T / B thành U (p) / D (riêng), để chúng ta có thể có F / B theo cách tương tự với ký hiệu Cube của Rubik, sau đó. . . khối ba tầng?
Soham Chowdhury

Câu trả lời:


8

Kim tự tháp, 122

Loại quái vật. Sử dụng đơn giản là đệ quy, không có gì lạ mắt như lập trình động.

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

Trình diễn trực tuyến .

Đầu vào theo cách sau: Đầu tiên là lưới (không thoát, không có ký hiệu phụ) và sau đó là hai dòng đầu vào, ví dụ (Zig zag)

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

8

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

Đây là một ký tự Unicode sử dụng riêng mà Mathicala sử dụng làm siêu ký tựT , tức là nó là toán tử chuyển vị.

Đây là một phiên bản dễ đọc hơn:

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

Đây là một hàm không tên, lấy ba chuỗi cho đầu vào dạng lưới, đầu trên và bên trái và in các đầu ra dưới cùng và bên phải.

Giải trình

Chúng ta hãy thực hiện từng bước này (Tôi sẽ cố gắng không nắm bắt bất kỳ kiến ​​thức Mathicala nào). Bạn cần phải đọc mã trở lại phía trước. Thuật toán cơ bản chỉ quét qua các dòng tính toán từng hàm và lưu trữ kết quả trongf được truy cập bởi các ô tiếp theo.

Xử lý đầu vào

Đó là bit này:

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

Điều này chỉ đơn thuần phân chia lưới thành một danh sách các ký tự lồng nhau (lưu ý rằng tôi đã xác định hlà bí danh cho Charactermột nơi nào đó trong mã) và sau đó thêm một hàng và một cột với các đầu vào. Điều này hoạt động, bởi vì 10cũng là tên của các hàm chức năng không đổi, vì vậy thực sự đặt chúng vào có tác dụng tương tự như cho ăn các đầu vào theo cách thủ công. Vì đây là các hàm nên về mặt kỹ thuật, chúng sẽ lấy đầu vào từ bên ngoài lưới, nhưng vì chúng là các hàm không đổi không thành vấn đề. Góc trên bên trái được một0 nhưng điều này khá tùy tiện vì kết quả của ô đó không bao giờ được sử dụng.

Cũng lưu ý chuyển vị. Việc thêm các cột cần nhiều ký tự hơn là thêm các hàng, vì vậy tôi hoán chuyển lưới sau khi thêm hàng trên cùng. Điều này có nghĩa là trên / dưới và trái / phải được hoán đổi cho phần chính của chương trình, nhưng chúng hoàn toàn có thể trao đổi nên không thành vấn đề. Tôi chỉ cần đảm bảo trả lại kết quả theo đúng thứ tự.

Giải quyết lưới điện

(Phần này hơi lỗi thời. Sẽ sửa một khi tôi thực sự chắc chắn mình đã chơi golf.)

Tiếp theo, chúng tôi chạy MapIndexedqua cấp độ bên trong của danh sách lồng nhau này. Điều này gọi hàm ẩn danh được cung cấp làm đối số đầu tiên cho mỗi ký tự trong lưới, cũng cung cấp cho nó một danh sách với hai tọa độ hiện tại. Lưới được sắp xếp theo thứ tự, vì vậy chúng ta có thể tính toán từng ô một cách an toàn dựa trên các ô trước đó.

Chúng tôi sử dụng các biến r(ight) và b(ottom) làm bảng tra cứu cho kết quả của từng ô. Hàm ẩn danh của chúng tôi có tọa độ hiện tại #2, vì vậy chúng tôi nhận đầu vào cho bất kỳ ô nào với

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

Lưu ý rằng trong hàng và cột đầu tiên, điều này sẽ truy cập các giá trị không xác định của rb . Mathematica thực sự không có vấn đề gì với điều đó và sẽ chỉ trả lại cho bạn tọa độ của bạn, nhưng dù sao chúng tôi cũng loại bỏ kết quả này, vì tất cả các ô trong hàng / cột đó là các hàm không đổi.

Bây giờ điều này:

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

Là một hình thức chơi gôn của

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

Đến lượt nó là một hàm, với hai đầu vào ô, trả về một Hiệp hội (bạn gọi nó là hàm băm hoặc bảng trong các ngôn ngữ khác), có chứa tất cả các kết quả ô có thể có cho hai đầu vào này. Để hiểu, làm thế nào tất cả các hàm được thực hiện, bạn cần biết rằng đối số đầu tiên của hàm đó có thể được truy cập #và thứ hai với #2. Hơn nữa,## cung cấp cho bạn một chuỗi cả hai đối số có thể được sử dụng để "tách" các đối số.

  • 0: rất đơn giản, chúng ta chỉ cần trả về một hằng số {0, 0}và cũng gán nó choz việc sử dụng trong tương lai (ví dụ: trong ô không gian).
  • 1: về cơ bản chỉ là {1,1}, nhưng có zđiều này được rút ngắn lại 1+z. Chúng tôi cũng lưu cái này vàoo , vì nó sẽ có ích cho tất cả các ô có cả hai đầu ra giống hệt nhau.
  • +: Ở đây chúng tôi sử dụng trình tự. {##}là giống như {#,#2}và vượt qua cả hai đầu vào thông qua không thay đổi.
  • \: Chúng tôi trao đổi hai đối số, {#2,#} .
  • U: Bây giờ chúng ta có thể sử dụng o. o#2có nghĩa{1,1}*#2 chúng ta chỉ cần đặt đối số hàng đầu vào cả hai đầu ra.
  • ): Tương tự cho đối số bên trái: o# .
  • !: Bitwise không gây khó chịu trong Mathicala, nhưng vì chúng ta chỉ có 01, chúng ta chỉ có thể trừ cả hai đầu vào từ 1( từ đó đảo ngược chúng) và chuyển chúng vào:1-{##} .
  • &: Cái này khá tiện lợi. Đầu tiên chúng tôi nhận thấy rằng bitwise và for 01giống hệt với phép nhân. Hơn nữa, o##cũng giống nhưo*#*#2 .
  • |: Một lần nữa, chúng tôi sử dụng một chức năng tương đương. Bitwise hoặc giống như Maxtrong trường hợp này, vì vậy chúng tôi áp dụng Maxcho các đối số đầu vào và nhân kết quả vào {1,1}.
  • ^: Thời gian ngắn nhất tôi tìm thấy cho xor là lấy sự khác biệt và bình phương nó (để đảm bảo tính tích cực), vì vậy chúng tôi đã có o(#-#2)^2.

Sau khi chức năng này hoàn thành và trả về liên kết đầy đủ, chúng tôi sử dụng ký tự của ô hiện tại để lấy ra phần tử mà chúng tôi quan tâm và lưu trữ nó trong rb . Lưu ý rằng đây cũng là giá trị trả về của hàm ẩn danh được sử dụng trongMapIndexed , vì vậy ánh xạ sẽ thực sự cung cấp cho tôi một lưới tất cả các kết quả.

Xử lý đầu ra

MapIndexedtrả về lưới 3D, trong đó kích thước thứ nhất tương ứng với tọa độ lưới ngang (nhớ chuyển vị trước đó), kích thước thứ hai tương ứng với tọa độ lưới dọc và thứ ba cho biết chúng ta có đầu ra bên dưới hay bên trái. Lưu ý rằng điều này cũng chứa hàng và cột đầu vào mà chúng ta cần loại bỏ. Vì vậy, chúng tôi truy cập đầu ra dưới cùng của hàng dưới cùng với

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

và đầu ra bên phải của cột cuối cùng với

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

Lưu ý rằng 2;; là một phạm vi từ phần tử thứ hai đến phần tử cuối cùng.

Cuối cùng, chúng tôi áp dụng Printcho cả hai thứ đó (sử dụng @@@làm đường cú pháp cho cấp độ thứ hai Apply), chỉ in tất cả các đối số của nó qua lại (và vì nó được áp dụng cho hai biểu thức riêng biệt, sẽ có một dòng mới giữa đáy và đầu ra đúng).


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

Xem kết quả trực tuyến tại đây!

Điều này xác định một hàm void f(char*, char*, char*), sẽ lấy bảng làm đầu vào đầu tiên của nó, sau đó là hàng đầu vào trên cùng, và sau đó là hàng đầu vào bên trái.

Đây là những gì tôi đã sử dụng để kiểm tra nó:

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

Do đó, bằng cách nhập hệ số nhân 2 bit của Sp3000:

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

Chúng tôi nhận được:

00001001
11111111

Một lưu ý khác, với một nửa trình bổ sung của Sp3000, tôi muốn thấy một trình bổ sung đầy đủ ... Một trong số các bạn đã làm điều đó! Tôi không nghĩ hệ thống tự nó là ngôn ngữ lập trình, nhưng nó rất thú vị. Điều này có vẻ như là một mục tiêu tuyệt vời cho metagolf, mặc dù!

Giải thích ngắn gọn:

Đây là mã được làm sáng tỏ, nhận xét:

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

Chúng tôi lặp đi lặp lại c, từ trái sang phải (sau đó từ trên xuống dưới), viết lại các tđầu vào mỗi lần và đẩy ra một đầu ra ngoài cùng bên phải được đưa vào lchuỗi. Chúng ta có thể tưởng tượng điều này khi thay thế hàng trên cùng cbằng 10 là lặp đi lặp lại, và theo dõi của các bit được đẩy ra ngoài ở bên phải.

Đây là một chuỗi trực quan hơn, từng hàng:

 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.

Điều này rõ ràng trở nên phức tạp hơn với các biểu tượng và kích cỡ khác nhau, nhưng ý tưởng trung tâm nắm giữ. Điều này chỉ hoạt động vì dữ liệu không bao giờ chảy lên hoặc trái.


Rất nhiều tiềm năng để chơi golf! Bắt đầu bằng cách thay đổi tiêu đề fthành f(c,t,l)char*c,*t,*l(đừng nói xấu về kiểu trả về).
FUZxxl

@FUZxxl Ai đó đã đề cập đến vấn đề này trong trò chuyện, nhưng tôi không thể làm cho nó hoạt động được. Đây có phải là tiêu chuẩn hành vi? LLVM ném ít nhất 2 lỗi với dòng đó.
BrainSteel

Lấy làm tiếc. Đáng lẽ phải thế f(c,t,l)char*c,*t,*l;. Không biên dịch trong chế độ C11, vì quy tắc int ngầm cho phép chúng ta loại bỏ kiểu trả về đã bị loại bỏ trong bản sửa đổi đó.
FUZxxl

@FUZxxl Nó dường như cũng thất bại trong C99. Trong thực tế, mọi chế độ tôi đặt trình biên dịch đã từ chối mã đó.
BrainSteel

Bạn đã thêm dấu chấm phẩy ngay sau đó *l? Nó biên dịch ở chế độ C99 trên máy của tôi.
FUZxxl

7

Python 2, 316 byte

Hàm này xây dựng 10 hàm lambda gạch, sau đó lặp qua lưới, cập nhật trạng thái logic. Các trạng thái logic dọc và ngang cuối cùng sau đó được in.

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)

Mã không mã hóa bao gồm các bài kiểm tra:

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

Các test.txttập tin (bao gồm 2 bài kiểm tra khác bằng cách 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

Đầu ra thử nghiệm:

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

Nghiêm túc CH, nếu đây chưa phải là đồ chơi, bạn nên bắt đầu gọi cho một số nhà máy sản xuất đồ chơi.

Đã chơi gôn nhiều hơn và kém hiệu quả hơn nhiều, nhưng vẫn chưa bắt kịp với RugPython. Đầu vào như f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010"), đầu ra là một bộ gồm hai chuỗi. Hãy chắc chắn rằng bảng không có một dòng mới, điều này sẽ phá vỡ mọi thứ.

Chương trình kiểm tra

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

Bạn cũng có thể kiểm tra tất cả các trường hợp có thể với test_all().

Trường hợp kiểm tra thêm

Một nửa Adder

Đây là một nửa bổ sung có thêm các bit trên cùng bên trái, xuất ra <input bit> <carry> <sum>:

+))
U&+
U+^

Các xét nghiệm:

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

Đầu ra phải giống nhau ngay cả khi các bit thứ hai / thứ ba của đầu vào bị thay đổi.

Ca phải

Cho abc / def, kết quả này fab / cde:

\\\
\++
\++

Các xét nghiệm:

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

Máy phân loại 3 bit

Sắp xếp ba bit đầu tiên của đỉnh vào ba bit cuối cùng. Đầu ra phải là rác.

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

Các xét nghiệm:

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

Hệ số nhân 2 bit bằng 2 bit

Lấy các bit thứ 1/2 trên cùng là số thứ nhất và các bit thứ 3/4 trên cùng là số thứ hai. Đầu ra cho bốn bit cuối cùng của đáy. Đầu ra phải là rác.

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

Chỉnh sửa: Đánh gôn ra một cột và hai hàng.

Các xét nghiệm:

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

Có lẽ rất nhiều chỗ để giảm điều này vào lúc này, nhưng điều này thực sự thú vị để làm. Có hai chức năng. Hàm d là công nhân và f là bộ so sánh.

Hàm d được gọi với 3 chuỗi, Gates, Top và Left. Cổng được đưa vào một ma trận được xác định bởi chiều rộng.

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

Định dạng một chú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)
}

Một số bài kiểm tra

> 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.