Generazione di Brainf *** NOPs


26

A volte quando si scrive il codice Brainfuck, si sente la necessità di renderlo più lungo del necessario per incoraggiare il debug. Potresti farlo semplicemente inserendo un ><, ma che divertimento è? Avrai bisogno di qualcosa di più lungo e di meno NOPey per confondere chiunque legga il tuo codice.

Introduzione rapida a Brainfuck

Brainfuck è un linguaggio di programmazione esoterico creato nel 1993 da Urban Müller, noto per il suo estremo minimalismo. (Wikipedia)

Brainfuck è un linguaggio basato su otto comandi: +-><,.[]. Il codice viene eseguito su qualcosa di simile a una macchina di Turing: un nastro infinito su cui è possibile modificare i valori. In questa sfida, ci concentreremo sui primi quattro:

+    increment the value at the pointer
-    decrement the value at the pointer
>    move the pointer right
<    move the pointer left

Brainfuck NOPs

Un Brainfuck NOP è una sequenza di personaggi brainfuck che, se eseguiti da qualsiasi stato, non portano a nessun cambiamento nello stato. Sono costituiti dai quattro personaggi sopra menzionati.

La sfida

La sfida è scrivere un programma o una funzione che, una volta eseguito, genera un NOP di brainfuck casuale della lunghezza data.

Ingresso

Riceverai come input un numero intero pari non negativo n. (I NOP ​​sono impossibili per dispari n.)

Produzione

Verrà emesso un NOP Brainfuck casuale della lunghezza n.

Regole

  • La definizione di NOP: quando l'output del programma viene inserito in qualsiasi momento in un programma brainfuck, il comportamento di detto programma non deve cambiare in alcun modo. In altre parole, non deve cambiare lo stato dell'interprete.
    • Si noti che, ad esempio +>-<, non è corretto, poiché modifica i valori delle due celle senza modificarle nuovamente. Si prega di testare la soluzione per questi prima di pubblicare.
    • Si noti inoltre che +>-<->+<è un NOP che non può essere ridotto a nulla semplicemente rimuovendolo >< <> +- -+. Pertanto, non è possibile utilizzare un algoritmo che li inserisce semplicemente uno nell'altro.
  • Ogni NOP valido della lunghezza ndeve avere una possibilità diversa da zero nell'output. La distribuzione non deve essere uniforme, però.
  • L'interprete brainfuck in questione ha un nastro doppiamente infinito di celle di precisione arbitrarie. Cioè, puoi andare infinitamente in entrambe le direzioni e incrementare / decrementare ogni cella indefinitamente.
  • Il programma deve terminare entro 1 minuto per n= 100 sulla mia macchina, quindi non generare tutti i NOP possibili e sceglierne uno.
  • Se ti viene fornito un input non valido (non intero, negativo, dispari, ecc.) Puoi fare tutto ciò che desideri, incluso l'arresto anomalo.

punteggio

Questo è , quindi vince la risposta più breve in byte.

Esempi

Ecco tutti gli output validi per n= 4:

++--    +-+-    +--+    --++    -+-+    -++-
>><<    ><><    ><<>    <<>>    <><>    <>><
><+-    ><-+    <>+-    <>-+
>+-<    >-+<    <+->    <-+>
+><-    -><+    +<>-    -<>+
+-><    -+><    +-<>    -+<>

Ecco alcune possibili uscite per n= 20:

+>>->+<->-<<<->>++<<
>+>-<+<->+-<>->+<-<+
+--+-++--++-+--+-++-
>>>>>>>>>+-<<<<<<<<<

18
ecco un NOP Brainfuck che non usa +-<>come avevi chiesto:a
undergroundmonorail

1
Non credo che esistano NOP non semplici, quindi probabilmente puoi rimuovere quella qualifica. .ha un effetto collaterale, ,sovrascrive un valore che non può essere recuperato senza l'uso di []. Ma []finirà per impostare un valore su zero. Questo sovrascrive anche un valore (quindi avremmo bisogno di un altro []per recuperarlo) a meno che non possiamo essere sicuri che la cella interessata fosse zero per cominciare. Tuttavia, dovremmo cercare una cella simile con qualcosa del genere [>]ed è impossibile tornare in modo affidabile alla posizione da cui proveniamo.
Martin Ender,

4
@Eumel "L'interprete brainfuck in questione ha un nastro doppiamente infinito di celle di precisione arbitrarie."
Martin Ender,

2
Si noti che "Brainfuck" non è più consentito nei titoli delle domande a livello di sistema. Sembra che tu sia stato in grado di aggirare la limitazione usando caratteri non ASCII. In futuro, attenersi a questa limitazione.
Alex A.

2
@undergroundmonorail Bene, Turing è completo ... quindi tecnicamente si potrebbe scrivere un PRNG in esso come qualsiasi altra lingua. (Anche se seminare potrebbe essere difficile.)
PurkkaKoodari l'

Risposte:


13

CJam, 62 59 byte

Grazie a nhahtdh per aver salvato 3 byte.

Poiché non è necessario alcun tipo di distribuzione purché ogni no-op appaia con probabilità finita, possiamo semplificarlo molto semplicemente generando una stringa contenente un numero bilanciato -+e <>, rispettivamente, testando se è un NOP e ordinandolo se non lo è.

Ovviamente, per input più lunghi, quasi sempre si otterrà un output ordinato, ma è possibile testare il codice con alcuni input come 8per vedere che in linea di principio può produrre qualsiasi NOP della lunghezza data.

ri_0a*\2/{;"-+<>":L2/mR}%smr:SL["Xa.Xm"3/2e*L]z:sers~0-S$S?

Provalo online.


1
Sì ... il limite arbitrario avrebbe dovuto essere n = 1000 in 10 secondi. I computer sono solo il modo di digiunare oggi ^^ Perché la risposta algoritmica lo risolve in meno di un secondo anche per n = 1000
Falco

Per n ancora più grandi, penso che sia possibile ordinare l'output solo se la stringa bilanciata non è NOP. La distribuzione è terribilmente distorta, ma è consentita dalla domanda.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ è un'idea chiara.
Martin Ender,

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Grazie, anche in questo caso vengono salvati tre byte.
Martin Ender,

16

CJam, 118 116 byte

Questo è leggermente sfuggito di mano ... specialmente la seconda metà sembra che dovrebbe essere molto giocabile.

ri2/_)mr:R-"<>"R*mr_'=fm0\{1$+}%+__&e`]:\{mr1aa..+}*\@](\z:~\{~\("+-"*mr1$3$e=[{_,)mr_2$<@@>}*+]@@f{`1$`={(}@?\}W<}/

Provalo qui.

Questo gestisce N = 100praticamente all'istante. Non ho tempo di scrivere la suddivisione completa del codice ora, quindi ecco l'algoritmo:

  • Genera una stringa bilanciata casuale di <e >con lunghezza casuale (pari) tra 0e Ninclusiva.
  • Riffle le posizioni della testina in questo array. Ad esempio "<>><"diventa [0 '< -1 '> 0 '> 1 '< 0].
  • Ottieni un elenco di tutte le posizioni raggiunte nel processo.
  • Per ciascuna di tali posizioni inizializzare una stringa vuota. Determina anche quante coppie di caratteri rimangono per raggiungere una stringa di lunghezza N.
  • Per ogni coppia rimanente aggiungere +-alla stringa di una posizione casuale.
  • Mescola tutte quelle stringhe.
  • Per ciascuna posizione, determinare la frequenza con cui tale posizione si verifica nell'array riffled e dividere la stringa corrispondente in tanti blocchi (di lunghezza casuale).
  • Nell'array riffled, sostituisci le occorrenze della posizione con i suoi blocchi casuali.

Fatto. Questo si basa sull'osservazione che:

  • Qualsiasi NOP deve avere una quantità uguale di <e >per riportare la testina nella posizione originale.
  • Il codice sarà un NOP fintanto che ogni cella a nastro viene incrementata con la frequenza decrementata.

Distribuendo quantità casuali ma equilibrati di +s e -s tra tutti i luoghi dove la testa del nastro è in una determinata cella, ci assicuriamo che troviamo ogni possibile NOP.


4

Mathematica, 350 byte

Quiet@(For[a="+",If[{##4}=={},#3!=0||Union@#!={0},Switch[#4,"+",#0[ReplacePart[#,#2->#[[#2]]+1],#2,#3,##5],"-",#0[ReplacePart[#,#2->#[[#2]]-1],#2,#3,##5],">",#0[#~Append~0,#2+1,#3+1,##5],"<",If[#2<2,#0[#~Prepend~0,1,#3-1,##5],#0[#,#2-1,#3-1,##5]]]]&@@{{0},1,0}~Join~Characters@a,a=""<>RandomSample@Flatten@RandomChoice[{{"+","-"},{">","<"}},#/2]];a)&

Troppo a lungo? Sì. Mi interessa anche? Non fino a quando qualcun altro pubblica una risposta valida.


4
Ti dispiacerebbe aggiungere una spiegazione, così le persone possono effettivamente convincersi che questo è valido? :)
Martin Ender,

Come funziona esattamente ? Se chiamo la funzione con un numero, ritorna solo +.
Martin Ender,

@ MartinBüttner Risolto ... Attualmente, genera solo programmi casuali con un uguale numero di coppie +- -e <- >fino a quando uno sembra essere un NOP. La metà è presa da un semplice interprete BF.
LegionMammal978,

ciò genera effettivamente una no-op valida di lunghezza 100 in meno di un minuto?
Martin Ender,

@ MartinBüttner Sì. In media, direi che ci vogliono circa 5 secondi. Inizialmente, ho provato programmi completamente casuali, ma non è mai terminato per la lunghezza 100.
LegionMammal978,

2

Python 3 , 177 byte

from random import*
n=int(input())
r=[0]*n*3
p=0
a=[43,45]
s=choices(a+[60,62],k=n)
for c in s:p+=~c%2*(c-61);r[p]+=c%2*(44-c)
if any(r+[p]):s=a*(n//2)
print(*map(chr,s),sep='')

Provalo online!

Ho usato il codice della risposta di Bubbler per la simulazione BF.


2

Python 3 , 163 byte

from random import*
n=int(input())
p=0;d=[0]*n;a=choices(b'+-<>',k=n)
for c in a:d[p]+=c%2*(44-c);p+=~c%2*(c-61)
if p|any(d):a=n//2*b'+-'
print(*map(chr,a),sep='')

Provalo online!

Programma completo che stampa i risultati su STDOUT. La riga che esegue il codice BF potrebbe essere golfabile.

Ha adottato l'approccio di Tyilo; se il codice BF generato non è un NOP, scartalo del tutto e torna a '+-'ripetuto.


Timeout per n = 100
l4m2

@ l4m2 Non ho notato questo requisito. Fisso.
Bubbler,


1

Wolfram Language (Mathematica) , 224 byte

(s=RandomSample[##&@@@Table["<"">",(r=RandomInteger)[#/2]]];While[(g=Length@s)<#,s=Insert[s=Insert[s,"+",i=r@g+1],"-",RandomChoice@@Select[GatherBy[0~Range~++g,Count[#,"<"]-Count[#,">"]&@Take[s,#]&],!FreeQ[#,i]&]+1]];""<>s)&

Provalo online!

Ecco la versione non golf (o meglio, pre-golf):

Function[{n},
 k = RandomInteger[n/2];
 s = RandomSample[## & @@@ Table["<" ">", k]];
 While[Length[s] < n,
   s = Insert[s, "+", i = RandomInteger[Length[s]] + 1];
   p = GatherBy[Range[0, Length[s]], 
     Count[#, "<"] - Count[#, ">"]& @ Take[s, #]&];
   j = RandomChoice @@ Select[p, ! FreeQ[#, i] &]];
   s = Insert[s, "-", j + 1];
   ];
 ""<>s]

Per prima cosa scegliamo un numero casuale di < "se >" da utilizzare e generiamo un elenco casuale con un numero uguale di ciascuno.

Per riempire il resto dei personaggi, scegliamo una posizione in cui aggiungere a + , quindi troviamo una posizione in cui il puntatore punta nella stessa posizione e aggiungiamo un -lì.

Ripetere l'operazione fino a quando l'elenco non ha lunghezza ne definire il risultato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.