Basit bir mantık kapısı hesaplayıcısı


9

Göreviniz, kabul etmeyi seçerseniz, aşağıdaki mantıksal operatörler için basit bir doğruluk değerlendiricisi oluşturmaktır:

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

Doğruluk tabloları aşağıdaki sıradadır:

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

Giriş, 0, 1 ve sembolü içeren basit bir dize olarak gelir. Girişi parametre olarak kabul edebilir veya stdin'deki kullanıcıdan okuyabilirsiniz. İşte bazı örnek giriş / çıkış çiftleri:

Input: 1
Output: 1

Input: ~1
Output: 0

Input: 0|1
Output: 1

Input: 1>0
Output: 0

İkili işleç her zaman boole değerinden önce görünürken, ikili işleçler her zaman iki boole değeri arasında görünür. Tüm girdilerin geçerli olacağını varsayabilirsiniz. Dizeler normal ASCII dizeleridir.

İsterseniz, 1 ve 0 yerine T ve F tuşlarını kullanabilirsiniz.

Bu : herhangi bir dilde en kısa kod kazanır!


3
İnanıyorum ^ki sembol ismi caret demeli .
FireFly

3
@FireFly Haha, haklısın. Öğle yemeğine çok yakın! Teşekkürler.
asteri

Yanıtlar:


6

APL (45-6 = 39)

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

Destekler Tve Fgirdi olarak ama her zaman çıktı 0veya 1.

Açıklama:

  • Z←⍞: bir satırı oku ve kaydet Z
  • L←'TF&|^vx>'⍳Z: 'TF&|^vx>'karakterin girip girmediğini Zvererek, her karakter için dizini girin .9'TF&|^vx>'
  • '10∧∨⍲⍱≠≤*'[... ]: içindeki ilgili karakteri bul '10∧∨⍲⍱≠≤*'. (Yani ilk listede olmayan karakterler olur *).
  • ↓⍉Z⍪⍉⍪: bunu bir matrise dönüştürün, orijinali ( Z) üstüne koyun ve ilk karakterin orijinal ve ikinci karakterin varsa çevirisinin olduğu bir dize listesine bölün.
  • (1+9≠L)⌷¨: Bu dizelerin her biri için, çeviri yoksa ilk karakteri ( L=9o yerde varsa ) ve varsa ikinci karakteri alın.
  • Örnek: Giriş olsaydı T|0, şimdiye 1∨0kadar karşılık gelen APL ifadesi olurdu
  • : eval

Not: ~ve =zaten doğru olanı yapın, böylece hiçbir şeyle değiştirilmeleri gerekmez.


Çok hoş! Bu, APL'ye tercüme et ve değerlendir için bir yaklaşım, değil mi? J'de gerund tabanlı bir yaklaşım düşünüyordum, ancak işlenenleri akıllıca nasıl bölebileceğimi bilmiyorum. : \
FireFly

Neden değişmeyen karakterler için çeviri kuralları ekleyebileceğiniz zaman matris manipülasyonu yapıyorsunuz ⍎'1010~∧∨⍲⍱≠=≤'['10TF~&|^vx=>'⍳⍞]? (Puan 33-6 = 27)
TwiNight

8

C - 165 127

Bu eğlenceliydi! Arama için sabit bir ofsete dayanan düz arama tablosu.

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

Herhangi bir nedenle getsdolaylı olarak beyan edilmez, bu yüzden dahil etmeyi kaldırdığımda (veya başka bir yerde, çok fazla maliyete) gets(t+2)geçmek zorunda kaldım (gets(t+2),t).


açıklama

Her şeyden önce, operatörlerin doğruluk tabloları üst üste binen birçok karaktere sahip olduğundan, arama tablolarını örtüşmeye izin verecek şekilde saklamak istiyoruz. Bunları nasıl saklamayı seçtim:

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)

Ardından, operatör sembollerini bu ofsetlerle eşlemek istiyoruz. Bunu, LUT verilerinden sabit bir ofsette (yani, 16 karakter sonra, yani doğrudan LUT verilerinden sonra) aynı dizede operatör sembollerini saklayarak yaparız. Arama işlemi "operatörü bul s, çıkart 16, ekle left*2+right(sol / sağ işlenen). Boş" kimlik işlemi "araması için, girişin getirilme şekli nedeniyle bu durumda operatör t[1], başlatılan her şeye davamızı laflar /. Böylece, kullandığımız /kimlik çalışmasını temsil etmek Arama tablosu anahtarı olarak. biz tekli işlemek ~operasyonu " left(arama hesaplama önce de belirtildiği üzere)" her zaman bu aynıdır / . /az birini olur0ASCII-akıllıca, yani ASCII basamaklarını telafi ettiğimizde \temsil eder -1. Arama tablosu anahtar alanındaki eğik çizgi (ikinci-son karakter s, yani) bunu telafi etmek için konumlandırılır.

Sıradaki girdi işleme. Girdinin dinamik uzunluğu vardır, ancak girdiden bağımsız olarak sol işlenen, operatör ve sağ işlenen için belirli statik adlarımız varsa daha kolay olurdu. Girişi sağdan sola okuyabileceğimizi iddia edersek, bu temelde otomatik olarak gerçekleşir - sağ işlenen her zaman en sağdaki karakterdir, operatör (varsa) soldan ikinci işleyicidir (varsa) ) üçüncü-sağdan. Dizeyi bu şekilde dizine ekleyebilmek strchriçin \0sonlandırıcıyı bulmak için kullanırız ( - 3dizine eklemeyi basitleştirmek için). Bu, giriş 1 veya 2 karakter olduğunda neden t[0]ve t[1]sol işlenen / operatör haline geldiğini gösterir .

Bir araya getirmek, çıktı olurdu putchar(strchr(s,u[1])[(u[0] - '0')*2 + (u[2] - '0') - 15]), ancak bazı yeniden düzenleme ve sürekli katlama bunun yerine bizi kısaltır putchar(strchr(s,u[1])[u[0]*2+u[2]-159]).


Bunun nasıl çalıştığını açıklayabilir misiniz?
Johannes Kuhn

Doğruluk tablosu çakışması parlak bir fikirdi. Bunu asla kendim düşünmezdim. :)
asteri

Ayrıca sağdan sola okuma. Değişken uzunluk girişinin ve konumlandırmanın zor olacağını biliyordum ve bu onu çözmenin harika bir yolu. Gerçekten mükemmel hazır düşünme. Gelişim ekibim üzerinde çalışmak ister misiniz? Haha
Asteri

4
Bence daha fazla cevabın bunun gibi açıklamaları olmalı. Hala hatırı sayılır bir şey öğrenenlere yardım eder! (Ve hala neredeyse öğrenenler tarafından herkes anlamına gelir)
agweber

@agweber: Bunu duymak güzel, açıklamam için biraz endişeliydim. Ve evet, muhtemelen buradaki herkes "hala öğreniyor" aşamasındadır .. en azından ben olduğumu biliyorum.
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

Ungolfed:

# 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

Bence foreach hattının bir açıklamaya ihtiyacı var:

  • split $argv {} giriş dizesini (aslında bir liste, ancak kod golf) karakterlerine böler.
  • string map {{~ 0} 1 {~ 1} 0} ...bir dize ve yerine geçer sürer ~ 0ile 1ve ~ 1ile0
  • lassign ... a listenin ilk öğesini alır ve a değişkenine atar, geri kalanını döndürür.
  • foreach {op b} ... {code}listeye girer ve her seferinde 2 öğe alır: opveb
  • set a [$op $a $b]komutu değişkende çalıştırır, opsonucua

3

JavaScript - 107105 karakter

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

Haha güzel. Çok kullanışlı. Bunu eval()ne zaman uydurduğumu bile düşünmedim . Eve gitmem ve test etmem için bana biraz ver.
asteri

1
nand = &~ve ne de = |~?
Johannes Kuhn

@Johannes: Gerçekten değil &~ve |~fakat NAND sadece tersidir VE. Yani, bitlerden birini ters çevirmek sonucu da tersine çevirir.
ProgramFOX

3

Befunge- 98-10410101 98-6 72

... çünkü her görevin bir esolang çözümüne ihtiyacı var .. C uygulamamın çevirisi, ancak karakterleri teker teker işlemek.

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

Eğlenceli bir gerçek: Değişiklik @için a,$ve bunu yaparsanız o kimlik aslında sadece kimlik varsayılan olur, "lhs = 0 ve rhs'sine = girdi ile son komutu tekrarlamak" olduğunu fark edeceksiniz olsa (yerine bir fantezi bitmeyen repl olsun ). REPL artık değil.

Ungolfed (önceki sürüm):

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 $

Düzenleme: @jpjacobs'un çözümünden esinlenerek, artık LUT'taki karakterlerin pozisyonlarını doğruluk tablolarını temsil etmeye güveniyorum. Örneğin, |1110 pozisyonunda 2 = 14 çünkü bu doğruluk tablosuna karşılık gelir |.


Bu çılgınca. Tamam, aklınızdaki her çözüm çılgın.
Johannes Kuhn

2

J - 65 67-6 = 61

Artık b. Zarf. Fonksiyonun atamasını saymadan: TF versiyonu için 67 karakter, TF olmayan versiyon için 63 karakter:

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

LgcTF, 0 ve 1'in yanı sıra T ve F'yi de işler.

J'nin tüm sözdizimini trenler, parantez açısından destekler ve kesinlikle sağdan sola değerlendirir (başka öncelik kuralı yoktur).

Operatör listesinde olmayan + Z karakterleri kullanılamaz, diğerleri standart J'de (değişkenler dahil) hareket eder.

Kullanımı:

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

PostScript 263

Firefly'ın fikri Postscript'e çevrildi.

{(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

Girintili'ye:

%!

{
    (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 karakter

Ay koordinatı için girişin ikinci sembolünü (hem kompakt hem de kaçınılmaz çarpışmalardan oluşan bir işlev bulmak) bir işti ve her bir modulo 2'yi ilk ve üçüncü sembolleri x koordinatının en az iki biti olarak alarak çalışır, belirtilen konumda ne olursa olsun değer elde etmek. Daha iyi bir hash fonksiyonu veya doğruluk tablolarını saklamak / ele almak için daha kompakt bir yöntem, uzunluğu kısaltmanın sadece iki olası yoludur.

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







1001
0001
1101
1

0
0110



1110
1000


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