Створіть послідовність фігури-фігури Хофстадтера


16

У Геделя, Ешера, Баха , Дугласа Хофстадтера вводиться ціла послідовність, яку зазвичай називають послідовністю цифра-фігура:

2, 4, 5, 6, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, ...

Вам може сподобатися самостійно розробляти визначення послідовності як частину виклику, але якщо ви не можете чи не хочете розібратися в цьому, ви можете знайти його на OEIS як послідовність A030124 та дещо чіткіше визначення у Вікіпедії .

Напишіть програму або функцію, яка, задана nчерез STDIN, ARGV або аргумент функції, друкує список перших nчисел послідовності в STDOUT у будь-якому розумному форматі списку.

Це кодовий гольф, найкоротше рішення в байтах.

Відповіді:


6

CJam, 38 30 29 21 байт

li_3*,2>\{(_pX+:X-}*;

Спробуйте в Інтернеті.

Як це працює

li                     " Read an integer N from STDIN.              ";
  _3*,2>               " Push S := [ 2 3 ... (N * 3 - 1) ].         ";
        \{        }*   " Do the following N times:                  ";
          (            " Shift an integer I from S.                 ";
           _p          " Print a copy of I, followed by a linefeed. ";
             X+:X      " Execute X += I. (X is initialized to 1.)   ";
                 -     " Remove X from S.                           ";
                    ;  " Discard S from the stack.                  ";

Приклад виконання

$ cjam <(echo 'li_3*,2>\{(_pX+:X-}*;') <<< 20
2
4
5
6
8
9
10
11
13
14
15
16
17
19
20
21
22
23
24
25

Ви пропустили aditsu, коли набирали URL-адресу для перекладача
Beta Decay

@BetaDecay, то чому б не редагувати, щоб це виправити;)
Мартін Ендер

@Martin Я не думав, що мені вистачає респ ...
бета-розпад

2
@BetaDecay Ви цього не зробите, але ви все одно можете запропонувати їх (що навіть дає 2 повторення, якщо вони будуть прийняті).
Мартін Ендер

Я почував себе таким розумним, як грати з 8 додаткових байтів свого коду. Тоді я зрозумів, що зараз це робить точно так само, як відповіді гістократа, Матсхойса та Пітера Тейлора ...
Денніс

6

Хаскелл, 67 61 60 56 55 53 символів

g n=take n$2:4:h
a#(x:s)=[a..x-2]++x#s
h=5#scanl(+)8h

повернутися до першого алгоритму.

це рішення обчислює послідовність комплементу шляхом підсумовування вихідних елементів послідовності. Потім вона обчислює послідовність як усі числа між порядковими номерами комплементу.

(#)це функція, яка обчислює числа між послідовністю доповнення.
hсама послідовність.
g- це функція, яка відповідає на запитання.

функція g визначена просто для того, щоб взяти необхідну кількість елементів з h.

тонкощі:

hнасправді послідовність фігурних фігур за винятком перших 2 елементів.
обчислюється не послідовність комплектування, а послідовність комплектування з додаванням 1 для кожного елемента.
ці дві тонкощі є причиною scanl(+)8h(яка є кодом послідовності доповнення (за винятком перших 2 елементів) з доданими 1) 8. це для третього елемента послідовності доповнення з доданим до нього 1.
причина обчислення не пропускає перші два елементи в тому, що вони додані gв 2:4:h.

приклад:

>g 50
[2,4,5,6,8,9,10,11,13,14,15,16,17,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,43,44,46,47,48,49,50,51,52,53,54,55,57,58,59]

5

Рубі, 54 48

f=->n{x=1
b=*2..n*n
n.times{b-=[x+=p(b.shift)]}}

Демо

Редагувати: Це ще раз, коли я зрозумів, що мені не потрібно зберігати повну послідовність доповнення в пам'яті. Ось як це працює зараз: ми використовуємо xдля відстеження найбільшого обчисленого числа в послідовності доповнення, і bце пул кандидатів для послідовності. nразів, ми виводимо найменший елемент, що залишився, bі додаємо його xдо обчислення наступного числа в послідовності доповнення. Потім ми видаляємо обидва числа з пулу кандидатів, тому ми завжди виводимо найменше число, яке вже не було додано до жодної послідовності.

Прийоми Ruby Golf: Синтаксис лямбда-стабі коротший, ніж визначення методу. Вимога, що вихід дається STDOUT замість повернення, надихнула мене використовувати той факт, що повернене значення p(x)є x, якого я зазвичай не пам'ятаю, оскільки це не так у версії Ruby, що використовується в Anarchy Golf.


1
Як це працює?
гордий haskeller

1
FWIW ви можете використовувати 2..2*n. Мені доводиться використовувати, n*nтому що я роблю ефективно, b = [x]^bтому мені потрібен найбільший елемент, bщоб бути більшим, ніж найбільше значення x, але ваш b -= [x]просто вимагає, щоб він bмістив максимально можливе значення вихідної послідовності.
Пітер Тейлор

4

GolfScript ( 24 21 байт)

~.3*,1>\{(\(.p@+\|}*;

Демонстрація в Інтернеті

Це почалося зовсім по-іншому, але закінчилося зближенням на порту GolfScript рішення рубіка Гістократа , перш ніж Денніс висловив кілька пропозицій, які прийняли його в дещо іншому напрямку. Зокрема, друк чисел, коли ми їх ідентифікуємо, значно заощаджує їх над збиранням у масив для друку наприкінці; причина полягає в тому, що це означає, що нам ні в якому разі не потрібно турбуватися про більше ніж 3 пункти на стеку.

Розсічення

~.3*,           # Eval input n, dup, multiply by 3, make list [0 1 ... 3n-1]
1>              # Discard 0, which is part of neither sequence
\{              # Execute n times: stack contains pool of numbers not yet seen
                # in either sequence and the first element of it is the next element of the
                # complement sequence
  (\(           #   Pop two numbers from the start of the pool: stack is
                #     pool[0] pool[2..max] pool[1]
  .p            #   Print pool[1]
  @+            #   Rotate pool[0] to top and add to pool[1]
  \|            #   Place pool[0]+pool[1] at the start of the pool and
                #   (this is the clever bit) remove it from later in the pool
}*
;               # Discard the unused remainder of the pool

Якщо ви заміните ^на \-, ви можете замінити ).*на 3*. Це не заощадить жодних байтів, але це значно скоротить час роботи та використання пам'яті. - Ви повинні мати можливість зберегти один байт, зберігаючи ціле число у верхній частині масиву. Цикл матиме однакове число байтів, але ініціалізація буде на один байт коротшою.
Денніс

2
Встановити союз працює навіть краще, ніж різниця:~.3*,1>\{(\(.p@+\|}*;
Денніс

3

J - 28 char

Функція, яка бере nаргумент.

($+/\(-.~2+i.)&:>:+/)^:_&2 4

Ми запускаємо функцію, nяк аргумент як лівий, на її правому аргументі кілька разів, поки вона не призводить до зміни. Аргумент для початку - це список 2 4.

У самій функції ми беремо часткові суми +/\і повну суму +/, а потім збільшуємо їх обидві &:>:. Потім генеруємо кожне ціле число від 2 до одного більше, ніж повна сума ( 2+i.), і встановлюємо віднімання ( -.) часткових сум, залишаючи більш довгу послідовність цифра-цифра за визначенням. Нарешті, ми скорочуємо або циклічно розширюємо список на довжину n.

Результатом є те, що 2 4стає 3 7, і це видаляється з 2..8відходу 2 4 5 6 8. Після чергового раунду, 2 4 5 6 8стає 3 7 12 18 26стає

2 4 5 6 8 9 10 11 13 14 15 16 17 19 20 21 22 23 24 25 27

Таким чином ми неодноразово розширюємо послідовність фігури-фігури. $Поведінка довжини просто нетривіальна економія характеру спосіб чекає послідовності вирости до довжини nабо більше, і виводять nперші значення , коли вони перестають змінюватися. Нам також не потрібно чекати дуже довго: ми можемо отримати аж 46336 термінів із чотирьох застосувань внутрішнього дієслова.

Та ж функція в k:

  • k2, 37 символів: {{x#y@&~_lin[y:1+!1+/y;1+\y]}[x]/2 4}
  • k4, 36 символів: {{x#y@&~(y:2+!1+/y)in\:1+\y}[x]/2 4}

2

Ява - 183 158

Це було найбільше, що я коли-небудь коли-небудь займався гольфом, і я пишаюся цим! (Хоча його немає ніде вгорі діаграм (адже це Java))

Дякую Пітеру Тейлору за пропозиції

class f{public static void main(String[]a){int q=1,m=Byte.valueOf(a[0]),w=2,n[]=new int[m*m*2];for(n[q+=w]=1;m-->0;){System.out.println(w);for(;n[++w]>0;);}}}

більший -

public class f {
    public static void main(String[] a) {
        int q = 1, m = Byte.valueOf(a[0]), w = 2, n[] = new int[m * m * 2];
        for (n[q += w] = 1; m-- > 0;) {
            System.out.println(w);
            for (; n[++w] > 0;)
                ;
        }
    }
}

Цей внутрішній цикл для циклу досить вражаючий, але я думаю, що ви можете зберегти кілька байт. Byte.valueOfзаощаджує три, і оскільки питання не визначає діапазон введення, я думаю, він повинен бути прийнятним. Поза петлями, mвикористовується лише для ініціалізації n, так, k++<mможливо m-->0, усунення kцілком. int[] nможе бути ініціалізований як int n[]і об'єднаний у попередній ініціалізатор. nніколи не має інших значень, ніж 1це n[...]!=0могло бути n[...]>0. Потім ініціалізатор може стати ініціалізаторною частиною першого forциклу.
Пітер Тейлор

І якщо ви позбудетеся від uі просто використовувати ++w, немає необхідності встановлювати n[q]або n[w]. Є одна помилка в тому, що ви біжите в кінці, nколи m==2, здається, найкраще виправити ініціалізацію n=new int[2*m*m], але я думаю, що це до 157 байт.
Пітер Тейлор

Те, що я мав на увазі про те, що ініціалізатор став частиною першого ініціалізатора для циклу, - це for(int q=1,w=2,m=...,n[]=...;m-->0;){...збереження крапки з комою.
Пітер Тейлор

1

Python 2 - 77 байт


Код:

n=input();x=1;b=range(2,n*n)
while n:v=b.pop(0);x+=v;print v;b.remove(x);n-=1

Працює так само, як рішення @ histocrat, за винятком введення даних від stdin.



0

Желе , 15 байт

SƤŻ‘µṀ‘Rḟ
2dz¡ḣ

Спробуйте в Інтернеті!

Помилка пам'яті на вході 6.

Як це працює

SƤŻ‘µṀ‘Rḟ  Aux. link (monad). Input: part of the desired sequence
SƤŻ‘       Sum of prefixes, then prepend a zero and increment
           This is a list of numbers to exclude from the next iteration
    µ      Re-focus on the above
     Ṁ‘Rḟ  Create range 1..Max + 1, then remove all elements of the above
           +1 is needed to progress from [2] to [2,4]

2dz¡ḣ  Main link (monad). Input: n, number of terms
2dz¡   Starting from 2, apply aux. link n times
    ḣ  Take n elements from the beginning

Більш ефективна версія, 16 байт

SƤŻ‘µṀ‘Rḟḣ³
2ÇÐL

Спробуйте в Інтернеті!

Використовує ідею з цього J відповіді . Скоротіть кожну ітерацію до потрібної довжини та візьміть точку фіксації. Я думав використовувати S(sum) замість Ṁ‘(max + 1), але не можу гарантувати її коректність.


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