9 miliardów imion Boga


74

9 miliardów imion Boga to krótka historia Arthura C. Clarke'a. Chodzi o grupę tybetańskich mnichów, których porządek poświęcony jest spisaniu wszystkich możliwych imion Boga, zapisanych własnym alfabetem. Zasadniczo poświęcają się pisaniu każdej możliwej permutacji swojego alfabetu, ograniczonej kilkoma zasadami. W opowieści klasztor zatrudnia inżynierów, aby napisali program, który wykona za nich całą pracę. Twoim celem jest napisanie tego programu.

Zasady:

  • Alfabet mnicha używa 13 znaków (według moich szacunków). Możesz użyć ABCDEFGHIJKLMlub innego zestawu 13 znaków.

  • Minimalna długość możliwej nazwy to 1 znak. Maksymalna długość wynosi 9 znaków.

  • Żadna postać nie może powtarzać więcej niż 3 razy z rzędu. AAABAjest prawidłową nazwą, ale AAAABnie jest.

  • Twój program powinien wydrukować (do pliku) każdą możliwą nazwę w kolejności od Ado MMMLMMMLM, oddzieloną dowolnym znakiem spoza alfabetu (znaki nowej linii, średniki, cokolwiek).

  • To jest golf golfowy i możesz używać dowolnego języka. Najkrótsze rozwiązanie do 1 czerwca 2014 wygrywa.

Edycja: nazwy powinny zaczynać się Ai kończyć MMMLMMMLM, przechodząc kolejno przez wszystkie miliardy nazw. Ale konkretna sekwencja należy do ciebie. Możesz wydrukować najpierw wszystkie 1-literowe nazwy, a następnie wszystkie 2-literowe nazwy itp. Lub możesz wydrukować wszystkie nazwy zaczynające się od A, a następnie wszystkie zaczynające się od Blub inny wzór. Ale człowiek powinien być w stanie odczytać plik i potwierdzić, że wszystko tam jest i w dowolnej logicznej kolejności, którą wybierzesz, zakładając, że ma czas.


29
Próbujesz zakończyć wszechświat, proszę pana?
Boluc Papuccuoglu

8
Link do historii dla wszystkich zainteresowanych.
ThatOneGuy


1
To weryfikuje, że liczba nazw w obecnym problemie rzeczywiście wynosi 11 459 252 883 (jak stwierdzono w programie C edc65 ). Wykonawczego roztwór Ross Millikana jest w MathSE generuje następującego wielomianu wzoru na wielu nazw o długości <= 9, dla zmiennej alfabetu wielkości k: f(k) = k^9 + k^8 + k^7 - 5*k^6 + k^5 + k^4 + 4*k^3 - 2*k^2 + k. Wdrożenie Sage: goo.gl/0srwhq
res

3
@ edc65 Więc 105.8GBwszystko powiedziane i zrobione! Cieszę się, że gwiazdy nie zgasły ... a może musisz wydrukować listę, aby tak się stało ...?
recursion.ninja

Odpowiedzi:


34

Ruby, 46

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

Moje oryginalne, podobne rozwiązanie było dłuższe i niepoprawne (generuje liczby bazowe 13, co nie jest całkiem wszystkie z powodu wiodących zer), ale zostawię to tutaj, ponieważ i tak uzyskało głosy.

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

14
Cóż, uruchomiłem twój kod przez około godzinę i dostałem do 2 miliardów nazw i 21 GB pliku tekstowego, zanim to zobaczyłem i zamknąłem. Nie doceniłem wielkości pliku.
CSturgess

2
@CSturgess Cóż, Ruby nie jest najszybszym językiem dla tego rodzaju rzeczy na rynku ...
BenjiWiebe

8
@BenjiWiebe Ale wciąż szybciej niż odręcznie napisane przez mnichów!
Turophile

1
Zaakceptowanie tego, ponieważ ma więcej głosów.
CSturgess

4
Nie publikowanie tego jako oddzielnej odpowiedzi, ponieważ wymaga ogromnie dużej ilości pamięci (~ 30 TB, jeśli moje obliczenia są poprawne), ale teoretycznie można to skrócić do 43 znaków za pomocąk=*?A..?M*9;puts k-k.grep(/(.)\1{3}|[N-Z]/)
Ventero

24

C 140 177 235

Dobry stary styl proceduralny, bez fantazji.
Liczy (bez zapisu) 11 459 252 883 nazw w 8 minut.
Następnie dokonaj edycji za pomocą środowiska wykonawczego i rozmiaru pliku nazw. Obserwuj niebo ...
Czas działania 57 minut, rozmiar pliku 126 051,781,713 (9 znaków + crlf na wiersz). Podaj mi adres e-mail mnichów, abym mógł wysłać im spakowany plik do sprawdzenia ręcznego ...

Edytuj Gra w golfa jeszcze trochę, przerobiono czek dla powtarzających się liter.
Nadal nie najkrótszy, ale przynajmniej ten kończy się i generuje wymaganą moc wyjściową.
Czas działania 51 min, rozmiar pliku 113 637 155 697 (tym razem bez wiodących odstępów)

Uwaga dodatkowa: oczywiście plik wyjściowy jest bardzo ściśliwy, nadal musiałem zabić 7zip, po 36 godzinach pracy wynosił 70%. Dziwne.

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);}

Nie golfił

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);
            }
        }
    }
}

nie ma #include?
Simon Kuang

@ SimonKuang, niektóre kompilatory automatycznie wstawią podstawowe (stdio).
Paul Draper

1
@ Simon to standard C. Domyślnie obiektami globalnymi są int, a funkcje globalne zwracają int. Visual Studio wyświetla C4013 ostrzeżenie o „puts” nie zdefiniowane, ale i tak jest ważne.
edc65

4
zmieści się w tweecie!
CincauHangus

19

Golfscript, 58 47 znaków

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

Dzięki Peterowi Taylorowi oszczędziłem seppuku od nie bicia rozwiązania Ruby! Uruchom sam kod do 10 , a oto dowód na to, że pomija liczby cztery w rzędzie .


1
Łatwe zapisywanie: użyj n+zamiast ''+n. Myślę, że to w ramach zasad korzystania ze znaków alfabetu kontrolnych, więc można również wymienić 65+ze 13+i zapisać inną postać nazywając 13:^. I myślę, że tak 13,{ stuff [...]może być 13,1/{ stuff 4*.
Peter Taylor

1
Początkowo myślałem, że oszczędzanie nastąpi poprzez filtr i przy odrobinie pracy można to zrobić. Od tego czasu 13,można zastąpić {65+}%n+}%{ backtick {\4*/,}+78,1/%1-!},całkowitą oszczędnością 8, ratując życie.
Peter Taylor

Dopóki postać jest czymś, co można fizycznie zobaczyć, będzie działać. Naprawdę możesz nawet uwzględnić nowe znaki jako postać. Tak długo, jak postacie mają sekwencję.
CSturgess

@PeterTaylor: Jesteś dżentelmenem i uczonym!
Claudiu

Po AAAMtym powinno być AAABA, a nie BAAAB, prawda?
justhalf

18

Narzędzia linii poleceń Bash + Linux, 43 bajty

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

Używa techniki podobnej do mojej poniższej odpowiedzi, ale po prostu liczy się w bazie 16 i usuwa wszystkie „nazwy” zawierające 0, elub fteż te, które zawierają więcej niż 3 takie same kolejne cyfry.

Konwertuj na alfabet mnicha w następujący sposób:

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

Bash + coreutils (dc i egrep), 46 bajtów

Edycja - poprawiona wersja

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

Uruchomienie zajmie trochę czasu, ale myślę, że jest poprawne.

dcodlicza w dół od 14 ^ 9 do 1 i wyświetla w bazie 14. egrep odfiltrowuje liczby z więcej niż 3 kolejnymi cyframi. Odfiltrowujemy również nazwy zawierające cyfry „0”, więc otrzymujemy prawidłowy zestaw liter w nazwach.

Pytanie określa, że ​​można użyć dowolnego alfabetu, więc używam [1-9] [AD]. Ale w celu przetestowania można to przekształcić do [AM] za pomocą tr:

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

Daje to sekwencję:

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

Uwaga: to dcpolecenie wymaga rekurencji ogona do działania. Działa to na wersji DC 1.3.95 (Ubuntu 12.04), ale nie 1.3 (OSX Mavericks).


10

APL (59)

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

Napisane własnym alfabetem :) Jest trochę długie. Uruchomienie zajmuje również dużo czasu 9, wypróbuj go z niższą liczbą, aby przetestować, jeśli chcesz.

Wyjaśnienie:

  • {... }¨⍳9: dla każdej liczby od 1 do 9:
    • ⍳13*⍵: uzyskaj wszystkie liczby od 1 do 13^⍵
    • ¯1⌽: Obracać listę w lewo o 1 (tak mamy 13^⍵, 1, 2, ..., 13^⍵-1, który zamienia się 0, 1, 2 ...modulo 13^⍵).
    • (⍵/13)⊤: zakoduj każdy numer w bazie 13 za pomocą cyfr
    • ⎕A[1+... ]: dodaj jeden (tablice są indeksowane 1) i wyszukaj ⎕A(alfabet)
    • ↓⍉: zamień macierz w wektor wektorów wzdłuż kolumn.
  • Z←⊃,/: połącz ze sobą każdy wewnętrzny wektor wektorów, dając nam listę możliwych nazw (ale nie spełnia jeszcze reguł).
  • {... : dla każdej nazwy sprawdź, czy spełnia zasadę 4 powtórzeń:
    • 4/¨⎕A[⍳13]: dla każdego znaku wygeneruj ciąg 4 tego znaku
    • ⍷∘⍵¨: dla każdego łańcucha sprawdź, czy jest obecny w
    • ∨/,↑: podejmij logiczne lub wszystkie z tych testów,
    • ~: i odwróć to, co 1oznacza, że ​​spełnia zasady i 0oznacza, że ​​nie.
  • Z/⍨: wybierz spośród Zwszystkich elementów, które spełniają ruiny
  • : wyświetl każdy w osobnym wierszu

9
Jestem rozczarowany. Biorąc pod uwagę jego reputację, można by pomyśleć, że APL miałoby do tego jednoznakowe rozwiązanie, którego żadna klawiatura nie mogłaby pisać.
Mark

7
@ Mark, jestem pewien, że APL ma to, ale nikt nie wie, co to za postać :)
Paul Draper

1
należy napisać to na kamieniu, a kiedy przyszli ludzie to znajdą, mogą pomyśleć, że to po prostu prymitywny język pisany.
CincauHangus

9

Perl, 70 68 66 50 znaków

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

Stosowanie:

$ perl -E 'code' > output_file

Zaletą jest to, że wydruki są buforowane, więc najpierw drukowane są wszystkie rozwiązania 1-znakowe, a następnie słowa 2-znakowe i tak dalej.


Najlepszą rzeczą w tym rozwiązaniu jest piersi po lewej stronie 1.
Dan Hanly

8

Perl - 35 bajtów

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

Licząc shebang jako jeden bajt.

To luźne tłumaczenie odpowiedzi histokraty .

A..1x9jest trochę dziwny; to jest skrót 'A'..'111111111'. Akumulator nigdy nie osiągnie wartości końcowej (zawiera tylko duże litery), ale nadal będzie się kończył, gdy będzie dłuższy niż 9 znaków. Można to przetestować, na przykład, używając 1x4zamiast tego.


Szacunek! Dlaczego o tym nie pomyślałem? ;)
Zaid

Zauważ, że Ruby nie musi również tworzyć całego zakresu w celu iteracji. Jedynym powodem, dla którego kod w moim komentarzu wymaga tak ogromnej ilości pamięci, jest to, że zamienia zakres w tablicę (aby mogła go użyć Array#-).
Ventero

@Ventero Ahh tak, grepzrobi to. Nie jestem całkowicie biegły w Ruby.
primo

6

PYG (waaay zbyt długo, na języku, do golfa)

szepty : 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))))

Mimo że jest to bliskie tego, jak bym to zrobił w Pythonie:

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

Pomijając oczywiście komplikacje z długiej linii;)


3

Pyth , 34 znaki

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

Wyjaśnienie:

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 bajtów

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 bajtów

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

Wypróbuj online! (link oblicza tylko do 14**4.)

Jak to działa

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.

Zakłada standardową implementację ECMAScript 2017 jako warstwę JS (i wystarczającą ilość pamięci do przechowywania tablicy), w której Arrayobiekt może mieć maksymalną 2**53-1długość.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.