Виведіть список усіх раціональних чисел


13

З усього математики завжди знайдеться кілька теорем, які виходять за рамки будь-якого здорового глузду. Одним з таких є той факт, що існують різні розміри нескінченності. Ще один цікавий факт - ідея про те, що багато нескінченностей, які здаються різними розмірами, насправді однакового розміру. Існує стільки ж парних чисел, скільки цілих чисел, скільки є раціональних чисел.

Загальна концепція цього питання полягає у протистоянні химерній реальності нескінченності. У цьому виклику ваша програма виведе список, який:

  • У будь-який конкретний момент часу завжди мати цілу кількість записів
  • Врешті-решт містять (якщо його потрібно виконувати досить довго) будь-яке конкретне (не нульове) раціональне число точно один раз у всьому списку
  • Містять необмежену кількість порожніх слотів (записи в списку, які без потреби встановлюються на 0)
  • Майте частку порожніх слотів, що наближається до межі 100%
  • Для кожного додатного цілого числа N майте нескінченну кількість місць з N послідовними порожніми прорізами

Змагання

Ваше завдання полягає в тому, щоб написати цю найкоротшу програму, яка виведе спеціальний список із наступними правилами:

  1. Усі записи з індексом, який не є квадратним числом, слід встановити на нуль. Отже, перший запис буде нульовим, другий та третій - нульовим, четвертий - ненульовим тощо.
  2. Всі раціональні числа будуть у вигляді неправильної дробу (наприклад, 4/5 або 144/13), яка була спрощена. Виняток становлять нулі, що буде просто 0.
  3. Усі (позитивні та негативні) раціональні цифри повинні з часом з’являтися у списку, якщо ваша програма працює досить довго та має достатньо пам'яті. Для будь-якого конкретного раціонального числа необхідний час може бути довільно великим, але завжди кінцевим, кількість часу.
  4. Якщо бігти протягом нескінченної кількості часу, жодне ненульове раціональне число ніколи не повинно з’являтися двічі.

Правило 3 допускає певні зміни, оскільки існує нескінченна кількість можливих юридичних результатів.

Виходом буде потік рядків. Кожен рядок буде мати загальну форму, 5: 2/3де перше число - це номер введення, а потім - раціональне число. Зауважте, що 1: 0завжди буде перший рядок виводу.

Приклад фрагменту виводу:

1: 1/1
2: 0
3: 0
4: 2/1
5: 0
6: 0
7: 0
8: 0
9: -2/1
10: 0
etc...

Правила, положення та примітки

Це код гольфу. Діють стандартні правила гольф-коду. Крім того, через різницю, дозволену у висновку, вам потрібно хоча б показати, чому ви вважаєте, що ваш список буде містити всі можливі раціональні числа точно один раз, і що ваше рішення є правильним.

EDIT: Оскільки числа простих ліній не відволікали виклик, я змінюю його на квадратні числа. Це досягає тієї ж мети, а також скорочує рішення.


1
У чому суть правила 1? Ви просто хочете, щоб люди взаємно гольфували дві окремі програми, щоб перевірити первинність і перерахувати раціональність?
Пітер Тейлор

Це показує, як дуже мала частина цілих чисел все ще має таку саму кардинальність, як і повний набір раціональних чисел, а також дозволяє відсоток порожніх слотів наближатися (але ніколи не досягати) 100%.
PhiNotPi

Я припускаю, що програма також повинна працювати у фіксованому обсязі пам'яті, тобто вона не може припустити, що машина завжди може виділити більше? Також, чи проти правил використовувати (скажімо) C int для індексу списку, коли ви знаєте, що він має обмежений діапазон? (Незважаючи на те, що точний ліміт може змінюватися залежно від реалізації.) Чи потрібна якась форма бінту?
хлібниця

1
@PhiNotPi, є набагато простіші способи зробити це, і це відволікається від більш цікавої частини питання.
Пітер Тейлор

1
Зауважте, що 1: 0завжди буде перший рядок виводу. - Це суперечить вашому прикладу і теж не має для мене сенсу.
Wrzlprmft

Відповіді:


6

Haskell, 184 символи

main=putStr.unlines$zip[1..](s>>=g)>>=h
s=(1,1):(s>>=f)
f(a,b)=[(a,a+b),(a+b,b)]
g x@(a,b)=[x,(-a,b)]
h(i,(a,b))=(i^2)%(u a++'/':u b):map(%"0")[i^2+1..i*(i+2)]
i%s=u i++": "++s
u=show

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

Вихід (без нульових рядків для стислості):

1: 1/1
4: -1/1
9: 1/2
16: -1/2
25: 2/1
36: -2/1
49: 1/3
64: -1/3
81: 3/2
100: -3/2
...

5

Мудрець, 103 113 128

Мудрець може легко перерахувати раціоналів! Форматування, щоб відповідати вимогам програми, як завжди, все руйнує.

for i,q in enumerate(QQ):
 for j in[(i-1)^2+1..i*i]:print'%d:'%j,[0,'%d/%d'%(q.numer(),q.denom())][j==i*i]

Шавлія перераховується QQвідповідно до їх висоти : максимальне абсолютне значення чисельника та знаменника після зменшення GCD.


Ви можете усунути x.next()і використовувати printтільки один раз, а саме, довівши рахунок до 124: x=enumerate(QQ) for i,q in x: for j in[(i-1)^2+1..i*i]: print'%d: '%j,'%d/%d'%(q.numer(),q.denom())if j.is_square()else 0. Це не відображається належним чином у коментарі, але я думаю, ви можете зрозуміти, що я маю на увазі.
res

До речі, зауважую, що після перших 4 позитивних елементів перерахування шавлії не таке, як в інших відповідях. Формули Калкіна-Вільфа дають послідовність, в якій знаменником раціонального є чисельник наступного раціонального; наприклад (..., 1/3, 3/2, 2/3, ...), порівняно з мудрецями (..., 1/3, 3/1, 2/3, ...). Я не можу знайти жодної документації для перерахунку Саджа, щоб побачити, як це обчислюється.
res

@res, дякую! Я хотів би об'єднати заяви про друк, але забув використати позначення [x..y]. Приємно бачити тут іншого користувача Sage!
кабіна


2

Хаскелл, 55 байт

mapM_ print$join$iterate(>>=(\x->[x+1,1/(1+1/x)]))[1%1]

виходи

1 % 1
2 % 1
1 % 2
3 % 1
2 % 3
3 % 2
1 % 3
4 % 1
...

1% 1 - корінь дерева Калкіна-Вільфа; ітерація додає обох дітей кожного вузла; приєднання згортає рівні в єдиний список.

120 символів, якщо додати належний імпорт, 0 та мінуси:

import Data.Ratio
import Control.Monad
main=mapM_ print$0:(join(iterate(>>=(\x->[x+1,1/(1+1/x)]))[1%1])>>=(\x->[-x,x]))

виходи

0 % 1
(-1) % 1
1 % 1
(-2) % 1
2 % 1
(-1) % 2
1 % 2
(-3) % 1
3 % 1
(-2) % 3
2 % 3
(-3) % 2
3 % 2
(-1) % 3
1 % 3
(-4) % 1
4 % 1
...

виведення порожніх слотів? це з поганим смаком :( ти був у мене в "списку всіх позитивних раціоналів"


mapM_ print$fix((1%1:).(>>= \x->[x+1,1/(x+1)]))становить 47 знаків. від haskellwiki . працює як є, без будь-якого імпорту, на "Спробуйте це" haskell.org "Спробуйте" (ну, без mapM_ printчастини ...)
Буде Нісс

1

PHP 105 байт

Примітка. Щоб правильно працювати, цей код повинен бути збережений як iso-8859-1 (ansi). Інтернет-перекладачі, які кодують весь вхід до utf8 за замовчуванням (наприклад, ideone), генерують неправильний вихід.

<?for($f=µ;$i++<$j*$j||++$j%2||(--$$f?$$f--:$f^=C);)echo"$i: ",$i==$j*$j?$j%2?$x=++$ö.~Ð.++$µ:"-$x":0,~õ;

Використання перерахування Георга Кантора (трохи змінено для значень +/-).

Якщо у вас виникли проблеми із запуском вищезазначеного коду (можливо, через надмірну кількість повідомлень NOTICE), скористайтеся цим замість цього (107 байт):

<?for($f=µ;$i++<$j*$j||++$j%2||(--$$f?$$f--:$f^=C);)echo"$i: ",$i==$j*$j?$j%2?$x=++$ö.'/'.++$µ:"-$x":0,'
';

1
Я отримую помилки під час виконання цього коду (який, мабуть, містить якісь дивні символи; наприклад, "$ ö. ~ Ð.").
res

Чи можете ви продемонструвати, що це рішення працює, скажімо на ideone? Я також отримую помилки: ideone.com/ru1fo
mellamokb

Схоже, Ideone помиляється, коли генерується занадто багато повідомлень NOTICE: і ~ Ð (рівне '/'), і ~ õ (рівне "\ n") будуть генерувати ПОВІДОМЛЕННЯ кожну ітерацію. Звичайно, якщо у вас відключені повідомлення, це не проблема. Паста з обома заміненими (107 байт): ideone.com/lFUbl
primo

Я щойно помітив, що інтерпретатор PHP Ideone генерує неправильний вихід. Якщо запустити код локально, ви побачите, що він правильний. Або ви можете перевірити його за допомогою дійсного інтерпретатора PHP, такого як перевірка продуктивності Anarchy Golf: golf.shinh.org/checker.html (збережіть його у файл та завантажте)
primo

Коли я зберігаю переглянутий код у файл із кодуванням ANSI, він запускається на інтерпретаторі Anarchy Golf. Однак зараз існує інша проблема: вона порушує вимогу, що "жодне ненульове раціональне число ніколи не повинно з’являтися двічі" у списку. Насправді код, як видається, перераховує кожен раціональний нескінченно багато разів; наприклад , 1/1, 2/2, 3/3, ... все ж раціонально, а також для 1/2, 2/4, 3/6, ... і т.д.
рес

0

Октава, 168 байт

a=b=p=1;do for i=(p-1)^2+1:p^2-1 printf("%d: 0\n",i)end
printf("%d: %d/%d\n",p^2,a,b)
a=-a;if a>0do if b==1 b=a+1;a=1;else a++;b--;end until 1==gcd(a,b)end
p++;until 0

Рішення не дуже складне, це просто просте діагональне проходження «килима» раціональних чисел, відкидання всіх дробів, які можна спростити. Після додатного числа a/b, навпаки -a/bзавжди друкується, перш ніж вийде наступне з послідовності.

Діагональне обхід усіх позитивних раціоналів

Оскільки всі позитивні прості дроби будуть надруковані та будуть надруковані протилежно підписані дроби, і ніколи не можливо, щоб два різні прості дроби мали однакове значення, кожне ненульове раціональне число буде надруковано рівно один раз.

Дегольф:

a=b=p=1
do
    for i=(p-1)^2+1:p^2-1
        printf("%d: 0\n",i)         # p=2,3,4: 1..3,5..8,10..15
    end
    printf("%d: %d/%d\n", p^2,a,b); # p=2,3,4: 4,9,16
    a=-a;
    if a>0                          # the rule is: after a/b, a>0 output -a/b
        do
            if b==1 b=a+1;a=1; else a++;b--; end
        until 1==gcd(a,b)
    end
    p++;
until 0
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.