9 мільярдів імен Божих


74

9 мільярдів імен Божих - це коротка історія Артура К. Кларка. Йдеться про групу тибетських ченців, наказ яких присвячений запису всіх можливих імен Бога, написаних власним алфавітом. По суті, вони присвячені написанню всіх можливих перестановок свого алфавіту, обмежених кількома правилами. У сюжеті монастир наймає деяких інженерів, щоб написати програму, щоб виконати всю роботу за них. Ваша мета - написати цю програму.

Правила:

  • В алфавіті ченця використовується 13 символів (за моїми оцінками). Ви можете використовувати ABCDEFGHIJKLMабо інший набір з 13 символів.

  • Мінімальна довжина можливого імені - 1 символ. Максимальна довжина - 9 символів.

  • Жоден символ не може повторюватися більше 3 разів поспіль. AAABAє дійсним ім'ям, але AAAABце не так.

  • Ваша програма повинна роздрукувати (у файл) всі можливі імена в послідовності від Aдо MMMLMMMLM, відокремлених будь-яким символом не в алфавіті (нові рядки, напівколонки, що завгодно).

  • Це код-гольф, і ви можете використовувати будь-яку мову. Виграє найкоротше рішення до 1 червня 2014 року.

Редагувати: імена повинні починатися Aі закінчуватися MMMLMMMLM, просуваючись по всіх мільярдах імен послідовно. Але конкретна послідовність залежить від вас. Ви можете спочатку роздрукувати всі 1-літерні імена, потім усі 2-літерні імена тощо. Або ви можете надрукувати всі імена, починаючи з A, потім усі ті, що починаються з B, або якийсь інший шаблон. Але людина повинна мати можливість прочитати файл і підтвердити, що вони всі є, і в будь-якому логічному порядку ви виберете, якщо припустити, що у них є час.


29
Ви намагаєтесь покінчити із Всесвітом, сер?
Болук Папуккуоглу

8
Посилання на історію для всіх, хто цікавиться.
ThatOneGuy


1
Це підтверджує, що кількість імен у цій проблемі дійсно становить 114559528583 (як це знайдено в програмі C на edc65 ). Виконує рішення Ross Милликена в MathSE генерує наступну поліноміальних формулу для числа імен з довжиною <= 9, для змінного алфавіту розміру до: f(k) = k^9 + k^8 + k^7 - 5*k^6 + k^5 + k^4 + 4*k^3 - 2*k^2 + k. Реалізація мудреця: goo.gl/0srwhq
res

3
@ edc65 Отже, 105.8GBвсе сказано і зроблено! Я радий, що зірки не вийшли ... або, можливо, вам доведеться роздрукувати список, щоб це сталося ...?
recursion.ninja

Відповіді:


34

Рубі, 46

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

Моє оригінальне подібне рішення було більш тривалим і неправильним (воно виводило базові 13 числа, що не зовсім з них через провідні нулі), але я залишу його тут, оскільки він все одно отримав голоси.

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

14
Добре, я запустив ваш код близько години і отримав до 2 мільярдів імен та текстовий файл 21 ГБ, перш ніж побачити це та вийти з нього. Я недооцінив, наскільки великим буде файл.
CSturgess

2
@CSturgess Ну, Рубі - не найшвидша мова для подібних речей там ...
BenjiWiebe

8
@BenjiWiebe Але все ж швидше, ніж монахи написані від руки!
Турофіл

1
Приймаю цю, бо в неї більше голосів.
CSturgess

4
Не публікуйте це як окрему відповідь, оскільки для цього потрібна величезна кількість пам'яті (~ 30 ТБ, якщо мій розрахунок є правильним), але теоретично ви можете скоротити це до 43 символів за допомогоюk=*?A..?M*9;puts k-k.grep(/(.)\1{3}|[N-Z]/)
Вентеро

24

C 140 177 235

Старий добрий процедурний стиль, без фантазії.
Він нараховує (не записує) 114559528583 імена за 8 хвилин.
Далі редагуйте разом із періодом виконання та розміром файлу імен. Спостерігайте за небом ...
Тривалість виконання 57 хвилин, розмір файлу 126,051,781,713 (9 символів + кримінальний ряд на рядок). Скажіть, будь ласка, електронну адресу ченців, щоб я міг надіслати їм заархівований файл для ручної перевірки ...

Редагував Golfed ще трохи, переробив чек на повторні листи.
Все-таки не найкоротший, але принаймні цей припиняється і генерує необхідний вихід.
Час виконання 51 хв., Розмір файлу 113,637,155,697 (цього разу немає провідних пробілів)

Побічна примітка: очевидно, вихідний файл дуже стисливий, все-таки мені довелося вбити 7zip, після роботи 36 годин він був на 70%. Дивно.

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

Безумовно

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

ні #includeз?
Саймон Куанг

@SimonKuang, деякі компілятори автоматично вводять основні (stdio).
Пол Дрейпер

1
@Simon це стандарт C. За замовчуванням глобальні об'єкти int, а глобальні функції повертають int. Візуальна студія виводить попередження C4013 про те, що "ставиться" не визначено, але все-таки воно дійсне.
edc65

4
вписується в твіт!
CincauHangus

19

Гольфскрипт, 58 47 символів

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

Завдяки Пітеру Тейлору, я позбавлений сеппуку від того, щоб не побити рішення Рубі! Запустіть код до 10 самостійно , і ось доказ, він пропускає чотири рядки .


1
Легке збереження: використовувати n+замість ''+n. Я думаю , що це в рамках правил , щоб використовувати алфавіт з керуючими символами, так що ви могли б також замінити 65+з 13+і зберегти ще один символ, називаючи 13:^. І я думаю, що це 13,{ stuff [...]могло бути 13,1/{ stuff 4*.
Пітер Тейлор

1
Моя початкова думка полягала в тому, що заощадження буде здійснюватися через фільтр, і за допомогою трохи роботи це можна зробити. З цього 13,моменту можна замінити {65+}%n+}%{ backtick {\4*/,}+78,1/%1-!},на загальну економію 8, що врятує ваше життя.
Пітер Тейлор

Поки персонаж є чимось, що ви можете фізично побачити, він буде працювати. Дійсно, ви навіть можете включити нові рядки як персонаж. Тільки до тих пір, поки є послідовність з персонажами.
CSturgess

@PeterTaylor: Ви джентльмен і науковець!
Клавдіу

Після AAAMце має бути AAABA, а ні BAAAB, правда?
justhalf

18

Утиліти командного рядка Bash + Linux, 43 байти

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

Для цього використовується аналогічна методика моєї відповіді нижче, але якраз підраховується в базі 16 і викреслюється всі "імена", що містять 0, eабо fтакож ті, що мають більше 3-х однакових послідовних цифр.

Перетворіть алфавіт ченця так:

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

Bash + coreutils (dc і egrep), 46 байт

Редагувати - виправлена ​​версія

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

Це займе певний час, але я вважаю, що це правильно.

dcвідлічує вниз від 14 ^ 9 до 1 і виводить у базу 14. egrep фільтрує числа з більш ніж 3-ма послідовними однаковими цифрами. Ми також фільтруємо будь-які імена з цифрами "0", тому отримуємо правильний набір букв в іменах.

Питання вказує, що може використовуватися будь-який алфавіт, тому я використовую [1-9] [AD]. Але для тестування це можна перетворити на [AM], використовуючи tr:

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

Це дає послідовність:

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

Зверніть увагу, що ця dcкоманда вимагає хвостової рекурсії для роботи. Це працює на dc версії 1.3.95 (Ubuntu 12.04), але не 1.3 (OSX Mavericks).


10

APL (59)

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

Написаний власним алфавітом :) Це трохи довго. Також потрібно тривати багато часу 9, спробуйте з меншим числом, щоб перевірити, якщо хочете.

Пояснення:

  • {... }¨⍳9: для кожного числа від 1 до 9:
    • ⍳13*⍵: отримати всі числа від 1 до 13^⍵
    • ¯1⌽: Повернути список вліво на 1 (у нас є 13^⍵, 1, 2..., 13^⍵-1, який перетворюється в по 0, 1, 2 ...модулю 13^⍵).
    • (⍵/13)⊤: кодуйте кожне число в базі 13 за допомогою цифр
    • ⎕A[1+... ]: додати один (масиви є 1-індексованим) та шукати в ⎕A(алфавіт)
    • ↓⍉: перетворіть матрицю у вектор векторів уздовж стовпців.
  • Z←⊃,/: приєднуйтесь до кожного внутрішнього вектора разом, даючи нам список можливих імен (але це ще не відповідає правилам).
  • {... : для кожного імені перевіряйте, чи відповідає воно правилу 4 повторних символів:
    • 4/¨⎕A[⍳13]: для кожного символу генеруйте рядок із 4 символів
    • ⍷∘⍵¨: для кожного рядка перевірити, чи він присутній у
    • ∨/,↑: взяти логічний або з усіх цих тестів,
    • ~: та інвертувати його, так що це 1означає, що він відповідає правилам, а 0значить, ні.
  • Z/⍨: виберіть з Zусіх елементів, що відповідають рулям
  • : відобразити кожного в окремому рядку

9
Я розчарований. Зважаючи на його репутацію, ви можете подумати, що APL для цього має односимвольне рішення, яке не може вводити жодна клавіатура.
Марк

7
@ Марк, я впевнений, що в APL це є, але ніхто не знає, що це за персонаж :)
Пол Дрейпер

1
слід записати це на камінь, і коли майбутні люди знайдуть це, вони можуть просто подумати, що це просто примітивна письмова мова.
CincauHangus

9

Perl, 70 68 66 50 символів

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

Використання:

$ perl -E 'code' > output_file

Приємно те, що відбитки буферні, тому ви отримуєте спочатку всі друковані рішення з 1 символом, а потім 2-символьні слова тощо.


Найкраще в цьому рішенні
цицька

8

Perl - 35 байт

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

Порахувавши шебанг як один байт.

Це нещільний переклад відповіді гістократа .

A..1x9трохи дивацтва; це скорочення для 'A'..'111111111'. Акумулятор ніколи насправді не досягне термінального значення (він містить лише великі літери), але він все одно закінчиться, коли стане довшим, ніж 9 символів. Це можна перевірити, наприклад, 1x4замість цього.


Повага! А чому я цього не придумав? ;)
Заїд

Зауважте, що Ruby не потрібно створювати весь діапазон для того, щоб його повторити. Єдина причина, що код у моєму коментарі вимагає такого величезного обсягу пам'яті, це те, що він перетворює діапазон у масив (щоб він міг використовувати Array#-).
Вентеро

@ Вентеро Ага так, grepзробимо це. Я не зовсім вільно володію Рубі.
примо

6

Pyg (Waaay занадто довго, для мови зробив для гри в гольф)

Шепіт : 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))))

Незважаючи на те, що це близько до того, як я б насправді робив це в 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

Мінус звичайного ускладнення курсу;)


3

Піт , 34 символи

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

Пояснення:

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 байт

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 байт

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

Спробуйте в Інтернеті! (посилання обчислює лише до 14**4.)

Як це працює

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.

Передбачає стандартну реалізацію ECMAScript 2017 як рівень JS (і достатньо пам'яті для зберігання масиву), де Arrayоб'єкт може мати максимальну 2**53-1довжину.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.