Gere a sequência Stöhr


12

Estou aprendendo Ruby e escrevi meu primeiro código não trivial para resolver esse problema.

O desafio é gerar os primeiros n elementos da sequência de Stöhr , S , definida da seguinte forma:

S [0] = 1

S [n] é o menor número que não pode ser expresso como a soma de dois elementos anteriores distintos na sequência.

Assim, a sequência começa com 1, 2, 4, 7 e 10. O próximo elemento é 13, porque 11 (= 1 + 10) e 12 (= 2 + 10) são somas dos elementos anteriores, mas 13 não é.

Estou procurando o código mais curto. O meu, em Ruby, tem 108 caracteres, mas talvez eu espere para ver o que os outros inventam antes de publicá-lo?


Eu gosto das respostas até agora. Agora, talvez seja tarde demais para voltar e alterar os requisitos, mas suponho que deveria ter mencionado que estou particularmente interessado em soluções que usam a definição da própria sequência (ou seja, o código não sabe antecipadamente que, eventualmente, os números aumentam 3). Então: pontos de bônus morais, se você puder fazer isso.
Théophile

Esse é o problema das sequências matemáticas. Se você conhece o padrão, ele geralmente será mais curto.

Essa sequência é aritmética sem nenhum uso (?).
user75200

@ user75200 A sequência não é aritmética, como pode ver nas diferenças nos três primeiros elementos, mas a subsequência que começa no terceiro elemento é de fato aritmética. É usado em conexão com o problema do selo postal.
Théophile

Respostas:


13

APL, 7

No APL, você pode escolher se deseja trabalhar com o índice 0 ou o índice 1. Você faz isso configurando a variável global ⎕IO ← 0

Se optarmos por trabalhar no índice 0, temos:

+\3⌊1⌈⍳

Explicação:

⍳    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)

Experimente em tryapl.org


Você não pode trabalhar com um índice baseado em 1 e, em seguida, criar uma matriz de 1n e simplesmente anexá-la a outra 1? Se isso pode ser feito, é mais curto?
Optimizer

O código que cheguei foi mais longo. Este foi o meu código para o índice 1, 10 caracteres: + \ 3⌊1, ⍳¯1 + Além disso, a versão do índice-0 funciona com o argumento 0 também, enquanto este não.
Moris Zucca

Ah sim . APL realmente brilhou por aqui ..
Optimizer

9

Haskell - 11 21

Sequência infinita preguiçosa

1:2:[4,7..]

Função que retorna apenas o número de membros fornecido (suspiro)

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

Você precisa fazer uma entrada e imprimir apenas os primeiros nnúmeros.
Optimizer

4
@Optimizer Bem, tecnicamente , você precisa "gerar os primeiros n elementos da sequência Stöhr" - isso não significa que você não pode gerar o restante deles também! Também não diz que você deve receber uma entrada. o código original do swish na verdade gera os primeiros n termos, para qualquer n .
wchargin

1
@WChargin tentando ser inteligente demais não é novidade. Tomando o texto do OP muito literalmente e produzindo uma saída extra além do necessário, ambos são considerados brechas padrão.
Optimizer

2
@Optimizer Na verdade, ser preguiçoso significa que nenhuma saída extra será gerada até que você solicite, e você pode solicitar os termos que desejar.
28515

1
@ swish Eu não entendo. O que é preguiçoso aqui?
Optimizer

7

Python 2, 37 35 bytes

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

Fazendo uso de um padrão ...


1
Você pode incluir 4no intervalo:lambda n:[1,2][:n]+range(4,n*3-4,3)
Jakube

Bom achado. Editado para 35 agora.
Logic Knight

6

CJam, 14 bytes

1l~{_p_3e<+}*;

Teste aqui.

Começa em 1. Então, 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.";

Isso generaliza facilmente para seqüências h- Stöhr se substituirmos 3 por 2 h -1 .


6

Brainfuck, 13 caracteres

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

Ou 30 caracteres, se quisermos limitá-lo a n saídas:

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

1
Eu acho que você precisa imprimir os primeiros nelementos, não um fluxo infinito deles ...
Sp3000 26/01/15

@ Sp3000 O uso de códigos como entrada e saída numérica geralmente é aceito? Não foi possível encontrar na meta. Com isso, seria bastante fácil corrigir o código BF.
randomra

Pessoalmente, não tenho certeza de qual é o consenso geral sobre isso, desculpe. Eu também tive um problema com isso.
Sp3000 26/01

para os primeiros n elementos, acho que poderia fazer -> +. <[-> +. <[-> ++. <[-> +++. <]]] (29 caracteres), mas isso não é tão elegante . E eu não acho que o idioma seja especificamente limitado ao uso de códigos ASCII para entrada e saída.
jgosar

1
Seu código precisa responder à pergunta mesmo que não seja tão elegante. Sugiro editar a postagem e corrigir a resposta para ,->+.<[->+.<[->++.<[->+++.<]]]. (Você perdeu a entrada lendo vírgula no começo.)
randomra

4

Python, 136 bytes

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])]

Direto da definição. Não sei ao certo quanto posso jogar golfe - certamente é muito mais longo do que eu esperava.


3

J, 14 caracteres

Isso apenas codifica a [1,2, 4+3*k (k=0..n-1) ]sequência e leva a primeira N.

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

.

J, 18 caracteres

Este usa uma combinação linear de [0,1,2,3...], [1,1,0,0...]e [0,1,1,1...]. Deve ser mais curto, mas parece que não consegue jogar golfe.

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

3

Prelúdio , 32 20

Edit: ... com o dobro das vozes agora!

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

Isso pressupõe o intérprete Python com NUMERIC_OUTPUT = True. Como a submissão de Brainfuck, esta resposta assume que a entrada é fornecida na forma de um ponto de código. Isso é em parte para obter mais atenção para essa meta discussão (e em parte porque eu amo o Prelude). Portanto, se você quiser imprimir os primeiros 32 números, digamos, precisará colocar um espaço em STDIN. Obviamente, isso significa que há um limite superior para as entradas válidas, mas essa resposta não está ganhando de qualquer maneira, então acho que dentro das limitações do Prelude isso está bom.

Explicação

No Prelude, todas as linhas são executadas em paralelo, cuja linha possui sua própria pilha, inicializada com uma quantidade infinita de zeros. Existe apenas um ponteiro de instrução (apontando para as colunas); portanto, se você inserir um loop em uma voz, todas as outras vozes serão repetidas.

A seguir, transpus o código, para que eu possa anotar linhas em vez de colunas:

?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

Como uma função recursiva baseada na definição do problema

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

Usando o padrão 1,2, 1 + 3 * k: 58

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

Nota lateral: localizando a sequência h-Stöhr (verificando a soma de até hnúmeros em vez de apenas 2). A Rfunção tenta todas as somas possíveis de um determinado número de elementos da lista.

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 aproximadamente equivalente (e compatível com 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
}

Teste no console do FireFox / FireBug. Função simples:

S(20)

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

Função avançada:

S(10,5)

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


2

> <> (peixe) , 72 65 49 46 caracteres

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

A entrada é fornecida ao intérprete:

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

Meu primeiro> <> programa, sugestões apreciadas.


Ah que bom! Eu esperava que alguém escrevesse um programa> <>.
Théophile

2

> <>, 31 bytes

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

Lê em um único caractere, usa seu ponto de código (por exemplo, espaço = 32) e imprime os números um em cada linha.


2

Perl6 22/30

Vou ver se o Perl6 pode deduzir a sequência para mim.

Para fazer isso, usei o REPL embutido no 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 ...

Hmm, eu vejo o padrão que Perl deduziu. Após 4 para obter o próximo valor, basta adicionar 3.

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

O que salva um caractere criando o código para obter uma lista infinita dos números na seqüência de 13 caracteres de Stöhr.

Esse código só faz algo útil no REPL, pois imprime a essência do resultado para nós. Para imprimi-lo, você teria que dizer explicitamente ao Perl para imprimir os resultados.

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

( * + 3é simplesmente uma maneira de obter uma referência de código que retorna 3 adicionados ao seu único argumento. Outras maneiras de escrevê-lo seriam { $_ + 3 }, ou -> $i { $i + 3 }, ou { $^i + 3 }ou sub ($i){ $i + 3 })


A maneira mais curta de criar algo Callable para gerar os primeiros n elementos é obter uma fatia dos elementos.

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

Em um contexto vazio que geraria os primeiros $_valores, jogue-os imediatamente fora.

Em qualquer coisa que não seja o contexto nulo, ele cria um bloco de código anônimo (uma sub-rotina básica sem nome) que recebe um argumento.

# 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;

Se você realmente acha que precisa ter um nome para se qualificar como válido para esse desafio, provavelmente faria o seguinte:

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

Embora como stambém seja usado para o operador de substituição, para chamar isso, os parênteses não são opcionais. (Você poderia ter dado um nome diferente, suponho)

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

A menos que especificado de outra forma no desafio, os envios para desafios de golfe com código precisam ser programas ou funções completos , não apenas trechos.
Martin Ender

O @ MartinBüttner, para ser justo, 1,2,4,*+3...*cria um objeto que irá gerar os valores necessários. Eu não acho que muitas pessoas realmente criariam algo Callable em torno de algo assim no Perl6.
precisa saber é o seguinte

2

Vejo que já existe uma resposta Java muito melhor, mas passei um tempo nisso e vou publicá-la. mesmo que seja péssimo.

Caractere Java 313 (+4 para caber na tela)

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

sempre grato por receber dicas ou sugestões sobre como melhorar


1

T-SQL 204

Supõe que a entrada esteja em uma variável chamada @N. Posso fazer um procedimento, se você quiser, mas realmente não há uma boa maneira de obter STD_IN no T-SQL.

Além disso, yay por bônus moral!

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 @

Agradável! Não sei muito sobre SQL - como o @N é usado aqui? Vejo que está definido próximo ao início, mas depois não parece ser mencionado posteriormente.
Théophile

Parece que @Né o "i" do "for loop".
Jacob

Jacob está certo. O @N é o "i" do loop for, que é um loop while no SQL. Essencialmente, ele cruza a tabela e encontra pares que se somam a @Q. Se houver pelo menos dois pares (ou seja, não apenas um número em si), ele será ignorado. Caso contrário, ele será adicionado à tabela. @ é o nome da tabela.
#

1

Mathematica, 27 bytes

Hmmm, ainda não há resposta do Mathematica? Aqui estão dois:

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

ambos definem uma função pura sem nome que recebe um número inteiro e retorna uma lista de números inteiros. Isso se baseia na mesma relação de recorrência que meu envio de CJam. Observe que o Arraycódigo baseado em começa 1/2, porque a relação de recorrência é sempre aplicada antes que o valor seja retornado.



1

Python - nem mesmo perto (139)

Agindo sob a suposição de que isso não era facilmente calculável como outros fizeram, a solução mais curta que encontrei está abaixo:

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]))))

Versão sem golfe:

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

Compartilhe e curta.


1

Ruby - 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}

Isso usa a definição da sequência.

Versão mais legível:

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
}

imprimir q [10]

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


Dicas de golfe em Ruby: em *k=1vez de k=[1]. foo while barem vez de while bar;foo;end. [*s..e]em vez de (s..e).to_a. .mapem vez de to_a.map. {|a,b|a+b}em vez de {|i|i.inject(:+)}.
histocrat

@histocrat Obrigado, isso é muito útil!
Théophile


0

TI-BASIC, 41 27 30 bytes

Para sua calculadora

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

0

GML , 67 bytes

n=argument0;for(i=1;i<=n;i++){t=i;if i>2t=(i-2)*3+1show_message(t)}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.