I 9 miliardi di nomi di Dio


74

The 9 Billion Names of God è un racconto di Arthur C. Clarke. Parla di un gruppo di monaci tibetani il cui ordine è dedicato a scrivere tutti i possibili nomi di Dio, scritti nel loro proprio alfabeto. In sostanza, sono dedicati a scrivere ogni possibile permutazione del loro alfabeto, limitato da alcune regole. Nella storia, il monastero assume alcuni ingegneri per scrivere un programma per fare tutto il lavoro per loro. Il tuo obiettivo è scrivere quel programma.

Regole:

  • L'alfabeto del monaco usa 13 caratteri (secondo le mie stime). Puoi usare ABCDEFGHIJKLMo qualche altro set di 13 caratteri.

  • La lunghezza minima di un nome possibile è 1 carattere. La lunghezza massima è di 9 caratteri.

  • Nessun personaggio può ripetere più di 3 volte in successione. AAABAè un nome valido, ma AAAABnon lo è.

  • Il tuo programma dovrebbe stampare (su un file) ogni possibile nome in sequenza da Aa MMMLMMMLM, separato da qualsiasi carattere non presente nell'alfabeto (newline, punti e virgola, qualunque cosa).

  • Questo è code-golf e puoi usare qualsiasi lingua. Vince la soluzione più breve entro il 1 giugno 2014.

Modifica: i nomi dovrebbero iniziare con Ae terminare MMMLMMMLM, procedendo in sequenza attraverso tutti i miliardi di nomi. Ma la sequenza particolare dipende da te. Puoi stampare prima tutti i nomi di 1 lettera, quindi tutti i nomi di 2 lettere, ecc. Oppure puoi stampare tutti i nomi che iniziano con A, quindi tutti quelli che iniziano con B, o qualche altro motivo. Ma un essere umano dovrebbe essere in grado di leggere il file e confermare che sono tutti lì e nell'ordine logico che scegli, supponendo che abbiano il tempo.


29
Stai cercando di porre fine all'universo, signore?
Boluc Papuccuoglu,

8
Link alla storia , per chiunque sia interessato.
ThatOneGuy


1
Ciò verifica che il numero di nomi nel presente problema sia effettivamente 11.459.252.883 (come si trova nel programma C di edc65 ). Implementazione soluzione di Ross Millikan al MathSE genera la seguente formula polinomiale per il numero di nomi con lunghezza <= 9, per la variabile alfabeto dimensione k: f(k) = k^9 + k^8 + k^7 - 5*k^6 + k^5 + k^4 + 4*k^3 - 2*k^2 + k. Implementazione prudente
res

3
@ edc65 Quindi, 105.8GBtutto detto e fatto! Sono contento che le stelle non siano uscite ... o forse devi stampare la lista perché ciò accada ...?
recursion.ninja,

Risposte:


34

Ruby, 46

?A.upto(?M*9){|s|s[/(.)\1{3}|[N-Z]/]||puts(s)}

La mia soluzione originale e simile era più lunga e sbagliata (produceva numeri base13, che non sono tutti dovuti a zero iniziali), ma la lascerò qui perché ha comunque ottenuto voti.

1.upto(13**9){|i|(s=i.to_s 13)[/(.)\1{3}/]||puts(s)}

14
Bene, ho eseguito il tuo codice per circa un'ora e ho ottenuto fino a 2 miliardi di nomi e un file di testo da 21 GB prima di vedere questo e di chiuderlo. Ho sottovalutato quanto sarebbe grande il file.
CSturgess,

2
@CSturgess Bene, Ruby non è la lingua più veloce per questo genere di cose là fuori ...
BenjiWiebe

8
@BenjiWiebe Ma ancora più veloce di essere scritto a mano dai monaci!
Turophile,

1
Accettarlo perché ha più voti.
CSturgess,

4
Non pubblicarlo come una risposta separata, poiché richiede un'enorme quantità di memoria (~ 30 TB, se il mio calcolo è corretto), ma in teoria puoi accorciarlo a 43 caratteri conk=*?A..?M*9;puts k-k.grep(/(.)\1{3}|[N-Z]/)
Ventero

24

C 140 177 235

Buon vecchio stile procedurale, nessuna fantasia.
Conta (senza scrivere) 11.459.252.883 nomi in 8 minuti.
Prossima modifica con il runtime e la dimensione del file dei nomi. Guarda il cielo ...
Durata 57 minuti, dimensione file 126.051.781.713 (9 caratteri + crlf per riga). Per favore dimmi l'indirizzo e-mail dei monaci, in modo che io possa inviare loro il file zippato, per il controllo manuale ...

Modifica Golf un po 'di più, rielaborato l'assegno per lettere ripetute.
Non è ancora il più breve, ma almeno questo termina e genera l'output richiesto.
Durata 51 min, dimensione file 113.637.155.697 (non ci sono spazi vuoti iniziali questa volta)

Una nota a margine: ovviamente il file di output è molto comprimibile, tuttavia ho dovuto uccidere 7zip, dopo aver lavorato 36 ore era al 70%. Strano.

char n[]="@@@@@@@@@@";p=9,q,r;main(){while(p)if(++n[p]>77)n[p--]=65;else for(r=q=p=9;r&7;)(r+=r+(n[q]!=n[q-1])),n[--q]<65&&puts(n+q+1,r=0);}

Ungolfed

char n[]="@@@@@@@@@@";
p=9,q,r;
main()
{
    while (p)
    {
        if (++n[p] > 77)
        {
            n[p--] = 65; // when max reached, set to min and move pointer to left
        }
        else 
        {
            for (r=q=p=9; r & 7 ;) // r must start as any odd number
            {
                r += r+(n[q]!=n[q-1])); // a bitmap: 1 means a difference, 000 means 4 letters equal
                n[--q] < 65 && puts(n+q+1,r=0);
            }
        }
    }
}

no #includes?
Simon Kuang,

@SimonKuang, alcuni compilatori inseriranno automaticamente quelli di base (stdio).
Paul Draper,

1
@Simon è lo standard C. Per impostazione predefinita, gli oggetti globali sono int e le funzioni globali restituiscono int. Visual Studio genera un avviso C4013 su "put" non definito, ma è valido comunque.
edc65,

4
si inserisce in un tweet!
CincauHangus,

19

Golfscript, 58 47 caratteri

"A"13
9?,{13base{65+}%n+}%{`{\4*/,}+78,1/%1-!},

Grazie a Peter Taylor, mi viene risparmiato dal seppuku di non battere la soluzione di Ruby! Esegui il codice fino a 10 da solo , e qui è la prova che salta i numeri di quattro righe .


1
Risparmio semplice: utilizzare n+invece di ''+n. Penso che sia nel rispetto delle regole di utilizzare un alfabeto con caratteri di controllo, in modo da poter sostituire anche 65+con 13+e salvare un altro personaggio nominando 13:^. E penso che 13,{ stuff [...]potrebbe essere 13,1/{ stuff 4*.
Peter Taylor,

1
Il mio pensiero iniziale era che il salvataggio sarebbe stato tramite un filtro e con un po 'di lavoro si può fare. Da 13,in poi può essere sostituito con {65+}%n+}%{ backtick {\4*/,}+78,1/%1-!},un risparmio totale di 8, salvando la vita.
Peter Taylor,

Finché il personaggio è qualcosa che puoi vedere fisicamente, funzionerà. Davvero potresti persino includere newline come personaggio. Solo finché c'è una sequenza per i personaggi.
CSturgess,

@PeterTaylor: sei un gentiluomo e uno studioso!
Claudiu,

Dopo AAAMdovrebbe essere AAABA, e non BAAAB, giusto?
solo

18

Utilità della riga di comando di Bash + Linux, 43 byte

jot -w%x $[16**9]|egrep -v "[0ef]|(.)\1{3}"

Questo utilizza una tecnica simile alla mia risposta di seguito, ma conta solo nella base 16 e rimuove tutti i "nomi" contenenti 0, eo fanche quelli con più di 3 stesse cifre consecutive.

Converti in alfabeto del monaco come segue:

jot -w%x $[16**9]|egrep -v "[0ef]|(.)\1{3}" | tr 1-9a-d A-M

Bash + coreutils (dc ed egrep), 46 byte

Modifica: versione corretta

dc<<<Edo9^[p1-d0\<m]dsmx|egrep -v "0|(.)\1{3}"

Questo richiederà un po 'di tempo per funzionare ma penso che sia corretto.

dcconta verso il basso da 14 ^ 9 a 1 e genera in base 14. egrep filtra i numeri con più di 3 cifre consecutive consecutive. Filtriamo anche tutti i nomi con cifre "0", in modo da ottenere il set corretto di lettere nei nomi.

La domanda specifica che può essere usato qualsiasi alfabeto, quindi sto usando [1-9] [AD]. Ma per i test, questo può essere trasformato in [AM] usando tr:

dc<<<Edo9^[p1-d0\<m]dsmx|egrep -v "0|(.)\1{3}" | tr 1-9A-D A-M

Questo produce la sequenza:

MMMLMMMLM MMMLMMMLL MMMLMMMLK ... AC AB AA M L K ... C B A

Nota questo dccomando richiede il ricorsione della coda per funzionare. Funziona su DC versione 1.3.95 (Ubuntu 12.04) ma non 1.3 (OSX Mavericks).


10

APL (59)

↑Z/⍨{~∨/,↑⍷∘⍵¨4/¨⎕A[⍳13]}¨Z←⊃,/{↓⍉⎕A[1+(⍵/13)⊤¯1⌽⍳13*⍵]}¨⍳9

Scritto nel suo stesso alfabeto :) È un po 'lungo. Ci vuole anche molto tempo per eseguirlo 9, provalo con un numero inferiore per testarlo se lo desideri.

Spiegazione:

  • {... }¨⍳9: per ogni numero da 1 a 9:
    • ⍳13*⍵: ottieni tutti i numeri da 1 a 13^⍵
    • ¯1⌽: Ruotare la lista verso sinistra di 1 (in modo da avere 13^⍵, 1, 2, ..., 13^⍵-1, che si trasforma in 0, 1, 2 ...modulo 13^⍵).
    • (⍵/13)⊤: codifica ogni numero nella base 13 usando le cifre
    • ⎕A[1+... ]: aggiungi uno (le matrici sono 1 indicizzate) e cerca in ⎕A(l'alfabeto)
    • ↓⍉: trasforma la matrice in un vettore di vettori lungo le colonne.
  • Z←⊃,/: unisci ogni vettore interno di vettori, dandoci un elenco di nomi possibili (ma non soddisfa ancora le regole).
  • {... : per ogni nome, verifica se soddisfa la regola dei 4 caratteri ripetuti:
    • 4/¨⎕A[⍳13]: per ogni carattere, genera una stringa di 4 di quel carattere
    • ⍷∘⍵¨: per ogni stringa, verifica se è presente in
    • ∨/,↑: accetta la logica o di tutti questi test,
    • ~: e capovolgilo, quindi 1significa che soddisfa le regole e 0significa che non lo fa.
  • Z/⍨: seleziona tra Ztutti gli elementi che incontrano i ruderi
  • : visualizza ognuno su una riga separata

9
Sono deluso. Data la sua reputazione, penseresti che APL avrebbe una soluzione a un carattere per questo, che nessuna tastiera potrebbe digitare.
Segna il

7
@Mark, sono certo che APL ce l'ha, ma nessuno sa quale sia il personaggio :)
Paul Draper,

1
si dovrebbe scrivere questo su una pietra, e quando i futuri umani lo troveranno, potrebbero semplicemente pensare che sia solo un linguaggio scritto primitivo.
CincauHangus,

9

Perl, 70 68 66 50 caratteri

$"=",";map/(.)\1{3}/||say,glob$i.="{@a}"for@a=A..M

Uso:

$ perl -E 'code' > output_file

La cosa bella è che le stampe sono bufferate, quindi ottieni prima tutte le soluzioni a 1 carattere, seguite da parole a 2 caratteri e così via.


La cosa migliore di questa soluzione è il boob a sinistra dell'1.
Dan Hanly,

8

Perl - 35 byte

#!perl -l
/(.)\1{3}|[N-Z]/||print for A..1x9

Contando lo shebang come un byte.

Questa è una traduzione libera della risposta dell'istocratico .

A..1x9è un po 'strano; questa è una scorciatoia per 'A'..'111111111'. L'accumulatore non raggiungerà mai effettivamente il valore del terminale (contiene solo lettere maiuscole), ma terminerà comunque una volta che avrà una lunghezza superiore a 9 caratteri. Questo può essere testato, ad esempio, usando 1x4invece.


Rispetto! Ora, perché non ci ho pensato? ;)
Zaid,

Nota che anche Ruby non deve creare l'intero intervallo per iterarlo. L'unica ragione per cui il codice nel mio commento richiede un'enorme quantità di memoria è che trasforma l'intervallo in un array (in modo che possa essere utilizzato Array#-).
Ventero,

@Ventero Ahh sì, greplo farà. Non sono del tutto fluente in Ruby.
primo

6

Pyg (Waaay troppo a lungo, per una lingua fatta per il golf)

sussurri : 101 ...

Pe(*ItCh(((J(x)for x in ItPr("ABCDEFGHIJKLM",repeat=j)if not An((i*3 in x)for i in x))for j in R(14))))

Anche se questo è vicino a come lo farei in Python:

from itertools import *
for i in range(14):
    for j in ("".join(k) for k in product("ABCDEFGHIJKLM",repeat=i) if not any((i*3 in k) for i in k)):
        print j

Meno ovviamente la complicazione a lungo termine;)


3

Pyth , 34 caratteri

Kf<T"n"GJKFbJI>lb9Bb~Jm+bdfXVb*Y3K

Spiegazione:

Kf<T"n"G        K = list of letters in the alphabet before n.
JK              J = copy of K
FbJ             For b in J:
I>lb9B          If length of b > 9: break
b               print(b)
~J              J+=
~Jm+bd          J+=map(lambda d:b+d,
       XVb*Y3   index of Y*3 in reversed(b)
      fXVb*Y3K  filter for non-zero for Y in K on function index of Y*3 in reversed(b)
~Jm+bdfXVb*Y3K  J+=map(lambda d:b+d, filter(lambda Y:index of Y*3 in reversed(b), K))

2

Python 2 - 212 byte

from itertools import chain,product as p
a='ABCDEFGHIJKLM'
q={c*4 for c in a}
c=0
for n in chain(*(p(*([a]*l)) for l in range(1,10))):
 n=''.join(n)
 if not any(u in n for u in q):print n
 c+=1
 if c==10**9:break

0

Japt , 21 byte

Ep9 osE kè/0|(.)\1{3}

Provalo online! (il collegamento calcola solo fino a 14**4.)

Come funziona

Ep9 osE kè/0|(.)\1{3}/

Ep9  14**9
osE  Range from 0 to n (exclusive), mapped through base-14 conversion
kè   Remove elements that match at least once...
/0|(.)\1{3}/  the regex that matches a zero or four times same char.

Presuppone un'implementazione ECMAScript 2017 standard come livello JS (e memoria sufficiente per archiviare l'array), in cui un Arrayoggetto può avere la massima 2**53-1lunghezza.

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.