Brainfuck programını doğrulayın


17

Yine başka bir Brainfuck ayrıştırma sorunu, ama bu sefer ... farklı.

Çeşitli ilginç problemleri çözmek için Brainfuck programları yapan şirket olan Infinite Monkeys Incorporated'da çalışıyorsunuz (kazara, daha az değil - şirket rastgele programlar yapıyor). Ancak, sadece Brainfuck'ı çalıştıran hızlı Turing makinelerinizin sözdizimi hatalarıyla ilgili küçük ve pahalı bir sorunu olduğu anlaşılıyor - bir tane yapın ve bilgisayar patlar. Muhtemelen bir tasarım hatasıdır, ancak kimse bunun neden olduğunu bulmak için uğraşmamıştı.

Turing makineleri (özellikle hızlı olanlar) pahalı olduğundan (sonuçta, maliyeti olan sonsuz RAM'e sahip olduklarından), kodu çalıştırmadan önce programın sözdizimi hatalarına sahip olmadığından emin olmak daha iyi olacaktır. Şirketiniz çok sayıda kod çalıştıracaktır, bu nedenle manuel doğrulama çalışmaz. Brainfuck kodu için STDIN'i okuyan ve programda herhangi bir sözdizimi hatası varsa çıkış durumu 0'dan (hata) farklı olarak ayarlanmış bir program yazın (örneğin, ]eşleşme olmadığından sözdizimi hatasıdır [). Program tamamen iyi durumdaysa çıkış durumu 0'a ayarlanmış olarak çıkın.

Programınızın aşağıdakileri içeren hataları doğru bir şekilde fark ettiğinden emin olun: [] . Başka bir bilgisayarın patlamasını istemezdin, değil mi? Oh, ve mümkün olduğunca kısa olduğundan emin olun - patronunuz kısa programlar için para ödüyor (çünkü hızlı olduklarını düşünüyor ya da bir şey). Oh, ve Brainfuck'ta kodlamak zorunda değilsiniz (aslında, Brainfuck çıkış kodlarını desteklemediği için yapamazsınız) - kodunuz normal bilgisayarda çalıştırılacaktır.

Gördüğünüz gibi, işiniz Brainfuck programının "geçerli" (eşleştirilmiş []sembolleri var) olup olmadığını kontrol etmektir . Lütfen Brainfuck programlarının başka karakterleri olabileceğini unutmayın [], bu yüzden sadece başka komutları olduğu için programı reddetmeyin. En küçük kod kazanır, ancak muhtemelen zaten upvotes hakkında daha fazla önem verirsiniz.


1
İşlem çıkış kodu ayarlanmasına izin vermeyen diller ne olacak?
Kendall Frey

1
@KendallFrey: Basit, başka bir şey kullan. Veya GolfScript'te Ruby kodunu gömün. Belki de bu bazı ezoterik programlama dillerini engeller, ama iyi ...
Konrad Borowski

1
Hata kodunu hata durumunda 1'den (elbette 0 olmadığı sürece) başka bir şeye ayarlamak uygun mudur?
marinus

@marinus: Bunu neden isteyeceğini bilmiyorum, ama bence iyi.
Konrad Borowski

@GlitchMr: çünkü o zaman GCD(a,b)bunun yerine kullanabilirsiniz 0 != a || b.
Marinus

Yanıtlar:


6

GolfScript, 18 karakter

.{[]`?)},~](`91?./

Girişteki köşeli parantezler dengeli ise, bu kod çıkış kodu 0 ile başarılı bir şekilde çalışır (ve stdout'a biraz çöp yazdırır). Değilse, sıfır olmayan bir çıkış koduyla başarısız olur ve stderr'e bir hata iletisi yazdırır, örn:

(eval):2:in `/': divided by 0 (ZeroDivisionError)

veya

(eval):1:in `initialize': undefined method `ginspect' for nil:NilClass (NoMethodError)

Meydan okuma, stdout / stderr'e çıktı hakkında hiçbir şey söylemediğinden, bunun uygun olduğunu anladım. Her durumda, bunları her zaman için yeniden yönlendirebilirsiniz /dev/null.

Açıklama:

Kod, {[]`?)},köşeli parantezler dışındaki her şeyi girdiden ayırır ve~ dışındaki ayırır ve sonucu GolfScript kodu olarak değerlendirir. Zor kısmı, dengesiz parantezlerin GolfScript'te (ve gerçekten de kodumda bir tane var!) Mükemmel yasal olmasıdır, bu nedenle kodun çökmesini sağlamak için başka bir yola ihtiyacımız var.

Kullandığım hile, girişin bir kopyasını yığının altında bırakmak, tüm yığını (dengesiz kullanarak ]) bir diziye toplamak ve ilk öğeyi kaydırmaktır. Bu noktada üç şey olabilir:

  • Giriş kapatılmamışsa [, bir öğeyi boş bir diziden çıkarmaya çalışmak yorumlayıcıyı kilitler (bu durumda tam olarak istediğimiz şey budur!)
  • Girişteki braketler dengelenmişse, kaydırılan öğe orijinal giriş dizesi olacaktır.
  • Aksi takdirde (giriş açılmamış ]veya kapatılmamışsa [) bir dizi olacaktır.

Orijinal 14 karakterlik girişim daha sonra, iç içe geçmiş bir dizi olsaydı çökecek olan bir dizeyle kaydırılan değeri karşılaştırdı. Ne yazık ki, bir dize ile düz (veya özellikle boş) bir dizi karşılaştırmak da GolfScript yasal olduğu ortaya çıkıyor, bu yüzden çakmak geçmek zorunda kaldı.

Bunun yerine şu anki gönderimim dizelerden dizileri anlatmak için çok kaba bir yöntem kullanıyor: bunları ortadan kaldırıyor ve [(ASCII kodu 91) ' in ilk oluşumunu bulmaya çalışıyor. değişken bir diziydi. Eğer öyleyse, sıfırı kendisiyle bölmek istenen çökmeyi tetikler.

Ps. Diğer iki 18 karakterlik çözüm:

.{[]`?)},{.}%~](n<

ve

.{[]`?)},~]([n]+n<

Ne yazık ki, "boş dizi sorunu" çözmek için henüz daha kısa bir yol bulamadım.


dengeli ][mi ? : (yani programınızda başarısız oluyor mu?)
Justin

@Quincunx: Gerektiği gibi başarısız oluyor.
Ilmari Karonen

Ancak kabul edildi [[]; Şimdi 4 karakter pahasına düzelttim ve şimdi tüm testlerimi geçiyor.
Ilmari

Seni doğru anlıyorsam, sadece dizi boş olduğunda bir dize ve bir dizi arasında ayrım yapamayan 14 karakterlik bir çözüm vardı. 1+boş bir diziyi boş olmayan bir diziye, boş olmayan bir diziyi boş olmayan bir diziye ve bir dizeyi dizeye dönüştürür.
Peter Taylor

@PeterTaylor: Evet, öyleydi .{[]`?)},~](n<. Ben denedim 1+, ama dizi (muhtemelen yorumlayıcı bir dizi / dize ile bir karakteri karşılaştırmak çalışırken çökecek böylece muhtemelen başka bir şey içermelidir ) görünüyor. n+Diziyi bir dizeye zorladığı için kullanma da çalışmaz; [n]+ yapar işi, ama yine de 18 karakter beni koyar.
Ilmari Karonen

17

Brainfuck 76 bayt

>>+[<+++++++++[->---------<]+>-[--[[-]<->]<[<[->-]>[<+]<]>]<[-<+>]+>,]<<[<+]

Köşeli parantezler dengesizse bf yorumlayıcısını / derleyicisini çalışma zamanını başarısız duruma getirerek ve bazılarında bunu yansıtacak çıkış kodları varsa, bu bağlardan çıkar.

eof = 0, sarma değerleri ve sonlu hücre sayısı gerektirir

Ubuntu'da yorumlayıcıyı bf( sudo apt-get install bf) kullanabilirsiniz

% echo '[[[]' | bf -n bf_matching.bf
Error: Out of range! Youwanted to '<' below the first cell.
To solve, add some '>'s at the beginning, for example.
an error occured
% echo $? 
5
% bf -n bf_matching.bf < bf_matching.bf
% echo $?
0

5
Sorunun imkansız olduğunu söylemesine rağmen Brainfuck'ı nasıl kullandığınızı seviyorum.
Ocak'ta Riking

Vay canına. Dürüst olmak gerekirse şaşırdım. İmkansız olduğunu düşündüm, ama değil.
Konrad Borowski

1
@xfix: Brainfuck tur tamamlandı, böylece her şeyi yapabilir (G / Ç kısıtlamaları göz önüne alındığında)
marinus

2
@marinus Turing tamlığı, yalnızca tüm hesaplamaları yapabileceği anlamına gelir. Brainfuckherhangi bir hesaplamayı hesaplayan bir programı çalıştırabileceğiniz ve çalıştırdıktan sonra belleğini inceleyerek sonucu görebileceğiniz için G / Ç olmadan tamamlanıyor. G / Ç'siz BF, kamu hizmeti kurmanın zor olacağı için insanları daha az ilgilenir. Örneğin lisp tercümanımı asla yapamazdım .
Sylwester

14

Befunge 98 - 26 31 20 19 karakter

~:']-!\'[-!-+:0`j#q

Bazı büyük koşullardan kurtuldum. Şimdi program aşağıdaki gibi çalışır:

~:   read an input char and duplicate it

']-! push a 1 if the char is the ] char, 0 otherwise

\    swap the comparison value for the duplicated input char

'[-! push a 1 if the char is the [ char, 0 otherwise

-    subtract the two comparison values. If the second one is 1, the first is 0, 
     so the result is -1. Else if the second one is 0, the first is 1 and the result is
     1. Else, the first and the second are both 0 and the result is 0

+    Add the number to the counter (which is 0 if there is none already)

:0`  test if the counter is positive (that'd mean an invalid program). Pushes a 1 if 
     positive, 0 otherwise.

j#q  if the counter is positive, then this jumps to the q. Otherwise, it skips the q 
     and continues to the ~ at the beginning of the line. If there are no more chars in
     the input, then the IP will be sent back to the q. 

qprogramdan çıkar ve en üst değeri bir hata değeri olarak açar. Çok fazla varsa hata değeri -1 1 ], dengeli ise 0 ve çok fazla varsa pozitif negatif olur [. Sayı ise pozitif negatif, daha sonra birçok bu sayının mutlak değeri] 's programı dengelemek için ihtiyaç vardır.

Düzenleme: Anahtarlamalı artış ve azalma. [sayacı ]arttırır ve azaltır. Değiştirerek, 1 karakter kaydediyorum, çünkü çıkış koşulu için, sayacın negatif değil, pozitif olup olmadığını kontrol etmem gerekiyor.


Eski versiyon

~:'[-!j;\1+\#;']-!j;1-#;:0\`j#q

Bu kod aşağıdaki gibi çalışır:

~    read one char of input
:    duplicate it
'[-! push 1 if the character is [, 0 otherwise
j    jump that number of characters
;    skip until next ;
\1+\ increment counter

similarily for ].

#q when end of input is reached, ~ reflects the IP back. q ends the program with the error value on the stack.

Düzenleme: bu kabul edilen girişlerin ][, artık sayım negatif olduğunda,

:0\`j


O @JoKing arasındaki mesafeyi kullanarak, oldukça güzel [ve ]her ikisi ile karşılaştırma yapmak.
Justin

6

J ( 38 35)

exit({:+.<./)+/\+/1 _1*'[]'=/1!:1[3

Açıklama:

  • 1!:1[3: okuma stdin
  • '[]'=/: ilk satırın [girişteki s'nin bir bit maskesi olduğu ve ikinci satırın] .
  • 1 _1*: ilk satırı 1 ile ikinci satırı -1 ile çarpın.
  • +/: karakter başına delta girintisi vererek matrisin sütunlarını birlikte toplar
  • +/\: her karakterde girinti düzeyi vererek, bunların toplamını oluşturun
  • ({:+.<./): son elemanın ( {:) ve en küçük elemanın ( <./) GCD'sini döndürür . Tüm parantezler eşleşirse, her ikisi de olmalıdır, bu 0yüzden bu geri dönecektir0 . Diş telleri eşleşmezse, sıfırdan farklı bir değer döndürür.
  • exit: çıkış değerini buna ayarlayın ve çıkın.

Güzel arıza ...
Chris Cashwell

6

yakut (64)

exit $<.read.tr('^[]','').tap{|x|0while x.gsub!('[]','')}.empty?

daha önce (68):

exit ARGF.read.tr('^[]','').tap{|x| 0 while x.gsub!('[]','')}.empty?

Başka bir eşdeğer çözüm kullanır

exit $<.read.tr('^[]','').tap{|x|0while x.gsub!('[]','')}.size>0

sizedengesiz parantez toplamı 256'nın katı olduğunda yanlış negatifler (!!!) vereceği için tek başına kullanamazsınız


Bu kodgolf. Eminim burada bazı boşlukları kaldırabilirsiniz. Ruby biraz boşluk duyarlıdır, ancak birçok durumda onu görmezden gelir. Başlangıç ​​olarak, =operatörün yakınında boşluk gerekmez .
Konrad Borowski

daha iyi sürüm (biraz sed + tr çözümünden esinlenerek). Bundan daha iyi olabileceğimden emin değilim. En azından 4 boşluk kadar düşük!
yeniden yazılarak

1
Yine de ikisini kaldırabilirim.
Konrad Borowski

2
Sanırım etraftaki boşluklar 0gidebilir.
marinus

harika uzay hilesi, teşekkürler!
yeniden yazıldı

5

Perl, 30 karakter

Kurtarmaya yönelik temel Perl özyinelemeli regex'iniz:

perl -0ne 'exit!/^(([^][]|\[(?1)\])*)$/'

Burada kullanılan komut satırı argümanlarına aşina olmayanlar için: -0dosya girişi amacıyla satır sonu karakterini ayarlamanıza izin verir; -0argüman olmadan kullanıldığında satır sonu karakteri EOF olarak ayarlanır. -ngirişi (bu durumda tüm dosyayı) otomatik olarak $_önceden okur .

Normal ifade eşleşirse, çıkış kodu için 0 olarak reddedilen gerçek bir değer döndürür. Aksi takdirde, yanlış dönüş değeri 1 çıkış kodu verir.


Sanırım bu 30 karakterlik çözümü yenmek için cevabımı daha iyi golf oynamak zorunda kalacağım.
Justin

Orada. Çözümüm şimdi eskisinden çok daha kısa. Güzel çözüm. +1
Justin

4

bash (tr + sed) - 42

[ -z `tr -Cd []|sed ":a;s/\[\]//g;t a"` ]

Hata mesajlarına aldırmazsanız `ve arasındaki ]uzunluğu 41 kaldırabilirsiniz .


Hiçbir şeyi özlemediğim sürece, gereksiz bir kullanımınız vardır ( catve $()ayrıca "[]"yazılabilir []). Bu cevabı kabul ettim, ancak uzunluğa göre iyileşmeler görene kadar, bunu değerlendirmeyeceğim, çünkü kısa süre, bash için çok daha kısa olabilir.
Konrad Borowski

Aslında, kabuk komut dosyası yazmayı çok iyi bilmiyorum. Bu işlerin çoğunu yapamıyorum. Ben $()backticks ile değiştirdim ve "[]"-> []önerdi yaptım .
shiona


1
Bunu denediğimde başarısız olduğumu söyleyebilirdim, ama yanılmışım.
shiona

3

Perl (56 karakter)

$/=0;$r=qr/[^][]*(\[(??{$r})\])*[^][]*/;<>=~m/^$r$/||die

Bariz Perl çözümü: özyinelemeli bir normal ifade. Ne yazık ki oldukça ayrıntılı bir yapı.


3

Haskell (143)

import System.Exit
f=exitFailure
v c []|c==0=exitSuccess|True=f
v c (s:t)|c<0=f|s=='['=v(c+1)t|s==']'=v(c-1)t|True=v c t
main=getContents>>=v 0

to jgon: 2 koruma kullanmak if-then-else'dan daha yoğundur. Ayrıca, seninki parantezlerin doğru sırada olduğunu kontrol etmiyorum ("] [" geçer)


Vay canına, bu yorumu sadece bugün işaret edildiğinde gördüm. Kodumu düzelttim, ama evet güzel, gardiyanlar daha yoğun görünüyor (+1).
Ocak

3

C, 73 64 karakter

Ekmek kutusundan gelen öneriler sayesinde (bu muhtemelen çalışmak için küçük endian gerektirir):

i;main(c){while(read(0,&c,1)*(i+1))i+=(c==91)-(c==93);return i;}

Nasıl çalışır:

  • örtülü int global i0 olarak başlatıldı
  • cörtük bir int olur argc(1'e sıfırlanır, ancak yüksek bitler ayarlanmadığı sürece umursamayız)
  • read(0,&c,1)c'nin düşük baytına (küçük endian mimarilerde) tek bir karakter okur ve EOF'da 0 döndürür; i+1 != 0dengeli köşeli parantez alıntısı -1'e gitmediği sürece; onları bir araya getirmek (güvenli) bir boole VE&&
  • c==91için 1'e '[', c==93için 1'e']' . (Daha küçük olacak ama biraz düşünemiyorum ama hiçbir şey düşünemiyorum.)
  • return idengeli ise 0 durum koduyla, değilse sıfırdan çıkar. -1 iadesi teknik olarak POSIX'i ihlal eder, ancak kimse bunu umursamaz.

Önceki versiyon:

main(i){char c;i=0;while(read(0,&c,1)*(i+1))i+=(c==91)-(c==93);return i;}

getchar()Okuma yerine kullanmak kodu kısaltır ve değişkeniniz intyerine (örtük) kullanmanızı sağlar char. Ayrıca globallerin otomatik olarak sıfıra başlatıldığını unutmayın.
ekmek kutusu

Teşekkürler, getchar () 'ı unuttum. Global init'in nasıl yardımcı olduğundan emin değilim - bir global int tanımlamak örtük argc kullanmaktan daha fazla karakter gerektirir.
kabarık

1
Globaller de örtük olabilir. Bir fonksiyonun dışında c;global bir int tanımlar.
ekmek kutusu

Meanwhile, getchar(c) ends up not making it any shorter, at least using this approach, because it needs to be tested for >=0 in some way, and an implicit int for c passed into read() isn't guaranteed to work due to endianness.
fluffy

What about ][ ? I'm sure it's not balanced. Don't you have to keep track whether it goes negative at least once?
vsz

2

Lua, 56

os.exit(("["..io.read"*a".."]"):match"^%b[]$"and 0 or 1)

"^%b[]$" what is this? Can you explain? Surely, this isn't regex?
Cruncher

@Cruncher: It's not. It's Lua pattern, not regex (Lua patterns are similar to regexes, but they aren't). In this case it matches the beginning of string (^), balanced set of [ and ] with anything inbetween (%b[]), and end of string ($).
Konrad Borowski

1

GTB, 55

0→O:0→X[`I@I="[":X+1→X@I="]":X-1→X@X<0:1→O@!!Ig;e]l;e~O

Misses []

Use 0 to stop.


1

MATHEMATICA, 88 chars

s = "[ [ my crazy code ] [ don't explode please! [] [ :)Ahh) ]  [] []]]";

r=StringReplace;
StringLength@FixedPoint[r[#,"[]"-> ""]&,r[s,Except@Characters["[]"]-> ""]]

With functions name like RegularExpression` and StringLength I can never win text code golf context with Mathematica! :)
Murta

I know what you mean:) ToCharacterCode is much longer than ord as well... PS: What about setting an exit code?
Ajasja

Length[StringCases[s,"["|"]"]//.{x___,"[","]",y___}:>{x,y}]
alephalpha

1

Ruby, 59 58

Scans for opening and closing bracket, counting [ as 1 and ] as -1, and exits if the count drops below 0.

b=0
$<.read.scan(/\]|\[/){exit 1if(b+=92-$&.ord)<0}
exit b

1
Upvoted, and shortened by one character (I removed whitespace after exit 1 in case you ask).
Konrad Borowski

1

Hassium, 104 Bytes

func main(){l=0;r=0;b=input();foreach (c in b){if(c=="[")l++;if(c=="]")r++;}if(!(r==l))exit(1);exit(0);}

Full expanded (note doesn't work in online interpreter as input() is disabled) here


1

Turing Machine Code, 286 276 bytes

Again, I'm using the rule table syntax defined here.

0 * * l 1
1 _ ! r Q
5 _ _ r 5
5 * * * W
W [ ! l E
W ] ! l T
W _ _ l I
W * ! r *
E ! ! l *
E * * * R
R _ [ r O
R * * l *
T ! ! l *
T * * * Y
Y _ _ r U
Y * * l *
U [ _ r O
U ! ! * halt-err
I ! ! l *
I _ _ r halt
I * * l halt-err
O ! ! r Q
O _ _ l I
O * * r *
Q ! ! r *
Q * * * W

Terminates in state halt to accept the input and halt-err to reject it.


halt-err can be shorter, such as halt* for example.
Erik the Outgolfer

1

Pyth, 25 bytes

Ilzv::z"[^[\]]"k"]\[""],[

Try it online!

Python 3 translation:
import re
z=input()
if len(z):
 print(eval(re.sub("]\[","],[",re.sub("[^[\]]","",z))))

1

Haskell (167,159)

Did this mostly for fun, if anyone's got any suggestions for how to make it shorter, I'd be glad to hear them tho :)

import System.Exit
p x y b|b=x|True=y
main=getContents>>=(return.all (>=0).scanl (\v->p (v-1) (v+1).(==']')) 0.filter (`elem`"[]"))>>=p exitSuccess exitFailure

Edit: Fixed an issue pointed out to me in the comments (added 11 bytes).

Edit 2: Created auxiliary function for testing predicates using guards inspired by user13350, removing 8 bytes.



@user202729 That's an excellent point, that was super careless. Pretty sure it's fixed now.
jgon

1

Stax, 14 11 characters

╬Äτ↔EªÉs «Ü

Run and debug it

Credit to @recursive for -3 bytes.

ASCII equivalent:

.[]Y|&{yz|egp!

Remove all characters except [], then remove [] until the string no longer changes. Return 1 if the final string is empty.


1
Nice. You can use .[]|& to filter the characters, and then re-use the literal for 11
recursive
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.