Geçerli Brainf ** k programlarını sıralayın


41

Golunar / Tekli tüm geçerli kodlamak için bir yoldur Brainfuck programları, ancak en doğal sayılar geçerli bir programa karşılık gelmez çünkü, bir numaralandırma değildir.

Bu zorluğun amacı için, iki kat sonsuz bir bant olduğunu ve yorum yapmadığını varsayalım; yani, bir Brainfuck programı yalnızca karakterlerden oluşuyorsa <>+-.,[]ve tüm sol ve sağ parantezler eşleşiyorsa geçerlidir.

Örneğin, boş bir program, ,[+][-]., [>+<[--].]ve +[+[+][+[+]+]+]+.geçerli Brainfuck programları ise şunlardır ][ve a[]değillerdir.

Görev

Geçerli bir Brainfuck programını girdi olarak kabul eden ve aşağıdaki sınırlamalarla doğal bir sayı ( 1 , 2 , 3 ,…) döndüren bir program veya işlev yazın :

  • Üretilen çıktı, tüm geçerli Brainfuck programları için farklı olmalıdır.

  • Her doğal sayı için n , girdi olarak sağlandığı zaman n çıktısını üreten geçerli bir Brainfuck programı olmalıdır .

Ek kurallar

  • 100 veya daha az baytlık bir Brainfuck programı verildiğinde, programınız veya işleviniz bir dakika içinde bitmelidir.

    Bu, girişle eşleşene kadar geçerli tüm Brainfuck programlarını yineleyemeyeceğiniz anlamına gelir.

  • Standart kuralları geçerlidir.


3
Sekizlik olarak kodlamayı düşünüyordum ama eşleşen parantezler bunu zorlaştırıyor.
DankMemes

Boş program geçerli bir Brainfuck programı mı? Aynı zamanda doğal bir tamsayıya mı eşleştirilmeli?
orlp

9
Neden yakın oyla? Bu büyüleyici bir sorudur ve problem harika bir golf için büyüklük ve çeşitlilikte olur.
trichoplax 11

1
@ orlp Evet, boş program yukarıdaki tanımı yerine getiriyor
Dennis

3
Brainfuck'ta yazılmış bir cevabı görmek için hala bekliyorum ...
Michael Hampton

Yanıtlar:


16

Python 3, 443 158 155 154 134 131 128 124 117 116 115 bayt

c=d=C=D=0
for e in input():v='[<>,.-+]'.find(e);d=d*8+v;c+=c<0<6<v;c-=d>1>v;C,D=(c,C+1,d,D)[v>6::2]
print(-~D*8**C)

Sp3000 ve Mitch Schwartz: D sayesinde birkaç bayt

Bu nasıl çalışır:

Bu, geçerli tüm BF programlarını [bire-bir oranda a ile başlamayan tüm olası, geçerli veya geçersiz BF programlarına eşler . Bundan sonra, yeni program basitçe octal'a dönüştürülür.

Haritalama formülü:

  1. Bir BF programını 3 parçaya ayırın. İlk kısım sadece [karakterlerden oluşan en büyük önektir . Üçüncü kısım, sadece ]karakterlerden oluşan en büyük yazıdır . İkinci kısım orta kısımdır.
  2. İlk kısmı atın. Bunlar daha sonra yeniden hesaplanabilir.
  3. İkinci parçadaki desteklerle ]eşleşen üçüncü parçadaki tüm destekleri çıkarın [. Bunlar daha sonra yeniden hesaplanabilir.
  4. İkinci ve üçüncü kısımları bir araya getirin.

Bu açıklamayı anlamadıysanız, buradan başlayarak sohbette genişletilmiş bir açıklama bulabilirsiniz .

Başvuru için, işte ilk 20 program:

1 : 
2 : <
3 : >
4 : ,
5 : .
6 : -
7 : +
8 : []
9 : <[]
10 : <<
11 : <>
12 : <,
13 : <.
14 : <-
15 : <+
16 : [<]
17 : >[]
18 : ><
19 : >>
20 : >,

İşte ilk 1000 program: http://pastebin.com/qykBWhmD
İşte onları oluşturmak için kullandığım program: http://ideone.com/e8oTVl

İşte Hello, World!:

>>> ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
457711481836430915510337664562435564418569135809989841510260388418118348571803953323858180392373

Küçük kelime oyunu: Bir programı 0 ile eşleyemezsiniz .
Dennis,

@Dennis Boş bir program olsa program olarak sayılıyor mu?
Beta Çürümesi


@Dennis Golf oynadığımda bunu düzelteceğim.
TheNumberOne,

3
Bu çok zekice
gururlu haskeller

13

Python 2, 157 bayt

def f(s,o=0,d=0,D={}):T=s,o,d;x=D[T]=D[T]if T in D else~o and 0**o+sum(f(s[1:],cmp(c,"[")%-3-~o,d or cmp(c,s[0]))for c in"+,-.<>[]")if s else~d<0==o;return+x

Hala golf oynayabilir gibi görünüyor, ama şimdilik bunu gönderiyorum. Biraz önbelleğe alma ile özyineleme kullanır. Sinir bozucu, D.getönbellekleme için kısa devre yapmıyor, bu yüzden 9 byte tasarruf edemiyorum ...

Haritalama önce uzunluğa, ardından sıralamaya göre söz dizimi sırasına öncelik verir "][><.-,+"(aşağıdaki çıktı örneklerine bakın). Ana fikir önekleri karşılaştırmaktır.

Değişken , geçerli önek için hala açık oolan [parantez sayısını takip ederken, değişken aşağıdakileri dgösteren üç değerden birini alır:

  • d = 1: Geçerli önek, sözlükten daha eskidir s. Bu önek ve uzunluktaki tüm programları ekle <= s,
  • d = -1: Geçerli önek, sözlükten daha büyük s. Bu önek ve uzunluk ile tüm programları ekleyin < s.
  • d = 0: Geçerli önek bir önek olduğundan s, ddaha sonra 1 veya -1 olarak değiştirebiliriz .

Örneğin, varsa s = "[-]"ve mevcut öneki p = "+"beri, pdaha geç ssözlük sırasında biz ile başlayan programlar eklemek için yalnızca biliyoruz pki daha sıkı kısadır s.

Daha ayrıntılı bir örnek vermek gerekirse, bir giriş programımız olduğunu varsayalım s = "-[]". İlk özyinelemeli genişleme bunu yapar:

  (o == 0)               # Adds a program shorter than s if it's valid
                         # For the first expansion, this is 1 for the empty program
+ f(s[1:], o=-1, d=1)    # ']', o goes down by one due to closing bracket
+ f(s[1:], o=1, d=1)     # '[', o goes up by one due to opening bracket
+ f(s[1:], o=0, d=1)     # '>'
+ f(s[1:], o=0, d=1)     # '<'
+ f(s[1:], o=0, d=1)     # '.', d is set to 1 for this and the previous branches
                         # since they are lexicographically earlier than s's first char
+ f(s[1:], o=0, d=0)     # '-', d is still 0 since this is equal to s's first char
+ f(s[1:], o=0, d=-1)    # ',', d is set to -1 for this and the later branches
                         # since they are lexicographically later than s's first char
+ f(s[1:], o=0, d=-1)    # '+'

Biz onları önemseyen tüm değişkenler aracılığıyla yakalanır - Not biz aslında özyinelemede önekleri kullanmayın nasıl d, ove küçülen giriş programı s. Yukarıda çok fazla tekrar olduğunu fark edeceksiniz - burası önbellekleme işleminin gerçekleştiği, zaman içinde 100 char programlarını iyi işlememize izin veren yer.

sBoş olduğunda , (d>=0 and o==0)1'e dönüp dönmeyeceğine karar veririz (bu programı sayımsal olarak erken / eşit ve program geçerli olduğu için) veya 0 (bu programı saymayın).

İle herhangi bir durum futbolcu o < 0derhal getiri 0, bu önek ile herhangi programlar daha beri ]daha s [ve dolayısıyla geçersizdir.


İlk 20 çıktı:

 1
> 2
< 3
. 4
- 5
, 6
+ 7
[] 8
>> 9
>< 10
>. 11
>- 12
>, 13
>+ 14
<> 15
<< 16
<. 17
<- 18
<, 19
<+ 20

@ TheNumberOne'ın cevabıyla aynı Hello World örneğini kullanarak:

>>> f("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.")
3465145076881283052460228065290888888678172704871007535700516169748342312215139431629577335423L

4

Python 2,505 (golf oynamamaktadır)

Bu yaklaşımı geliştirmekten zevk aldım, ancak diğer yaklaşımlarla kıyaslandığında rekabetçi olmadığından golf oynamaktan rahatsız olmayabilirim. Çeşitlilik aşkına ve olası estetik ilgi için gönderiyorum. Özyineleme ve biraz matematik içerir.

F={0:1}

def f(n):
    if n not in F:
        F[n]=6*f(n-1) + sum(f(i)*f(n-2-i) for i in range(n-1))

    return F[n]

def h(x):
    if x=='': return 0

    if len(x)==1: return '+-<>,.'.find(x)

    if x[0]!='[':
        return h(x[0]) * f(len(x)-1) + h(x[1:])

    d=i=1
    while d:
        if x[i]==']': d-=1
        elif x[i]=='[': d+=1
        i+=1

    a=i-2
    b=len(x)-i

    return 6*f(a+b+1) + sum(f(i)*f(a+b-i) for i in range(a)) + h(x[1:i-1]) * f(b) + h(x[i:])

def g(x):
    return sum(f(i) for i in range(len(x))) + h(x) + 1

print g(raw_input())

İşlev f(n), geçerli beyin fırtınası programlarının sayısını sayar n. h(x)haritalar uzunlukta programları niçin [0..f(n)-1]ve g(x)söz konusu bijective sıralama fonksiyonudur.

Ana fikir, boş olmayan bir programın [6 olmayan []karakterden biriyle veya onunla başlayabilmesidir . Eski durumda, eşleştirmenin olası yerleri üzerinde yineleyebiliriz ]ve kapalı kısımda ve kuyrukta tekrarlayabiliriz (burada kuyruk aşağıdaki alt dize anlamına gelir ]). İkinci durumda, kuyruk üzerinde tekrar harekete geçebiliriz (burada kuyruk ilk karakteri düşürür). Bu akıl yürütme, hem sayma hem de hesaplama sırası için kullanılabilir.

Daha kısa programlar her zaman daha uzun programlardan daha düşük bir dereceye sahip olacaktır ve braket modeli ikincil bir belirleyici faktördür. Olmayan []karakterler göre sıralanır "+ - <> ,." (keyfi).

Örneğin n=4, şu durumlarda bizde:

zxxx
[]xx
[x]x
[xx]

burada zolmayan anlamına gelir []karakter ve xbu sınırlama altında, herhangi bir karakter için duran ]ilk eşleşmesi gerekir [. Programlar, bu sıraya göre ve tekrar tekrar xalt bölümlerde sıralanır ve soldaki bölümler, sonraki durumlarda sağ bölüme öncelik verilir. Rütbe hesaplaması, karışık-radix sayı sistemlerine benzer fve mevcut "radix" i hesaplamak için önemlidir.


4

Bu cevap , numaralandırmanın neden doğru olduğunu anlamakta biraz zor olabileceğiniz TheNumberOne , Enumerate geçerli Brainf ** k programlarının cevabının resmi bir kanıtıdır . Neden geçerli bir program tarafından kapsanmayan bir numaraya eşlenen bazı geçersiz programların olmadığını anlamak önemsizdir.

Bu cevap boyunca büyük harf, programları belirtmek için kullanılır ve küçük harf değişkenleri işlevler ve tam sayılar için kullanılır. ~ birleştirme işlecidir.

Teklif 1:

F işlevi bu cevapta açıklanan program olsun. Sonra her U programı için, f (U) = f (V) olacak şekilde geçerli bir V programı vardır.

1. Tanım:

G (X) ' [in X programında göründüğü sayı olmasını ve h (X)' un ]göründüğü sayı olmasını sağlayın .

Tanım 2:

Bu fonksiyon olarak P (x) tanımlayın:

P(x) = "" (the empty program) when x <= 0
P(x) = "]" when x = 1
P(x) = "]]" when x = 2
etcetera

Tanım 3:

X programına bakıldığında, X1'in en büyük [karakter öneki , X2'nin merkezi ve X3'ün en büyük ]karakter sonekini olduğunu belirtin .

Teklif 1'in kanıtı:

Eğer g (U) = h (U) ise U geçerli bir programdır ve V = U alabiliriz. (önemsiz dava).

Eğer g (U) <h (U) ise n = h (U) - g (U) [sembollerini hazırlayarak V oluşturabiliriz . Açıkçası f (V) = f (U) [önek içindeki tüm semboller kaldırıldı.

Şimdi g (U)> h (U) olarak düşünün. T = U2 ~ U3'ü tanımlayın. g (T) <= h (T) ise, n = g (U) - h (U) [sembollerini kaldırarak V oluşturabiliriz .

Öyleyse, h (T) <g (T) olduğunu varsayabiliriz. Yapı V = T ~ P (g (T) - h (T)).

Devam etmek için üç küçük gerçeğe ihtiyacımız var:

İstem 1: g (U2) = g (T)

U3 [tanımı gereği hiçbir sembol içermez . T = U2 ~ U3 olarak, [sembollerin tümü ilk bölümdedir.

2. İstem 2: s (U3) <g (T)

Bu, h (T) <g (T) ve h (U3) <h (U3 ~ U2) = h (T) olduğuna dikkat çekmektedir.

İstem 3: h (V3) = g (U2) - h (U2)

h(V3) = h(U3) + g(T) - h(T)                           using the construction of V
h(V3) = h(U3) + g(U2) + g(U3) - h(U2) - h(U3)         apply the definition of T
h(V3) = g(U2) - h(U2) *one term cancels, g(U3)        is always zero, as U3 contains only `]` symbols*

Şimdi f (V) = f (U) olduğunu gösterelim.

f(U) = U2 ~ P(h(U3) - g(U2)) = U2                     claim 2, definition of P

f(V) = U2 ~ P(h(V3) - g(V2))
     = U2 ~ P(h(V3) - g(U2))
     = U2 ~ P(g(U2) - h(U2) - g(U2))                  claim 3
     = U2 ~ P(-h(U2))
     = U2                                             definition P

Bu ispat tamamlar. QED

Benzersizliği de yapalım.

Teklif 2:

U, V iki farklı, geçerli programlar olsun. Sonra f (U)! = F (V)

Bu, önceki önermeye kıyasla oldukça basittir.

Diyelim ki U2 = V2. Ancak, U ve V'nin farklı olabilmesinin tek yolu, sırasıyla U1 ve U3'e n [ve ]sembollerin eklenmesi veya çıkarılmasıdır . Ancak bu f'nin çıktısını değiştirir, çünkü f ], son ekdeki eşleşmemiş sembollerin sayısını sayar .

Böylece U2! = V2.

Açıkçası, bu bir çelişkiye yol açar. U2 ve V2, sırasıyla f (U) ve f (V) 'nin çıkışında yer aldığından,' kenar 'dışında, U2'nin U3 ile birleştirildiği yer dışında farklılık gösteremezler. Ancak U2 ve V2'nin ilk ve son sembolleri sırasıyla [veya ]tanımda olamaz , oysa sırasıyla U1, U3, V1, V3'te izin verilen tek semboller bunlar. Böylece U2 = V2 olur. QED

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.