Генерация последовательности Штера


12

Я изучаю Ruby и написал свой первый нетривиальный код для решения этой проблемы.

Задача состоит в том, чтобы генерировать первые п элементов последовательности Stöhr , S , которая определяется следующим образом :

S [0] = 1

S [n] - наименьшее число, которое не может быть выражено как сумма двух различных предыдущих элементов в последовательности.

Таким образом, последовательность начинается с 1, 2, 4, 7 и 10. Следующим элементом является 13, потому что 11 (= 1 + 10) и 12 (= 2 + 10) являются суммами предыдущих элементов, а 13 - нет.

Я ищу самый короткий код. Мой собственный, в Ruby, имеет длину 108 символов, но, может быть, я подожду, чтобы посмотреть, что придут другие, прежде чем публиковать его?


Мне нравятся ответы до сих пор. Сейчас, возможно, уже слишком поздно возвращаться и изменять требования, но я полагаю, я должен был упомянуть, что мне особенно интересны решения, использующие определение самой последовательности (т. Е. Код не знает заранее, что в конечном итоге цифры увеличиваются на 3). Итак: моральные бонусы, если вы можете это сделать.
Теофил

Такова проблема с математическими последовательностями. Если вы знаете шаблон, он обычно будет короче.

Эта последовательность арифметическая без использования (?).
user75200

@ user75200 Последовательность не арифметическая, как вы можете видеть из различий в первых трех элементах, но подпоследовательность, начинающаяся с третьего элемента, действительно арифметическая. Он используется в связи с проблемой почтовой марки.
Теофил

Ответы:


13

APL, 7

В APL вы можете выбрать, хотите ли вы работать с индексом 0 или индексом 1. Вы делаете это, устанавливая глобальную переменную ⎕IO ← 0

Если мы решим работать с индексом 0, мы имеем:

+\3⌊1⌈⍳

Объяснение:

⍳    creates a sequence 0...n   (0 1 2 3 4 5)
1⌈   takes whichever is bigger, number in sequence or 1 (1 1 2 3 4 5)
3⌊   takes whichever is lower, number in sequence or 3 (1 1 2 3 3 3)
+\   partial sums for the sequence (1 2 4 7 10 13)

Попробуйте это на tryapl.org


Разве вы не можете работать с индексом на основе 1, а затем создать массив от 1 до n и просто добавить его к другому 1? Если это можно сделать, это короче?
Оптимизатор

Код, который я получил, был длиннее. Это был мой код для индекса 1, 10 символов: + \ 3⌊1, 1¯1 + Кроме того, версия index-0 тоже работает с аргументом 0, а эта - нет.
Морис Зукка

Ах. Да . APL действительно просвечивает здесь ..
Оптимизатор

9

Haskell - 11 21

Ленивая бесконечная последовательность

1:2:[4,7..]

Функция, которая возвращает только что предоставленное количество членов (вздох)

flip take$1:2:[4,7..]

Вы должны принять данные и распечатать только первые nцифры.
Оптимизатор

4
@Optimizer Ну, технически вы должны «сгенерировать первые n элементов последовательности Штера» - это не значит, что вы не можете сгенерировать и остальные из них! Это не говорит о том, что вы должны принять участие, либо. Оригинальный код swish действительно генерирует первые n терминов для любого n .
wchargin

1
@WChargin пытается быть умнее, не нова. Слишком буквальное восприятие формулировок ОП и создание дополнительных выходных данных, чем требуется, рассматриваются как стандартные лазейки.
Оптимизатор

2
@Optimizer На самом деле, ленивость означает, что никакой дополнительной информации не будет сгенерировано, пока вы не попросите об этом, и вы можете запросить любые термины, которые захотите.
взмах

1
@ я не понимаю. Что здесь ленивого?
Оптимизатор

7

Python 2, 37 35 байт

lambda n:[1,2][:n]+range(4,n*3-4,3)

Используя шаблон ...


1
Вы можете включить 4в диапазон:lambda n:[1,2][:n]+range(4,n*3-4,3)
Jakube

Хорошая находка. Отредактировано до 35 сейчас.
Логика Найт

6

CJam, 14 байтов

1l~{_p_3e<+}*;

Проверьте это здесь.

Начинается с 1. Затем S [n] = S [n-1] + min (S [n-1], 3) .

1l~{_p_3e<+}*;
1              "Push 1.";
 l~            "Read and evaluate input N.";
   {       }*  "Repeat this block N times.":
    _p         "Duplicate the last number and print it.";
      _3e<     "Duplicate it again, and take minimum with 3.";
          +    "Add to last number.";
             ; "Discard final number to prevent output.";

Это легко обобщает последовательности h- Stöhr, если заменить 3 на 2 h -1 .


6

Brainfuck, 13 символов

+.+.++.[+++.]

Или 30 символов, если мы хотим ограничить его выводами:

,->+.<[->+.<[->++.<[->+++.<]]]

1
Я думаю, вам нужно напечатать первые nэлементы, а не их бесконечный поток ...
Sp3000

@ Sp3000 Является ли использование кодов в качестве числового ввода и вывода общепринятым? Не могу найти на мета. При этом было бы довольно легко исправить код BF.
Рандора

Лично я не уверен, каково общее согласие для этого, извините. У меня тоже была небольшая проблема с этим.
Sp3000

для первых n элементов, я думаю, я мог бы сделать -> +. <[-> +. <[-> ++. <[-> +++. <]]] (29 символов), но это не так элегантно , И я не думаю, что язык специально ограничен использованием кодов ASCII для ввода и вывода.
jgosar

1
Ваш код должен ответить на вопрос, даже если он не такой элегантный. Я бы предложил отредактировать пост и исправить ответ на ,->+.<[->+.<[->++.<[->+++.<]]]. (Вы пропустили ввод запятой чтения в начале.)
randomra

4

Python, 136 байт

def f(n):
 if n<1:return[1]
 x=f(n-1);y=set(x)|{a+b for a in x for b in x if a!=b};return x+[min([a for a in range(1,max(y)+2)if{a}-y])]

Прямо из определения. Я не уверен, насколько я могу играть в гольф - это, конечно, намного дольше, чем я ожидал.


3

J, 14 символов

Это просто жестко кодирует [1,2, 4+3*k (k=0..n-1) ]последовательность и занимает первое место N.

   ({.1,2,4+3*i.) 10
1 2 4 7 10 13 16 19 22 25

,

J, 18 символов

Это один использует линейную комбинацию [0,1,2,3...], [1,1,0,0...]и [0,1,1,1...]. Должен быть короче, но не может играть в гольф.

   ((3&*+<&2-2**)@i.) 10
1 2 4 7 10 13 16 19 22 25

3

Прелюдия , 32 20

Редактировать: ... теперь вдвое больше голосов!

?(1-)
4 +3
2  ^
1 !^

Предполагается, что интерпретатор Python с NUMERIC_OUTPUT = True. Как и в представлении Brainfuck, этот ответ предполагает, что ввод дается в виде кодовой точки. Это частично, чтобы привлечь больше внимания к этой мета-дискуссии (и частично, потому что я люблю Prelude). Так что если вы хотите напечатать первые 32 числа, скажем, вам нужно поставить пробел на STDIN. Конечно, это означает, что есть верхний предел для допустимых входных данных, но этот ответ все равно не выигрывает, поэтому я думаю, что в рамках ограничений Prelude это нормально.

объяснение

В Prelude все строки выполняются параллельно, причем эта строка, имеющая собственный стек, инициализируется бесконечным количеством нулей. Существует только один указатель команды (указывающий на столбцы), поэтому, если вы введете цикл для одного голоса, все остальные голоса будут зацикливаться вместе с ним.

Далее я перенесу код, чтобы можно было комментировать строки вместо столбцов:

?421  Read a character into the first stack. Push 4, 2, 1 onto the other stacks, respectively.
      Generally, the fourth stack will hold the next number to be printed, the third stack the
      one after that, and the second stack the number two steps ahead.
(     Start a loop if the input wasn't 0.
1+ !  Push a 1 onto the first stack. Add the top elements in the second stack. On the first
      iteration this will be 0 and 4, so it does nothing. On all further iterations
      this will increment the last number by 3.
-3^^  Subtract one from the first stack. Push a 3 onto the second stack for the next iteration.
      Copy the last value from the second to the third, and the third to the fourth stack.
)     If the top of the first stack is not 0, jump back to the column after the (.

2

JavaScript (ES6) 92

Как рекурсивная функция, основанная на определении проблемы

S=(n,v=1,s=[],r=0)=>[for(a of s)for(b of s)r+=(a-b&&a+b==v)]|r||(s.push(v),--n)?S(n,v+1,s):s

Используя шаблон 1,2, 1 + 3 * k: 58

S=(n)=>(i=>{for(t=1;n>r.push(t+=i);i+=(i<3));})(0,r=[])||r

Примечание: поиск последовательности h-Stöhr (проверка суммы до hчисел вместо 2). RФункция пытается все possibile суммы выше заданного числа элементов списка.

S=(n,h=2,s=[],v=1,R=(t,v,l,i=0,r=t,w)=>{
  for(;r&&l&&v[i];i++)
    w=[...v],r=!R(t-w.splice(i,1),w,l-1)
  return!r;
})=>R(v,s,h)||(s.push(v),--n)?S(n,h,s,v+1):s

Ungolfed примерно эквивалентно (и ES5-совместимый)

function S(n, v, s)
{
  var r=0,a,b
  v = v||1
  s = s||[]
  for(a of s)
    for(b of s)
    {
      if (a != b && a+b == v) 
        r++;
    }
  if (r == 0) 
  {
    s.push(v);
    --n;
  }
  if (n != 0)
     return S(n,v+1,s)
  else
     return s
}

Проверьте в консоли FireFox / FireBug. Простая функция:

S(20)

[1, 2, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55]

Расширенная функция:

S(10,5)

[1, 2, 4, 8, 16, 32, 63, 94, 125, 156]


2

> <> (рыба) , 72 65 49 46 символов

1n1-:?!;' 'o2n1-v
v1&no' ':<4&;!?:<
>-:?!;&3+^

Ввод поступает переводчику:

>fish.py stohr.fish -v 10
1 2 4 7 10 13 16 19 22 25

Моя первая> <> программа, предложения приветствуются.


О, хорошо! Я надеялся, что кто-то напишет>> программу.
Теофил

2

> <>, 31 байт

4i1nao:?!;2nao1-:?!;$:nao3+$d0.

Читает один символ, использует его кодовую точку (например, пробел = 32) и печатает числа по одному в каждой строке.


2

Perl6 22/30

Я собираюсь посмотреть, сможет ли Perl6 определить последовательность для меня.

Для этого я использовал REPL, встроенный в Perl6

$ perl6
> 1,2,4,7...*
Unable to deduce arithmetic or geometric sequence from 2,4,7 (or did you really mean '..'?)
> 1,2,4,7,10...*
1 2 4 7 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 61 64 67 70 ...

Хм, я вижу образец, который вывел Perl. После 4, чтобы получить следующее значение, вы просто добавляете 3.

1,2,4,*+3...*

Который сохраняет один символ, создавая код, чтобы получить бесконечный список чисел в последовательности Штера длиной 13 символов.

Этот код только делает что-то полезное в REPL, так как он выводит суть результата для нас. Чтобы заставить его печатать иначе, вы должны явно указать Perl распечатать результаты.

$ perl6 -e 'say 1,2,4,*+3...*'

( * + 3это просто способ получить ссылку на код, который возвращает 3, добавленный к его единственному аргументу. Другие способы записать это будут { $_ + 3 }или -> $i { $i + 3 }, или, или, { $^i + 3 }или sub ($i){ $i + 3 })


Кратчайший способ создать что-то Callable для генерации первых n элементов - это получить часть элементов.

{(1,2,4,*+3...*)[^$_]} # 22

В пустом контексте, который будет генерировать первые $_значения, а затем быстро выбрасывать их.

В любом другом месте, кроме пустого контекста, он создает блок анонимного кода (базовая подпрограмма без имени), который принимает один аргумент.

# store it in a scalar variable
my $sub = {(1,2,4,*+3...*)[^$_]};
say $sub.(5);
# 1 2 4 7 10

# use it immediately
say {(1,2,4,*+3...*)[^$_]}.(5);
# 1 2 4 7 10

# pretend it always had a name
my &Stöhr-first = {(1,2,4,*+3...*)[^$_]};
say Stöhr-first 5;

Если вы действительно думаете, что у него должно быть имя, которое может считаться действительным для этой задачи, вы, вероятно, сделаете это:

sub s(\n){(1,2,4,*+3...*)[^n]} # 30

Хотя, так sкак также используется для оператора подстановки, вызывать это не обязательно. (Вы могли бы дать ему другое имя, я полагаю)

say s(5);
# 1 2 4 7 10

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

@ MartinBüttner, чтобы быть справедливым, на 1,2,4,*+3...*самом деле создает объект, который будет генерировать необходимые значения. Я не думаю, что многие люди на самом деле создают что-то вызываемое в Perl6.
Брэд Гилберт b2gills

2

Я вижу, что уже есть гораздо лучший ответ на Java, но я потратил некоторое время на это, и я собираюсь опубликовать его. даже если это отстой.

Java 313 char (+4 для размещения на экране)

import java.util.*;public class S{public static void main(String[] a){
Set<Integer> S=new HashSet<Integer>();S.add(1);int i=1,k=0;
while(S.size()<=new Integer(a[0])){if(S.contains(i)){}else{k=0;for(int j:S){
for(int l:S){if(l!=j){if((j+l)==i)k=1;}}}if(k==0)S.add(i);}i++;}for(int x:S)
{System.out.println(x);}}}

всегда благодарен за любые советы или рекомендации по улучшению


1

T-SQL 204

Предполагается, что входные данные находятся в переменной с именем @N. Я могу сделать процедуру, если хотите, но на самом деле нет хорошего способа получить STD_IN в T-SQL.

Кроме того, ура за моральный бонус!

DECLARE @Q INT=0,@B INT=2
DECLARE @ TABLE(A INT)WHILE @N>0
BEGIN
SET @N-=1
WHILE @B>1
BEGIN
SET @Q+=1
SELECT @B=COUNT(*)FROM @ C,@ B WHERE C.A+B.A=@Q
END
INSERT INTO @ VALUES(@Q)SET @B=2
END
SELECT*FROM @

Ницца! Я не очень разбираюсь в SQL - как здесь используется @N? Я вижу, что он установлен в начале, но потом, кажется, на него не ссылаются позже.
Теофил

Похоже, @Nэто «я» из «для цикла».
Джейкоб

Джейкоб прав. @N - это «i» цикла for, который является циклом while в SQL. По сути, он перекрестно соединяет таблицу с собой и находит пары, которые добавляют к @Q. Если есть хотя бы две пары (то есть не просто число с самим собой), то оно пропускается. В противном случае он добавляет его в таблицу. @ - это имя таблицы.
отмечает

1

Mathematica, 27 байт

Хм, все еще нет ответа Mathematica? Вот два:

NestList[#+3~Min~#&,1,#-1]&
Array[i=1/2;i+=3~Min~i&,#]&

оба определяют безымянную чистую функцию, которая получает целое число и возвращает список целых чисел. Это основано на том же отношении повторения, что и мое представление CJam. Обратите внимание, что Arrayкод на основе начинается с 1/2, потому что рекуррентное отношение всегда применяется перед возвращением значения.



1

Python - даже не близко (139)

Исходя из предположения, что это не так легко вычислить, как это сделали другие, самое короткое решение, которое я нашел, приведено ниже:

from itertools import combinations as C
x,i,n=[],1,input()
while len(x)<=n:
 if i not in [sum(y) for y in C(x,2)]:x.append(i)
 i+=1
print n

1

Clojure - 130 118

(defn s[n](last(take n(iterate #(if(<(count %)3)(conj %(+ (apply + %)1))(conj %(+(last %)(second %)(first %))))[1]))))

Версия без гольфа:

(defn stohr [n]
  (last
    (take n
      (iterate #(if (< (count %) 3)
                   (conj % (+ (apply + %) 1))
                   (conj % (+ (last %) (second %) (first %)))) [1]))))

Поделитесь и наслаждайтесь.


1

Рубин - 108 88

q=->n{*k=1;(m=k[-1];k<<([*m+1..2*m]-k.combination(2).map{|i,j|i+j})[0])while k.size<n;k}

Это использует определение последовательности.

Более читаемая версия:

q=->n{
    *k=1
    (
        m = k[-1]
        k << ([*m+1..2*m] - k.combination(2).map{|i,j|i+j})[0]
    ) while k.size < n
    k
}

печать q [10]

[1, 2, 4, 7, 10, 13, 16, 19, 22, 25]


Рубиновые советы по гольфу: *k=1вместо k=[1]. foo while barвместо while bar;foo;end. [*s..e]вместо (s..e).to_a. .mapвместо to_a.map. {|a,b|a+b}вместо {|i|i.inject(:+)}.
гистократ

@histocrat Спасибо, это очень полезно!
Теофил


0

TI-BASIC, 41 27 30 байтов

Для вашего калькулятора

Input N:For(I,1,N:I:If I>2:(I-2)3+1:Disp Ans:End

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