Genişletilmiş sıkıştırılmış beyin flak


26

Bu meydan okuma, Nisan 2018 LotM yarışmasının bir parçası olarak ve Brain- flak'ın 2. doğum günü için yayınlandı.


Brain-flak programlarını kodlamanın en etkili yolunun ne olacağını düşünüyordum. Yapılacak en açık şey, yalnızca 8 geçerli karakter olduğundan, her bir karakteri 3 bitlik bir sırayla eşlemektir. Bu kesinlikle çok etkili, ama yine de çok fazlalık var. Şifrelemeyi kısaltmak için faydalanabileceğimiz beyin-laf kodunun bazı özellikleri var.

  • Hepsi birbiriyle eşleşen 2 parantez ile temsil edilen tırnaklar, gerçekten 2 yerine tek bir bilgi birimi olarak işlev görür.

  • Bu daha az açıktır, ancak monadların kapanış baytları da gereksizdir. '?'Aşağıdaki pasajda karakterlerin neyi temsil ettiğini tahmin edebileceğinizi mi düşünüyorsunuz ?

     {(({}?<>?<>?
    

    Girdilerin geçerli beyin-flak kodu olduğunu varsayarsak, bu soru işaretlerinin her biri için yalnızca bir seçenek vardır. Bu, her kapanış braketini temsil etmek için açıkça yakın bir monad karakteri kullanabileceğimiz anlamına gelir . Bu, karakter kümesini küçük tutmanın ek avantajına sahiptir; bu, bir huffman kodlaması kullanmak istiyorsak büyük ölçüde yardımcı olacaktır. Yana yakın monad karakteri büyük olasılıkla açık farkla en yaygın karakter olacak o derece verimli olan tek bir bit ile temsil olabilir.

Bu iki püf noktası beyin-laf kodunu aşağıdaki algoritma ile sıkıştırmamıza izin verecek:

  1. Bir monanın her kapatma braketini ile değiştirin |. Başka bir deyişle, açılış maçından önce gelmemiş olan her kapatma braketini bir çubukla değiştirin. Yani...

    (({})<(()()())>{})
    

    olacaktı

    (({}|<(()()()||{}|
    
  2. Her niladı kapama braketi ile değiştirin. Bu nedenle, içinde hiçbir şey bulunmayan eşleşen braketler aşağıdaki eşlemeyi kullanır:

    () --> )
    {} --> }
    [] --> ]
    <> --> >
    

    Şimdi son örneğimiz:

    ((}|<()))||}|
    
  3. İzleyen |karakterleri kaldırın . Toplam çubuk sayısının toplam ({[<karakter sayısına eşit olması gerektiğini bildiğimiz için, sonunda eksik çubuk varsa, bunları çıkartabiliriz. Yani şöyle bir örnek:

    ({({})({}[()])})
    

    olacaktı

    ({(}|(}[)
    

Bugün için zorluk, bu süreci tersine çevirmektir.

Sadece karakterleri içeren bir dizi sıkıştırılmış beyin-lafı verildiğinde (){}[]<>|, onu orijinal beyin-lapa koduna genişletin. Girişin her zaman geçerli beyin flakasına genişleyeceğini varsayabilirsiniz. Girdinin hiçbir önek zamankinden daha içerecek Bu araçlar |daha ({[<karakterler.

Giriş, sondaki |karakterleri içermez . Bunlar bağlamdan çıkarılmalıdır.

Her zamanki gibi, tam bir program veya bir işlev sunabilirsiniz ve giriş / çıkış biçimlerine izin verilir. Bu bir olduğundan, kodunuz bayt cinsinden kaynak kodun uzunluğu ile puanlanacak, puan ne kadar küçük olursa o kadar iyi olur.

Test durumları

İşte bazı test durumları. Daha fazlasını isterseniz, bu test senaryosuyla ve bu test senaryolarının çoğunun geldiği Brain-Flak Wiki ile kendi test durumlarınızı oluşturabilirsiniz .

#Compressed code
#Original code

())))
(()()()())


([([}()||||(>||{(})|>|}{((<}|||>}|}>}
([([{}(())])](<>)){({}())<>}{}{((<{}>))<>{}}{}<>{}

({(}|(}[)|||}
({({})({}[()])}{})


(((()))||(](((}}||(}([(((}))||||(]((}}|}|}}|||]||]|[))||(}))|}(}|(}]]|}
((((()()()))([]((({}{}))({}([((({}()())))]([](({}{}){}){}{})))[]))[])[()()])({}()()){}({})({}[][]){}

4
deha. kesinlikle dahi. Bir türev dili yapmalısın.
NH.

8
@NH. Şahsen, sadece kodlamada farklı olan dillerin gerçekten sıkıcı olduğunu hissediyorum.
DJMcMayhem

1
@ dj ancak bu daha az bayt alır ve bu nedenle golf oynamak için daha iyidir.
NH.

5
Brain-Flak golf oynamakta iyi olacak şekilde tasarlanmamıştı.
DJMcMayhem

Yanıtlar:


32

Brain-Flak , 952 916 818 bayt

{(({})[(((()()()()()){}){}){}])((){[()](<{}>)}{}){{}(({})()<>)(<>)}{}(<>)<>(({})[(((()()()){}){}()){({}[()])}{}])((){[()](<{}>)}{})({}<>{})<>(({})[((((()()()()()){}){})){}{}])((){[()](<{}>)}{})({}<>{})<>(({})[(((((()()()()()){}){}){}())){}{}])((){[()](<{}>)}{})({}<>{}){{}(<(<>({})()()<>)>)}{}<>(({})[(((()()()()()){}){}){}()])((){[()](<{}>)}{}){{}(({})[()])(<>)<>(<({}<{({}<>)<>}{}>)>)<>{({}<>)<>}{}(<>)}{}(<>)<>(({})[(((((()()()()()){})){}{}())){}{}])((){[()](<{}>)}{})({}<>{})<>(({})[((((()()()()()){}){})()){}{}])((){[()](<{}>)}{})({}<>{})<>(({})[(((((()()()()()){}){}){}())()){}{}])((){[()](<{}>)}{})({}<>{}){{}<>(<(({})[()()])(<>)<>(<({}<{({}<>)<>}{}>)>)<>{({}<>)<>}{}>)}{}<>(({})[(((((()()()()()){}){})()){}{}){}])((){[()](<{}>)}{}){{}{}(<(<>{}<>)>)}{}(<>)<>(<({}<{({}<>)<>}{}>)>)<>{({}<>)<>}{}<>}{}{({}<>)<>}<>

Yerine sıfırdan göre daha karşı parantez hesaplayarak 360 bayt Kaydedilen (örneğin ')'= '(' + 1yerine (((5 * 2) * 2) * 2) + 1)

DJMcMayhem'deki doğrudan değişikliklerle 34 bayt kaydedildi

İşlem >]}kodunu üst üste bindirerek 10 bayt kaydedildi

Ruloları tekilleştirerek 118 bayt kurtarıldı

İlk rulo basitleştirmek için boş yığından yararlanarak 40 bayt kurtardı

Daha kısa devre kodları sağlayan EOF'yi -1 ile işaretleyerek 48 bayt kurtarıldı

Stoku kullanarak kaydedilen 36 bayt , kendim yerine mantığa eşittir

Jo King sayesinde çıktıları oluşturmak için daha etkili bir yol bulan 98 bayt kurtarıldı

Çevrimiçi deneyin!

Brain-Flak'ta ilk kez golf oynamanın sebebi, muhtemelen bazı büyük gelişmeler var. Her bir braket tipini işlemek için çok sayıda kopyala / yapıştır, otomatik tam sayı üreteci ve Roll pasajı buradan büyüktür .

Burada açıklama , TIO daha kolay biçimlendirir

Bonus cevabı:

Sıkıştırılmış Brain-Flak 583 bayt

{((}|[((()))))|}|}|}||(){[)|(<}|||}|{}((}|)>|(>||}(>|>((}|[((()))|}|})|{(}[)|||}||(){[)|(<}|||}|(}>}|>((}|[(((()))))|}|}||}}||(){[)|(<}|||}|(}>}|>((}|[((((()))))|}|}|})||}}||(){[)|(<}|||}|(}>}|{}(<(>(}|))>||||}>((}|[((()))))|}|}|})||(){[)|(<}|||}|{}((}|[)||(>|>(<(}<{(}>|>|}||||>{(}>|>|}(>||}(>|>((}|[((((()))))|}||}})||}}||(){[)|(<}|||}|(}>}|>((}|[(((()))))|}|}|)|}}||(){[)|(<}|||}|(}>}|>((}|[((((()))))|}|}|})|)|}}||(){[)|(<}|||}|(}>}|{}>(<((}|[))||(>|>(<(}<{(}>|>|}||||>{(}>|>|}|||}>((}|[((((()))))|}|}|)|}}|}||(){[)|(<}|||}|{}}(<(>}>||||}(>|>(<(}<{(}>|>|}||||>{(}>|>|}>|}{(}>|>|>

Çevrimiçi deneyin!

(Yukarıdaki bağlantı Sıkıştırılmış Beyin-Flak tercüman yoktur TIO çünkü dolmuyor Not. Sen Beyin-Flak bir transpiler bulabilirsiniz burada )

Bunun, bu aracı kullanarak Brain-Flak'a aktarılarak geçerli olduğunu kontrol ettim , şimdi zaman aşımının muhtemel olmadığı kadar verimli.


4
Brain-Flak'ta ilk kez golf oynamanın sonucu bu mu? Vay.
Outgolfer Erik

Her zaman yerini alabilir <>(<()>)ile (<>). Ayrıca, değiştirebilir (<>{}<>)(<()>)için(<(<>{}<>)>)
DJMcMayhem

1
Ben zar zor her ederse blok fazladan bir tane kalmadan döngünün sonunda Rulosunu ayıklamak için yönetilen nasıl bilmez @JoKing
Kamil Drakari

1
Bu golf oynamaktan öte .. Bu saf delilik. Tebrikler!
Arthur Attout

1
@JoKing Değişiklik beklediğimden daha kolay ve daha etkili oldu ve şimdi cevabına dahil edildi
Kamil Drakari

7

Retina 0.8.2 , 103 98 bayt

[])}>]
$&;
T`])}>|`[({<;
r`(.*)((;)|(?<-3>.))*
$&$.1$*;
(?<=(.)((;)|(?<-3>.))*);
;$1
T`;-{`_>-}`;.

Çevrimiçi deneyin! Link, test durumlarını içerir. Düzenleme: @MartinEnder ilham ile 5 bayt kurtardı. Açıklama:

[])}>]
$&;
T`])}>|`[({<;

;Her kapanış dirseğe bir son koyun ve hepsini açmak için hepsini değiştirin ve |s'yi de değiştirin ;.

r`(.*)((;)|(?<-3>.))*
$&$.1$*;

Eşleşmeyen açık parantezlerin sayısını sayın ve o kadar ;s ekleyin .

(?<=(.)((;)|(?<-3>.))*);
;$1

Her açılış braketini eşleşmesine kopyalayın ;.

T`;-{`_>-}`;.

Kopyalanan parantezleri çevirin ve ;s'yi silin .


1
Gibi bir |şeye tercüme ederseniz, tüm kaçan çubukları önleyebilirsiniz !. Çevirmek verirsen, daha bayt mal olmaz >-}için <-{(ı verir düşünüyorum hangi ziçin |).
Martin Ender

@MartinEnder Bununla ilgili amacınızı anladığımdan emin değilim, zancak yine de birkaç bayt daha tıraş ettim.
Neil

5

TIS , 670 666 bayt

-4 atlama geri atlamak için ileri atlamak için

Kod:

@0
MOV UP RIGHT
@1
MOV ANY ACC
SUB 41
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
MOV ACC DOWN
@2
NOP
MOV 124 LEFT
@3
MOV ANY DOWN
@4
MOV UP ACC
JGZ O
MOV 40 LEFT
JLZ (
MOV 41 LEFT
JRO 3
O:SUB 21
MOV ACC DOWN
JRO -8
(:MOV 41 RIGHT
@5
MOV ANY DOWN
@6
MOV ANY DOWN
@7
MOV UP ACC
JGZ O
MOV 60 LEFT
JLZ <
MOV 62 LEFT
JRO 3
O:SUB 31
MOV ACC DOWN
JRO -8
<:MOV 62 RIGHT
@8
MOV ANY DOWN
@9
MOV ANY DOWN
@10
S:MOV UP ACC
JGZ O
MOV 91 LEFT
JLZ [
MOV 93 LEFT
JRO 3
O:SUB 31
MOV ACC DOWN
JRO -8
[:MOV 93 RIGHT
@11
MOV ANY DOWN
@12
MOV ANY DOWN
@13
MOV UP ACC
JEZ |
MOV 123 LEFT
JLZ {
MOV 125 LEFT
JRO 2
|:MOV DOWN LEFT
JRO -7
{:MOV 125 RIGHT
@14
MOV ANY DOWN
@15
MOV UP DOWN
@16
MOV UP LEFT

Düzen:

6 3
CCCCCCCCCCCCCCCCSC
I0 ASCII -
O0 ASCII -

Çevrimiçi deneyin!

Bunun en küçük olduğundan şüpheliyim, ancak küçültmenin bir yolunu görmüyorum. Ne yazık ki, tüm NOPs zamanlama için gerekli görünüyor ve ben yığını koyamazsınız @14çünkü gelen okuma şu anda ANYiçinde @11.

Bu çözümün yapısı aşağıdaki gibidir:

Input
  |
  V
  0    1:synchro  2:EOF
  3    4:parens     5
  6    7:angles     8
  9   10:squares   11
 12   13:curlies   14
 15      stack     16
  |
  V
Output

Açık bir ayraç göründüğünde açık, çıkacak sol sütun boyunca gönderilir ve yakın sütun sağ sütun boyunca yığına gönderilir.

Yakın bir ayraç gördükten sonra, açık ve kapalı her ikisi de çıkılacak sol sütun boyunca gönderilir.

Bir boru göründüğünde, istif açılır ve çıktıya gönderilir.

EOF üzerine , yerine giriş akışı yerine @1okumaya başlayacaktır . Sonsuz bir boru akımı ürettiği için istif boşaltılacaktır.@2@0@2

Hem giriş hem de yığın tükendiğinde, program durur.

Uyarı: TIS'in kısıtlamaları nedeniyle, yığın boyutu 15 ile sınırlandırılmıştır. Bundan daha derin bir şey varsa, bu uygulama yanlış sonuç verecektir.


4

JavaScript (ES6), 107 bayt

Girdiyi karakter dizisi olarak alır. Bir dize döndürür.

a=>a.map(c=>(n=(S='|()[]{}<>').indexOf(c))?n&1?(s=[S[n+1],...s],c):S[n-1]+c:s.shift(),s=[]).join``+s.join``

Çevrimiçi deneyin!


Ayrıca bir karakter dizisi döndürerek 102 bayt .
Shaggy

@Shaggy Teşekkürler! Fakat birlikte karıştırılmış 1 karakter ve 2 karakterli dizeleri döndürmeye gerçekten izin var mı?
Arnauld

Hmm ... evet, belki de "izinli" çıktısını zorluyordur.
Shaggy

@DJMcMayhem Lütfen yeni çıktı formatına bir göz atar mısınız ve kabul edilebilir mi?
Arnauld

1
@arnauld Huh, nedense beni kızdırmadı. Sanırım hayır derdim. Bir karakter dizisi veya bir dize hem standart biçimlerdir, hem de dizelerden oluşan bir dizi benim için geçerli görünmüyor
DJMcMayhem


3

Ruby , 104 bayt

a=[];$<.chars{|c|r="|[{(<>)}]";i=r.index(c);i<1||(i<5?a:$>)<<r[-i];$>.<<i<1?a.pop: c};$><<a.reverse.join

Bu, konsola çıkan tam bir programdır. (i<5?a:$>)<<r[-i]şimdiye kadar yaptığım en havalı golflerden biri olmalı.

Çevrimiçi deneyin!

Ruby , 106 bayt

->s{a=[];(s.chars.map{|c|r="|>)}][{(<";d=r[-i=r.index(c)];i<5||a<<d;i<1?a.pop: i<5?d+c:c}+a.reverse).join}

Bu benim ilk çözümüm. Dizeleri alan ve döndüren adsız bir lambda işlevi.

Çevrimiçi deneyin!


3

Brain-Flak , 606 548 496 418 394 390 bayt

{((({})))(<>)(((((((([(())()()()]){}){}){}())(()))(((())()())()){}{})){}[()])({<(({}<>{}[()]))>(){[()](<{}>)}{}<>}{}<><{}>){({}({})<>)(<>)}{}({}<>)(<>)(((((((([(())()()()]){}){}){}())(()))(((())()){}()){})){})({<(({}<>{}[()]))>[()]{()(<{}>)}{}<>}{}<>){(<({}(<()>)<>({})<{({}<>)<>}>)>)<>{({}<>)<>}}{}({}()<>){{}({}<>)((<>))}{}{}<>(<({}(<()>)<><{({}<>)<>}>)>)<>{({}<>)<>}{}<>}{}{({}{}<>)<>}<>

Çevrimiçi deneyin!

Buna Kamil Drakari'nin cevabını golf oynayarak başladım , ancak benden ayrı bir cevap olarak göndermeye karar verdiğim noktaya benden uzaklaştı.

Açıklama:

{ #While input on stack
	((({})))(<>)	#Preserve copy of the character
	(((((		#Push the differences between start bracket characters
	((([(())()()()]){}){}){}())	#Push -31, 1
	(()))				#Push -30, 1
	(((())()())()){}{})		#Push -19, 1
	){}[()])			#Push -39
	({<(({}<>{}[()]))>(){[()](<{}>)}{}<>}{}<><{}>)	#If the character is any of the start brackets
	{({}({})<>)(<>)}{}					#Push the current character + TOS to the other stack

	({}<>)(<>)
	(((((		#Push the differences between end bracket characters
	((([(())()()()]){}){}){}())	#Push -31, 1
	(()))				#Push -30, 1
	(((())()){}()){})		#Push -19, 1
	){})				#Push -40
	({<(({}<>{}[()]))>[()]{()(<{}>)}{}<>}{}<>)	#If the character is any of the end brackets
	{(<({}(<()>)<>({})<{({}<>)<>}>)>)<>{({}<>)<>}}{}	#Push the character + TOS to the output

	({}()<>)	#If the character is not a |
	{{}({}<>)((<>))}{}	#Move current character to the other stack and push a zero
	{}		#Pop the top value of the stack, either the | or a 0
	<>(<({}(<()>)<><{({}<>)<>}>)>)<>{({}<>)<>}{}<>	#And push top of other stack to the output
}{}
{({}{}<>)<>}<>	#Reverse output and append the excess end brackets

Ve tabi ki...

Sıkıştırılmış Brain-Flak, 285 bayt:

{(((}|||(>|(((((((([()|)))||}|}|})|()||((()|))|)|}}||}[)||({<((}>}[)||||){[)|(<}|||}>|}><}||{(}(}|>|(>||}(}>|(>|(((((((([()|)))||}|}|})|()||((()|)|})|}||}|({<((}>}[)||||[)|{)(<}|||}>|}>|{(<(}(<)||>(}|<{(}>|>|||||>{(}>|>||}(})>|{}(}>|((>|||}}>(<(}(<)||><{(}>|>|||||>{(}>|>|}>|}{(}}>|>|>

1
Çok etkileyici golf! Bunu daha önce farketmediğim için kendimi hayal kırıklığına uğrattım, daha sonra nasıl çalıştığını anlamak için daha sonra içine dalmam gerekecek.
Kamil Drakari

2

Java 10, 424 bayt

s->{int i=0;for(var c:s.toCharArray()){if("(<[{".indexOf(c)>-1)i++;if(c=='|')i--;}for(;i-->0;)s+='|';s=s.replace(")","()").replace(">","<>").replace("]","[]").replace("}","{}");char[]c=s.toCharArray(),r=new char[124];r[40]=41;r[60]=62;r[91]=93;r['{']='}';var o="";for(;++i<c.length ;){if(c[i]=='|'){c[i]=o.charAt(0);o=o.substring(1);}if("(<[{".indexOf(c[i])>-1&")>]}".indexOf(i+1<c.length?c[i+1]:0)<0)o=r[c[i]]+o;}return c;}

Biraz uzun, ama nasıl daha da kısaltılacağını çözemedim. Bu olsa güzel bir meydan okuma.

Burada çevrimiçi deneyin .

Ungolfed versiyonu:

s -> { // lambda taking a String argument and returning a char[]
    int i = 0; // used for counting the number of '|'s that have been removed at the end of the input
    for(var c : s.toCharArray()) { // look at every character
        if("(<[{".indexOf(c) > -1) // if it's an open monad character
            i++; // we will need one more '|'
        if(c == '|') // if it's a close monad character
            i--; // we will need one '|' less
    }
    for(; i-- > 0; ) // add as many '|'
        s += '|';    // as necessary
    s = s.replace(")", "()").replace(">", "<>").replace("]", "[]").replace("}", "{}"); // replace compressed nilads with their uncompressed versions
    char[] c = s.toCharArray(), // from now on working on a char[] is more efficient since we will only be comparing and replacing
    r = new char[124]; // map open monad characters to their counterparts:
    r[40] = 41;   // '(' to ')'
    r[60] = 62;   // '<' to '>'
    r[91] = 93;   // '[' to ']'
    r['{'] = '}'; // '{' to '}'
    var o = ""; // we use this String as a kind of stack to keep track of the last open monad character we saw
    for(; ++i < c.length ;) { // iterate over the length of the expanded code
        if(c[i] == '|') { // if the current character is a close monad character
            c[i] = o.charAt(0); // replace it with the top of the stack
            o = o.substring(1); // and pop the stack
        }
        if("(<[{".indexOf(c[i]) > -1 // if the current character is an open monad/nilad character
         & ")>]}".indexOf(i+1 < c.length ? c[i+1] : 0) < 0) // and it's not part of a nilad (we need to test for length here to avoid overshooting)
            o = r[c[i]]+o; // using the mapping we established, push the corresponding character onto the stack
    }
    return c; // return the uncompressed code
}

2

Python 2, 188 184 180 177 174 173 bayt

p,q='([{<',')]}>'
d,s,a=dict(zip(p,q)),[],''
for c in input():
 if c in d:a+=c;s+=[c]
 elif'|'==c:a+=d[s.pop()]
 else:a+=dict(zip(q,p))[c]+c
for c in s[::-1]:a+=d[c]
print a

DJMcMayhem sayesinde 4 byte kurtarıldı.
Çevrimiçi deneyin!



2. ve son satırları karıştırıp 168 byte
DJMcMayhem

@DJMcMayhem Bu sadece sboş biterse işe yarar . Aksi takdirde, yanlış ucunda fazladan karakterlerle karşılaşırsınız.


1

Haskell , 152 bayt

fst.p
m c="> < ] [)(} {"!!mod(fromEnum c-6)27
p(c:r)|elem c")]}>",(s,t)<-p r=(m c:c:s,t)|c/='|',(s,'|':t)<-p$r++"|",(u,v)<-p t=(c:s++m c:u,v)
p e=("",e)

Çevrimiçi deneyin! veya tüm test durumlarını doğrulayın . pbasit bir gramer için öldürmenin üzerinde olabileceği özyinelemeli bir çözümleyici uygular.


1
mEşleşen braketi bulmak için güzel bir fonksiyon .
nimi

1

Python 2,244 bayt

s=input()
B='([{<'
C=')]}>'
Z=zip(B,C)
P=sum(map(s.count,B))-s.count('|')
for i,j in Z:s=s.replace(j,i+j)
s+=P*'|'
b=[0]
for i in s:[b.pop()for j,k in Z if j==b[-1]<k==i];b+=[i][:i in B];s=i=='|'and s.replace(i,C[B.find(b.pop())],1)or s
print s

Çevrimiçi deneyin!

Bu işe yaraması bir iki saatten fazla sürdü.

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.