Một máy tính cổng logic đơn giản


9

Nhiệm vụ của bạn, nếu bạn chọn chấp nhận nó, là xây dựng một bộ đánh giá sự thật đơn giản cho các toán tử logic sau:

----------------------------------------------------------------------------------
  Logical Name          |  Gate Name   |  Symbol  |  Symbol Name  |  Truth Table
----------------------------------------------------------------------------------
  Identity              |  is          |          |  (none)       |  10
  Negation              |  not         |    ~     |  tilde        |  01
  Conjunction           |  and         |    &     |  ampersand    |  1000
  Disjunction           |  or          |    |     |  pipe         |  1110
  Negative Conjunction  |  nand        |    ^     |  caret        |  0111
  Joint Denial          |  nor         |    v     |  "vee"        |  0001
  Exclusive Disjunction |  xor         |    x     |  "ecks"       |  0110
  Equivalence           |  equals/xnor |    =     |  equals       |  1001
  Implication           |  implies     |    >     |  greater than |  1011

Các bảng chân lý theo thứ tự sau:

  1. 1 1
  2. 1 0
  3. 0 1
  4. 0 0

Đầu vào sẽ có một chuỗi đơn giản là 0, 1 và ký hiệu. Bạn có thể chấp nhận đầu vào dưới dạng tham số hoặc đọc từ người dùng trên stdin. Dưới đây là một số cặp đầu vào / đầu ra mẫu:

Input: 1
Output: 1

Input: ~1
Output: 0

Input: 0|1
Output: 1

Input: 1>0
Output: 0

Toán tử đơn nguyên (phủ định) sẽ luôn xuất hiện trước giá trị boolean, trong khi các toán tử nhị phân sẽ luôn xuất hiện giữa hai giá trị boolean. Bạn có thể cho rằng tất cả các đầu vào sẽ hợp lệ. Chuỗi là chuỗi ASCII thông thường.

Nếu bạn thích, bạn có thể sử dụng T và F thay vì 1 và 0. -6 cho số ký tự của bạn nếu bạn hỗ trợ cả hai.

Đây là : mã ngắn nhất trong bất kỳ ngôn ngữ nào thắng!


3
Tôi tin rằng ^'s tên biểu tượng nên nói caret .
FireFly

3
@FireFly Haha, bạn nói đúng. Quá gần bữa trưa! Cảm ơn.
asteri

Câu trả lời:


6

APL (45 - 6 = 39)

⍎(1+9≠L)⌷¨↓⍉Z⍪⍉⍪'10∧∨⍲⍱≠≤*'[L←'TF&|^vx>'⍳Z←⍞]

Hỗ trợ TFlà đầu vào nhưng sẽ luôn luôn đầu ra 0hoặc 1.

Giải trình:

  • Z←⍞: đọc một dòng và lưu trữ nó trong Z
  • L←'TF&|^vx>'⍳Z: lấy chỉ mục 'TF&|^vx>'cho từng nhân vật Z, đưa ra 9nếu nhân vật không ở trong 'TF&|^vx>'.
  • '10∧∨⍲⍱≠≤*'[... ]: tìm ký tự tương ứng trong '10∧∨⍲⍱≠≤*'. (Vì vậy, các ký tự không có trong danh sách đầu tiên trở thành *).
  • ↓⍉Z⍪⍉⍪: biến điều này thành một ma trận, đặt bản gốc ( Z) lên trên nó và chia nó thành một danh sách các chuỗi, trong đó ký tự đầu tiên là bản gốc và ký tự thứ hai là bản dịch của nó, nếu có.
  • (1+9≠L)⌷¨: cho mỗi chuỗi này, lấy ký tự đầu tiên nếu không có bản dịch (nếu L=9ở vị trí đó) và ký tự thứ hai nếu có.
  • Ví dụ: nếu đầu vào là T|0, 1∨0bây giờ chúng ta sẽ có biểu thức APL tương ứng
  • : đánh giá

Lưu ý: ~=đã làm điều đúng đắn để họ không cần phải thay thế bởi bất cứ điều gì.


Rất đẹp! Đây là một cách tiếp cận dịch sang APL-and-eval, phải không? Tôi đã suy nghĩ về cách tiếp cận dựa trên gerund trong J, nhưng tôi không biết cách khéo léo tách các toán hạng. : \
FireFly

Tại sao thao tác ma trận khi bạn chỉ cần thêm quy tắc dịch cho các ký tự không thay đổi như thế ⍎'1010~∧∨⍲⍱≠=≤'['10TF~&|^vx=>'⍳⍞]nào? (Điểm 33-6 = 27)
TwiNight

8

C - 165 127

Đó là niềm vui! Bảng tra cứu đơn giản dựa trên phần bù cố định cho phần tra cứu.

main(){
  char*s="100011001110110v& x = |^> /~",
       t[6]="0/xxx",
      *u= strchr((gets(t+2),t),0)-3;
  putchar(strchr(s,u[1])[*u*2+u[2]-159]);
}

Vì một số lý do getskhông được khai báo ngầm, vì vậy khi tôi xóa phần bao gồm tôi phải đổi gets(t+2)thành (gets(t+2),t)(hoặc tương tự ở nơi khác, chi phí càng nhiều).


Giải trình

Trước hết, vì các bảng chân lý cho các toán tử có nhiều ký tự chồng chéo, chúng tôi muốn lưu trữ các bảng tra cứu theo cách để chúng tôi cho phép chồng lấp. Đây là cách tôi chọn để lưu trữ chúng:

v    &    x    =    |    ^    >       ~     (operation)
1000 0001 0110 1001 0111 1110 1101 01 10    (truth table [order 00,01,10,11])
0    1    3    5    7    8    9    B  D     (offset in LUT below)

0123456789ABCDE   (offsets)
100011001110110   (values)

Tiếp theo, chúng tôi muốn ánh xạ các ký hiệu toán tử tới các độ lệch này. Chúng tôi thực hiện điều này bằng cách lưu trữ các ký hiệu toán tử trong cùng một chuỗi ở phần bù cố định từ dữ liệu LUT (cụ thể là 16 ký tự sau, tức là ngay sau dữ liệu LUT). Quá trình tra cứu là "tìm toán tử trong s, trừ 16, thêm left*2+right(toán hạng trái / phải). Để tra cứu" thao tác nhận dạng "trống, do cách nạp dữ liệu, toán tử trong trường hợp này sẽ giải quyết bất cứ điều gì t[1]được khởi tạo- -trong trường hợp của chúng tôi /. vì vậy, chúng tôi sử dụng /là chìa khóa bảng tra cứu để đại diện cho hoạt động sắc. Khi chúng tôi xử lý các unary ~hoạt động " left" (để tính toán tra cứu đề cập trước đó) luôn luôn là cùng này / . /sẽ xảy ra là một trong ít hơn0ASCII-khôn ngoan, nghĩa là khi chúng ta bù cho các chữ số ASCII \sẽ đại diện -1. Dấu gạch chéo trong khu vực phím bảng tra cứu (ký tự thứ hai đến cuối cùng s, nghĩa là) được định vị để bù cho điều này.

Tiếp theo, xử lý đầu vào. Đầu vào có độ dài động, nhưng sẽ dễ dàng hơn nếu chúng ta có các tên tĩnh cụ thể cho toán hạng bên trái, toán tử và toán hạng phải, bất kể đầu vào. Nếu chúng ta giả vờ rằng chúng ta có thể đọc đầu vào từ phải sang trái, thì điều này về cơ bản sẽ xảy ra một cách tự động - toán hạng bên phải luôn là ký tự ngoài cùng bên phải, toán tử (nếu có) là từ thứ hai sang phải, toán hạng bên trái (nếu có ) là thứ ba đến bên phải. Để có thể lập chỉ mục chuỗi như thế này, chúng tôi sử dụng strchrđể xác định vị trí của bộ \0kết thúc ( - 3để đơn giản hóa việc lập chỉ mục). Điều này cho thấy tại sao t[0]t[1]trở thành toán hạng / toán tử bên trái tương ứng khi đầu vào là 1 hoặc 2 ký tự.

Đặt nó lại với nhau, đầu ra sẽ được putchar(strchr(s,u[1])[(u[0] - '0')*2 + (u[2] - '0') - 15]), nhưng một số tái cấu trúc và liên tục gấp thay vào đó giúp chúng ta ngắn hơn putchar(strchr(s,u[1])[u[0]*2+u[2]-159]).


Bạn có thể giải thích làm thế nào mà làm việc?
Julian Kuhn

Sự thật chồng chéo bảng là một ý tưởng tuyệt vời. Tôi sẽ không bao giờ nghĩ về điều đó bản thân mình. :)
asteri

Ngoài ra việc đọc từ phải sang trái. Tôi biết đầu vào và định vị có độ dài thay đổi sẽ đặt ra một thách thức và đó là một cách tuyệt vời để giải quyết nó. Thực sự xuất sắc suy nghĩ ra khỏi hộp. Bạn muốn làm việc trong nhóm phát triển của tôi? Haha
asteri

4
Tôi nghĩ rằng nhiều câu trả lời nên có giải thích như thế này. Giúp những người trong chúng ta vẫn đang học một chút đáng kể! (Và bởi những người vẫn đang học hỏi khá nhiều có nghĩa là tất cả mọi người)
agweber

@agweber: Thật tuyệt khi nghe, tôi hơi lo lắng về lời giải thích của mình. Và vâng, có lẽ tất cả mọi người ở đây đang trong giai đoạn "vẫn đang học" .. tốt, ít nhất tôi biết tôi.
FireFly

4

Tcl, 212 208-6 = 202

proc o n\ e {proc $n a\ b expr\ $e}
o > {$a<=$b}
o v {!($a|$b)}
o x {$a^$b}
o ^ {!($a&$b)}
namespace pat tcl::mathop 
lmap o\ b [lassign [split [string map {~0 1 ~1 0} $argv] {}] a] {set a [$o $a $b]}
puts $a

Ung dung:

# Defines an operator
proc operator {name expression} {
    proc $name {a b} "expr $expression"
}
operator > {$a<=$b}
operator v {!($a|$b)}
operator x {$a^$b}
operator ^ {!($a&$b)}
# Call the commands in ::tcl::mathop if the command is not in the global namespace
namespace path tcl::mathop
# lmap instead foreach
# assume that we only got 1 argument.
foreach {op b} [lassign [string map {{~ 0} 1 {~ 1} 0} [split $argv {}]] a] {
   set a [$op $a $b]
}
puts $a

Tôi nghĩ rằng dòng foreach cần một số lời giải thích:

  • split $argv {} chia chuỗi đầu vào (thực ra là một danh sách, nhưng mã golf) thành các ký tự của nó.
  • string map {{~ 0} 1 {~ 1} 0} ...lấy một chuỗi và thay thế ~ 0bằng 1~ 1với0
  • lassign ... a lấy phần tử đầu tiên của danh sách và gán nó cho biến a, trả về phần còn lại.
  • foreach {op b} ... {code}đi qua danh sách và mất 2 yếu tố mỗi lần: opb
  • set a [$op $a $b]thực hiện lệnh trong biến op, lưu trữ kết quả tronga

3

JavaScript - 107 105 ký tự

alert((x=eval(prompt().replace(/v/,'|~').replace(/\^/,'&~').replace(/x/,'^').replace(/=/,'==')))!=-1?x:0)

Haha, tốt lắm. Thật tiện dụng. Tôi thậm chí không nghĩ đến eval()khi tôi làm điều này. Chỉ cần cho tôi một chút để về nhà và kiểm tra nó.
asteri

1
nand = &~và cũng không = |~?
Julian Kuhn

@Johannes: Nó không thực sự &~|~, nhưng NAND chỉ là nghịch đảo của AND. Vì vậy, đảo ngược một trong các bit cũng làm đảo ngược kết quả.
Chương trìnhFOX

3

Befunge-98 - 104 101 98-6 72

... bởi vì mọi tác vụ đều cần một giải pháp esolang .. bản dịch triển khai C của tôi, nhưng thay vào đó xử lý từng ký tự một.

#v~
2_vp5a00+*2%2\p10\%
0:<+1_v#-g5\g1
1_|#:\</2\-
.@>2%
 v   ~x^&=.>  |

Thực tế thú vị: thay đổi @thành a,$và bạn nhận được một REPL không bao giờ thay thế (tuy nhiên, nếu bạn làm điều này, bạn sẽ nhận thấy rằng danh tính thực sự là "lặp lại lệnh cuối cùng với lhs = 0 và rhs = input", điều này chỉ xảy ra mặc định cho danh tính ). REPL không còn nữa.

Ungolfed (phiên bản trước):

v10001100111011v& x = |^>~
  $       1111111111222222
 1234567890123456789012345

 [read input]
> ~ :a- #v_   $ 21g " "- + 0g , @

v p11:   <
   ↑save chr

0 ←lup   [traverse LUT]
> 1+  :11g  \0g -! #v_
 v                  <
    lup chr acc
v>  :3` #v_  $"0"-\2*+

               v>   . , a,
 v       <
v> 9+9+ 21p $

Chỉnh sửa: lấy cảm hứng từ giải pháp của @jpjacobs, giờ đây tôi dựa vào vị trí của các nhân vật trong LUT để thể hiện các bảng chân lý. Ví dụ, |ở vị trí 1110 2 = 14 vì điều này tương ứng với bảng chân lý cho |.


Thật là điền rồ. Ok, mọi giải pháp trong befunge là điên rồ.
Julian Kuhn

2

J - 65 67-6 = 61

Không còn b. Trạng từ. Không tính việc gán chức năng: 67 ký tự cho phiên bản TF, 63 cho phiên bản không TF:

lgcTF =:".@({&('*+-+-<*01',.3 6#'.:')"1@n^:(9>n=:'&|~xv>^FT'&i.)@{.&.>&.;:)
lgc   =:".@({&('*+-+-<*',.3 4#'.:')"1@n^:(7>n=:'&|~xv>^'&i.)@{.&.>&.;:)

LgcTF xử lý cả 0 và 1 cũng như T và F.

Hỗ trợ tất cả cú pháp của J về các chuyến tàu, dấu ngoặc đơn và đánh giá đúng từ trái sang phải (không có quy tắc ưu tiên nào khác).

Tất cả các ký tự không có trong danh sách toán tử + Z không thể được sử dụng, các ký tự khác sẽ hoạt động như trong J tiêu chuẩn (bao gồm các biến).

Sử dụng:

NB.Assign TF anyhow
T=:1 [ F=: 0
lgc 'T & F'
0
lgc ' T ~@& F' NB. negation after and = nand
NB. make a truth table
d=: 0 1
lgc 'd ~@|/ d'
1 0
0 0 
NB. and so on... 

1

Bản thảo 263

Ý tưởng của Firefly được dịch sang Postcript.

{(0/xxx)dup 2 3 getinterval(%lineedit)(r)file exch 
readstring pop length 1 sub 3
getinterval(100011001110110v& x = |^> /~)dup
2 index 1 1 getinterval search pop exch pop exch pop 
length 3 2 roll{}forall exch pop exch 2 mul add 159 sub add 
1 getinterval =}loop

Thụt lề:

%!

{
    (0/xxx) dup 2 3 getinterval
    (%lineedit)(r)file exch % (0/xxx) file (xxx)
    readstring pop
    length % (0/xxx) len(x|xx|xxx)
    1 sub 3 getinterval % (0/x)|(/xx)|(xxx)
    (100011001110110v& x = |^> /~) dup
    2 index 1 1 getinterval search pop % (0/x)|(/xx)|(xxx) s post match pre
    exch pop exch pop % (xxx) s pre
    length 
    3 2 roll {} forall exch pop % s len(pre) u_0 u_2
    exch 2 mul add 159 sub add % s ind
    1 getinterval
    = flush
} loop

1

Befunge-93, 86 ký tự

Hoạt động bằng cách băm ký hiệu thứ hai của đầu vào (tìm một hàm vừa nhỏ gọn vừa tránh va chạm là một số công việc) cho tọa độ ay và lấy ký hiệu thứ nhất và thứ ba mỗi modulo 2 làm hai bit có ý nghĩa nhỏ nhất của tọa độ x, sau đó lấy bất cứ giá trị nào ở vị trí được chỉ định. Hàm băm tốt hơn hoặc phương pháp lưu trữ / giải quyết các bảng chân trị nhỏ gọn hơn chỉ là hai cách có thể giúp người ta cắt giảm độ dài.

~~~\:8/\5%:++00p2%\2%2*+00gg,@
0 1







1001
0001
1101
1

0
0110



1110
1000


0111
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.