Женские и мужские последовательности


20

Этот вопрос, вероятно, сложнее, чем все эти задачи «сгенерировать последовательность чисел», потому что для этого требуется, чтобы две последовательности работали в унисон.

Очень жду ответов!

В своей книге « Гёдель, Эшер, Бах: вечная золотая коса » Дуглас Хофштадтер имеет довольно много последовательностей чисел внутри, все они в некоторой степени полагаются на предыдущий термин. Информацию обо всех последовательностях смотрите на этой странице Википедии .

Одна пара последовательностей, которая действительно интересна, - это последовательности «Женский» и «Мужской», которые определены следующим образом:

для n > 0.

Вот женская последовательность и мужская последовательность .

Ваша задача, когда в nкачестве входных данных задано целое число , вернуть список последовательностей «Женский» и «Мужской» с количеством членов, равным nв двух строках вывода, с последовательностью «Женский» в первой строке и последовательностью «Мужской» в секунда.

Примеры входов и выходов: Вход: 5 Выход:[1, 1, 2, 2, 3] [0, 0, 1, 2, 2]

Вход: 10 Выход:[1, 1, 2, 2, 3, 3, 4, 5, 5, 6] [0, 0, 1, 2, 2, 3, 4, 4, 5, 6]

ПРИМЕЧАНИЕ. Разделение между списками означает разрыв строки.

Это код-гольф, поэтому выигрывает самый короткий код в байтах. Кроме того, добавьте объяснение для вашего кода.

Leaderboard


5
Можем ли мы вернуть пару списков из функции вместо печати списков?
Згарб

Другие проблемы , связанные с последовательностями Хофштадтера: последовательность Q , фигура-фигура последовательность
Мартин Эндер

@Zgarb Вы можете, если два списка находятся в разных строках.
clismique

2
@DerpfacePython В паре списков нет строк ; если функция возвращает пару списков, вы можете распечатать их по своему усмотрению. Это, как говорится, я не большой поклонник требования линий, даже при выводе на печать. Громоздкие форматы ввода / вывода - это одна из вещей, которую следует избегать при написании задач.
Деннис

4
Это не имеет большого значения для некоторых подходов / языков, но может иметь большое значение для других. В C можно сохранить много байтов, печатая последовательности в столбцах, а не в строках. В Python самый короткий подход, который я могу придумать, - это рекурсивная лямбда, похожая на мой рекурсивный ответ Джулии, который возвращает пару списков, но необходимость преобразования этого в строку с переводом строки делает ее намного длиннее, даже дольше, чем полная программа опубликовано Sp3000. Другие подходы, такие как рекурсивное решение с обратным отсчетом, а не с верхом, полностью исключены, так как добавить новую строку невозможно.
Деннис

Ответы:


3

Желе , 22 20 байт

ṙṪḢạL}ṭ
çƓḤ¤Ð¡1ṫ-Ṗ€G

Попробуйте онлайн!

Как это устроено

çƓḤ¤Ð¡1ṫ-Ṗ€G  Main link. No user arguments. Left argument defaults to 0.
   ¤          Combine the two links to the left into a niladic chain.
 Ɠ              Read an integer from STDIN.
  Ḥ             Unhalve/double it.
ç   С1       Call the helper link that many times. Return all results.
              In the first call, the left and right argument are 0 and 1 resp.
              After each iteration, the left argument is set to the return value
              and the right argument to the prior value of the left one.
       ṫ-     Tail -1; keep the last two items of the list of results.
         Ṗ€   Discard the last item of each list.
           G  Grid; format the pair of lists.


ṙṪḢạL}ṭ       Helper link. Arguments: x, y (lists)

ṙ             Rotate x k units to the left, for each k in y.
 Ṫ            Tail; extract the last rotation.
  Ḣ           Head; extract the last element.
              This essentially computes x[y[-1]] (Python notation), avoiding
              Jelly's 1-based indexing.
    L}        Yield the length of y.
   ạ          Take the absolute difference of the results to both sides.
      ṭ       Tack; append the difference to y and return the result.

5
И это та часть, где я горжусь собой за то, что принял вызов, который заставляет желе использовать более 10 байтов.
clismique

13

Юлия, 52 48 байтов

x->[n÷φ|(5n^2|4∈(2:3n).^2)for| =(+,-),n=1:x]

Попробуйте онлайн!

Фон

В книге «О женатых функциях Хофштадтера» автор показывает, что

Формула F / M

где φ обозначает золотое сечение ,

формула дельта / эпсилон

и F n обозначает n- е число Фибоначчи .

Кроме того, в « Продвинутых задачах и решениях» H-187: Фибоначчи - это квадрат , предлагающий показывает, что

Личность Фибоначчи / Лукаса

где L n обозначает n- е число Лукаса , и это - наоборот - если

обратная личность Фибоначчи / Лукаса

тогда n - это число Фибоначчи, а m - это число Лукаса.

Из этого мы выводим, что

дельта / эпсилон теорема

всякий раз, когда п> 0 .

Как это устроено

С учетом вводом х , мы строим 2 по й матрице, где | это сложение в первом столбце и вычитание во втором, и n перебирает целые числа от 1 до x в строках.

Первое слагаемое как F (n - 1), так и M (n - 1) просто n÷φ.

Мы вычисляем δ (n) и ε (n) , вычисляя 5n² | 4 и проверка, принадлежит ли результат массиву квадратов целых чисел от 2 до 3n . Это проверяет и на прямоугольность, и, поскольку 1 не находится в диапазоне, для n> 1, если | это вычитание.

Наконец, мы добавляем или вычитаем логическое значение, полученное из 5n^2|4∈(2:3n).^2или из ранее вычисленного целого числа.


это может быть выражено нерекурсивным / итеративным способом? Какова закрытая форма для этого?
Abr001am

Я добавил объяснение.
Деннис

11

Python 2, 79 70 байт

a=0,;b=1,
exec"a,b=b,a+(len(a)-b[a[-1]],);"*~-input()*2
print b,'\n',a

Итеративный, а не рекурсивный, потому что почему бы и нет. Первая строка имеет завершающий пробел - если это не хорошо, это можно исправить для дополнительного байта. -9 байт благодаря @Dennis.

Вот несколько комбинированных лямбд, которые не очень помогли:

f=lambda n,k:n and n-f(f(n-1,k),k^1)or k
f=lambda n,k:[k][n:]or f(n-1,k)+[n-f(f(n-1,k)[-1],k^1)[-1]]

Обе принимают nи параметр kлибо 0 или 1, указывая мужской / женский. Первая лямбда возвращает n-й элемент, а вторая лямбда возвращает первые n элементов (с экспоненциальным временем выполнения).


9

MATL , 23 байта

1Oiq:"@XJth"yy0)Q)_J+hw

Попробуйте онлайн!

объяснение

Это работает итеративно. Каждая последовательность хранится в массиве. Для каждого индекса n вычисляется новый член каждой последовательности и присоединяется к соответствующему массиву. Используется forцикл с N -1 членами, где N - входное число.

Обновление для последовательности M должно быть сделано в первую очередь. Это связано с тем, что последовательность F всегда больше или равна последовательности M для одного и того же индекса, поэтому, если мы попытаемся сначала обновить F, нам понадобится член M, который еще не вычислен.

Два уравнения обновления одинаковы, меняя F и M. Таким образом, код для обновления используется повторно, применяя forцикл с двумя итерациями и меняя последовательности в стеке.

1        % Push 1: seed for F sequence
O        % Push 0: seed for M sequence
iq:      % Input N. Generate range [1 2 ... N-1]
"        % For each (i.e. iterate N-1 times)
  @      %   Push current index, n (starting at 1 and ending at N-1)
  XJ     %   Copy to clipboard J
  th     %   Duplicate and concatenate. This generates a length-2 array
  "      %   For each (i.e. iterate twice)
    yy   %   Duplicate top two elements, i.e. F and M sequences
    0)   %     In the *first* iteration: get last entry of M, i.e M(n-1)
    Q)   %     Add 1 and index into F. This is F(M(n-1))
    _J+  %     Negate and add n. This is n-F(M(n-1)), that is, M(n)
    h    %     Concatenate to update M
    w    %     Swap top two elements, to bring F to top.
         %     In the *second* iteration the procedure is repeated to update F,
         %     and then the top two elements are swapped to bring M to top again,
         %     ready for the next iteration of the outer loop
         %   End for implicitly
         % End for implicitly
         % Display implicitly from bottom to top: first line is F, second is M

6

J, 47 байт

f=:1:`(-m@f@<:)@.*
m=:0:`(-f@m@<:)@.*
(f,:m)@i.

Использует рекурсивное определение. Первые две строки определяют глаголы fи mкоторые представляют женские и мужские функции, соответственно. Последняя строка - это глагол, который принимает один аргументn и выводит первые nчлены женской и мужской последовательности.

использование

   (f,:m)@i. 5
1 1 2 2 3
0 0 1 2 2
   (f,:m)@i. 10
1 1 2 2 3 3 4 5 5 6
0 0 1 2 2 3 4 4 5 6

6

JavaScript (ES6), 75 байт

g=n=>--n?([f,m]=g(n),m=[...m,n-f[m[n-1]]],[[...f,n-m[f[n-1]]],m]):[[1],[[0]]

Я мог бы сохранить 2 байта, если бы мне было разрешено сначала вернуть последовательность Male:

g=n=>--n?([f,m]=g(n),[m=[...m,n-f[m[n-1]]],[...f,n-m[f[n-1]]]]):[[1],[[0]]

6

Haskell, 57 байт

l#s=scanl(\a b->b-l!!a)s[1..]
v=w#1
w=v#0
(<$>[v,w]).take

Пример использования: (<$>[v,w]).take $ 5->[[1,1,2,2,3],[0,0,1,2,2]]

Вспомогательная функция #создает бесконечный список с начальным значением sи списком lдля поиска всех дальнейших элементов (по индексу предыдущего значения). v = w#1это женская и w = v#0мужская последовательность. В основной функции мы берем первые nэлементы обоих vи w.


4

Python 2, 107 байт

F=lambda n:n and n-M(F(n-1))or 1
M=lambda n:n and n-F(M(n-1))
n=range(input())
print map(F,n),'\n',map(M,n)

Попробуйте онлайн

Большие входные значения вызывают RuntimeError (слишком много рекурсии). Если это проблема, я могу написать версию, где ошибка не возникает.



3

Pyth, 24 байта

Возможно, невозможно использовать reduce для уменьшения количества байтов.

Простая реализация.

L&b-b'ytbL?b-by'tb1'MQyM

Попробуйте онлайн!

Как это устроено

L&b-b'ytb  defines a function y, which is actually the male sequence.

L          def male(b):
 &b            if not b: return b
   -b          else: return b-
     'ytb            female(male(b-1))


L?b-by'tb1 defines a function ', which is actually the female sequence.

L          def female(b):
 ?b            if b:
   -by'tb          return b-male(female(b-1))
         1     else: return 1


'MQ        print(female(i) for i from 0 to input)
yMQ        print(male(i) for i from 0 to input)

Включить ли анаграмматизированное имя или ваше оригинальное имя в таблицу лидеров? Кроме того, этот код ужасно длинный для программы Pyth.
clismique

Как давно ты здесь? Почему ты узнал, что я сменил имя? Поместите мое новое имя туда.
Утренняя монахиня

1
Я был здесь достаточно долго, чтобы знать, что ты сменил свое имя.
clismique

@DerpfacePython Видя, что другие ответы почти в 4 раза длиннее ... Я бы сказал, что мое решение не очень длинное.
Утренняя монахиня

Это очень верно, но это все еще долго по сравнению с другими программами Pyth для других вопросов.
clismique

3

Брахилог , 65 байт

:{:1-:0re.}fL:2aw,@Nw,L:3aw
0,1.|:1-:2&:3&:?--.
0.|:1-:3&:2&:?--.

Моя попытка объединить оба предиката для мужчины и женщины в один на самом деле удлинила код.

Вы можете использовать следующий один лайнер, который имеет такое же количество байтов:

:{:1-:0re.}fL:{0,1.|:1-:2&:3&:?--.}aw,@Nw,L:{0.|:1-:3&:2&:?--.}aw

Заметка : это работает с транспорером Prolog, а не со старым Java.

объяснение

Основной предикат:

:{:1-:0re.}fL                Build a list L of integers from 0 to Input - 1
             :2aw            Apply predicate 2 to each element of L, write the resulting list
                 ,@Nw        Write a line break
                     ,L:3aw  Apply predicate 3 to each element of L, write the resulting list

Предикат 2 (женский):

0,1.                         If Input = 0, unify Output with 1
    |                        Else
     :1-                     Subtract 1 from Input
        :2&                  Call predicate 2 with Input - 1 as argument
           :3&               Call predicate 3 with the Output of the previous predicate 2
              :?-            Subtract Input from the Output of the previous predicate 3
                 -.          Unify the Output with the opposite of the subtraction

Предикат 3 (мужчина):

0.                           If Input = 0, unify Output with 0
  |                          Else
   :1-                       Subtract 1 from Input
      :3&                    Call predicate 3 with Input - 1 as argument
         :2&                 Call predicate 2 with the Output of the previous predicate 3
            :?-              Subtract Input from the Output of the previous predicate 3
               -.            Unify the Output with the opposite of the subtraction

Подождите ... какой предикат 3?
clismique

Исправлена ​​ошибка @DerpfacePython. Также обратите внимание, что предикат one {:1-:0re.}используется для создания списка диапазонов.
Fatalize

3

Clojure, 132 131 байт

(fn [n](loop[N 1 M[0]F[1]](if(< N n)(let[M(conj M(- N(F(peek M))))F(conj F(- N(M(peek F))))](recur(inc N)M F))(do(prn F)(prn M)))))

Просто строит последовательности итеративно от нуля до n.

Неуправляемая версия

(fn [n]
  (loop [N 1 M [0] F [1]]
    (if (< N n)
      (let [M (conj M (- N (F (peek M))))
            F (conj F (- N (M (peek F))))]
        (recur (inc N) M F))
      (do
        (prn F)
        (prn M)))))

Хороший ответ, добро пожаловать на сайт! Нужен ли пробел или перевод строки? Я считаю 131 + завершающий пробел.
DJMcMayhem

Нет, нет необходимости в конце пробела. Подлый vim добавил новую строку в конце для подсчета wc.
отметка

3

Pyth, 23 байта

jCuaG-LHtPs@LGeGr1Q],1Z

Попробуйте онлайн: демонстрация

Объяснение:

jCuaG-LHtPs@LGeGr1Q],1Z

  u                ],1Z    start with G = [[1, 0]]
                           (this will be the list of F-M pairs)
  u             r1Q        for each H in [1, 2, ..., Q-1]:
              eG              take the last pair of G [F(H-1), M(H-1)]
           @LG                lookup the pairs of these values:
                              [[F(F(H-1)), M(F(H-1))], [F(M(H-1)), M(M(H-1))]]
          s                   join them:
                              [F(F(H-1)), M(F(H-1)), F(M(H-1)), M(M(H-1))]
        tP                    get rid of the first and last element:
                              [M(F(H-1)), F(M(H-1))]
     -LH                      subtract these values from H
                              [H - M(F(H-1)), H - F(M(H-1))]
   aG                         and append this new pair to G
jC                         at the end: zip G and print each list on a line

Альтернативное решение, которое использует функцию вместо Redu (также 23 байта):

L?>b1-LbtPsyMytb,1ZjCyM

Ницца. Очень мило на самом деле.
Дрянная Монахиня

3

Рубин, 104 92 97 82 байта

f=->n,i{n>0?n-f[f[n-1,i],-i]:i>0?1:0}
->n{[1,-1].map{|k|p (0...n).map{|i|f[i,k]}}}

Редактировать: f и mтеперь одна функция благодаря HopefullyHelpful . Я изменил вторую функцию для печати fтогда m. Пробел послеp является значительным, так как в противном случае функция печатает (0...n)вместо результата map.

Третья функция печатает сначала массив первых n членов f , а затем массив первых n членовm

Эти функции называются так:

> f=->n,i{n>0?n-f[f[n-1,i],-i]:i>0?1:0}
> s=->n{[1,-1].map{|k|p (0...n).map{|i|f[i,k]}}}
> s[10]
[1, 1, 2, 2, 3, 3, 4, 5, 5, 6]
[0, 0, 1, 2, 2, 3, 4, 4, 5, 6]

Вы можете бросить р и Паренс. Вывод не требуется для печати. Кроме того, вы можете перетянуть парней вокруг диапазона.
Не то, что Чарльз

Вы можете заменить функцию 2 на 1, которая имеет 2 аргумента nиi n>0?n-f(f(n-1,i),-i):i>0?1:0
HopefullyHelpful

@HopefullyHelpful Спасибо большое: D
Sherlock9

@NotthatCharles Не требуется ли вывод на печать? В Ruby, если я хочу, чтобы разрыв строки между fи m, мне нужно было распечатать. В противном случае, я просто получаю массив, как[[1, 1, 2, 2, 3, 3, 4, 5, 5, 6], [0, 0, 1, 2, 2, 3, 4, 4, 5, 6]]
Sherlock9

о, это говорит "разрыв строки". Печалька.
Не то, что Чарльз

3

APL (Dyalog Unicode) , 45 25 байт

Анонимная молчаливая функция. Требуется ⎕IO←0, что является стандартным для многих систем APL.

1 0∘.{×⍵:⍵-(~⍺)∇⍺∇⍵-1⋄⍺}⍳

Попробуйте онлайн!

Это работает путем объединения F и M в одну двоичную функцию с логическим левым аргументом, который выбирает функцию для применения. Мы используем 1 для F и 0 для M, чтобы мы могли использовать этот селектор в качестве возвращаемого значения для F  (0) и M  (0). Затем мы видим, что обе функции должны сначала вызывать себя (для аргумента минус один), а затем другую функцию в результате этого, поэтому сначала мы выполняем рекурсивный поиск с заданным селектором, а затем с логически отрицательным селектором.

nd ndice; ноль через аргумент минус один

1 0∘.{...}  Внешний (декартовый) «продукт» (но с функцией ниже вместо умножения), использующий в [1,0]качестве левых аргументов ( ) и индексы в качестве правых аргументов ( ):

×⍵ если правильный аргумент строго положительный (обозначен знаком правильного аргумента):

  ⍵-1 вычесть одно из правильного аргумента

  ⍺∇ вызвать себя с этим в качестве правого аргумента и левый аргумент в качестве левого аргумента

  (~⍺)∇ называть себя с этим в качестве правого аргумента и логическим отрицанием левого аргумента в качестве левого аргумента

  ⍵- вычтите это из правильного аргумента и верните результат

 еще:

   вернуть левый аргумент


Это хорошо работает, но при условии , что входные данные хранятся в переменной, по умолчанию запрещено.
Деннис

@ Денис Это не совсем. Это тфн тело. Когда я был здесь новичком, ngn сказал мне, что мне не нужно считать заголовок tfn (это будет два байта, имя с одним символом + символ новой строки, точно так же, как не учитывается имя исходного файла, и разрешены анонимные fns). Также и здесь, где заголовок представляет собой 1-символьное имя + пробел + 1-символьный аргумент name ( n) + плюс
символ

Что именно такое TFN?
Деннис

@Dennis Tfns - традиционное представление функций в APL. Состоит из строк кода практически без ограничений dfns . Например, вы можете иметь правильные структуры управления и выражения без результата. Строка «0» - это заголовок, который указывает синтаксис fn .
Адам

2

ES6, 89 85 83 байта

2 байта сохранены благодаря @ Bálint

x=>{F=[n=1],M=[0];while(n<x){M.push(n-F[M[n-1]]);F.push(n-M[F[n++-1]])}return[F,M]}

Наивная реализация.

Объяснение:

x => {
    F = [n = 1], //female and term number
    M = [0]; //male
    while (n < x) {
        M.push(n - F[M[n - 1]]); //naïve
        F.push(n - M[F[n++ - 1]]); //post-decrement means n++ acts as n in the calculation
    }
    return [F, M];
}

Я думаю, что вы можете сделать это анонимной функцией и заменить && - s на &
Bálint

Вы не можете, &&короткое замыкание, которое желательно, но я все равно удалил его, потому что синтаксис скобки в любом случае одинаково короток
только ASCII

Тогда вы могли бы сделать `F = [n = 1]
Bálint

2

Mathematica, 69 62 байта

Спасибо Sp3000 за предложение функциональной формы, которая сэкономила 14 байтов.

k_~f~0=1-k
k_~f~n_:=n-f[1-k,f[k,n-1]]
Print/@Array[f,{2,#},0]&

Это определяет именованную вспомогательную функцию, fа затем оценивает безымянную функцию, которая решает реальную задачу печати обеих последовательностей.


2

Perl 5,10, 85 байт

Мех, не знаю, если у меня будет больше идей поиграть в гольф ...

@a=1;@b=0;for(1..<>-1){push@a,$_-$b[$a[$_-1]];push@b,$_-$a[$b[$_-1]]}say"@a\n@b"

Попробуйте онлайн!

Я должен был добавить use 5.10.0на Ideone, чтобы он принялsay функцию, но она не байтов.

Это наивная реализация алгоритма, @aбудучи «женским» списком и@b «мужского» списка.

Вычеркнуто 85 все еще 85?


Пояснения, пожалуйста?
clismique

Почти так же, как мой ответ JS
только ASCII

@DerpfacePython На самом деле это наивная реализация. :)
Пол Пикард

Я не проверял, но я не думаю, что вам нужны круглые скобки вокруг каждого pushтермина, ни последняя точка с запятой перед закрывающей скобкой.
msh210

@ msh210 Действительно, забыл об этом. Всего экономит 5 байт, спасибо!
Пол Пикард

2

Java, всего 169 байт

int f(int n,int i){return n>0?n-f(f(n-1,i),-i):i>0?1:0;}void p(int n,int i){if(n>0)p(n-1,i);System.out.print(i==0?"\n":f(n,i)+" ");}void p(int n){p(n,1);p(0,0);p(n,-1);}

F (), M () 56 байт

int f(int n,int i){
    return n>0?n-f(f(n-1,i),-i):i>0?1:0;
}

рекурсивный цикл и печать 77 байт

void p(int n,int i) {
    if(n>0) {
        p(n-1,i);
    }
    System.out.print(i==0?"\n":f(n,i)+" ");
}

вывод списков в две разные строки 37 байт

void p(int n) {
    p(n,1);
    p(0,0);
    p(n,-1);
}

вход: p ( 10)
выход:

1 1 2 2 3 3 4 5 5 6 6 7 8 8 9 9 
0 0 1 2 2 3 4 4 5 6 6 7 7 8 9 9

1

C 166 байт

#define P printf
#define L for(i=0;i<a;i++)
f(x);m(x);i;c(a){L P("%d ",f(i));P("\n");L P("%d ",m(i));}f(x){return x==0?1:x-m(f(x-1));}m(x){return x==0?0:x-f(m(x-1));}

Использование:

main()
{
    c(10);
}

Выход:

1 1 2 2 3 3 4 5 5 6
0 0 1 2 2 3 4 4 5 6

Ungolfed (331 байт)

#include <stdio.h>

int female(int x);
int male(int x);
int i;
int count(a){
    for(i=0;i<a;i++){
        printf("%d ",female(i));
    }
    printf("\n");
    for(i=0;i<a;i++){
        printf("%d ",male(i));
    }
}
int female (int x){
    return x==0?1:x-male(female(x-1));
}
int male(x){
    return x==0?0:x-female(male(x-1));
}
int main()
{
    count(10);
}

0

8-е , 195 байт

Код

defer: M
: F dup not if 1 nip else dup n:1- recurse M n:- then ;
( dup not if 0 nip else dup n:1- recurse F n:- then ) is M
: FM n:1- dup ( F . space ) 0 rot loop cr ( M . space ) 0 rot loop cr ;

использование

ok> 5 FM
1 1 2 2 3 
0 0 1 2 2 

ok> 10 FM
1 1 2 2 3 3 4 5 5 6 
0 0 1 2 2 3 4 4 5 6 

объяснение

Этот код использует рекурсию и отложенное слово

defer: M- Слово Mобъявлено, чтобы быть определенным позже. Это отложенное слово

: F dup not if 1 nip else dup n:1- recurse M n:- then ;- Определить F рекурсивно для создания женских чисел в соответствии с определением. Обратите внимание, что Mеще не определено

( dup not if 0 nip else dup n:1- recurse F n:- then ) is M- Определить M рекурсивно для создания мужских чисел в соответствии с определением

: FM n:1- dup ( F . space ) 0 rot loop cr ( M . space ) 0 rot loop cr ; - Слово используется для печати последовательностей женских и мужских чисел

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.