Generar la secuencia de Stöhr


12

Estoy aprendiendo Ruby y escribí mi primer código no trivial para resolver este problema.

El desafío es generar los primeros n elementos de la secuencia de Stöhr , S , que se define de la siguiente manera:

S [0] = 1

S [n] es el número más pequeño que no se puede expresar como la suma de dos elementos anteriores distintos en la secuencia.

Por lo tanto, la secuencia comienza con 1, 2, 4, 7 y 10. El siguiente elemento es 13, porque 11 (= 1 + 10) y 12 (= 2 + 10) son sumas de elementos anteriores, pero 13 no lo es.

Estoy buscando el código más corto. La mía, en Ruby, tiene 108 caracteres, pero ¿tal vez esperaré para ver qué piensan los demás antes de publicarla?


Me gustan las respuestas hasta ahora. Ahora, tal vez sea demasiado tarde para regresar y cambiar los requisitos, pero supongo que debería haber mencionado que estoy particularmente interesado en soluciones que utilizan la definición de la secuencia en sí (es decir, el código no sabe de antemano que eventualmente los números suben por 3). Entonces: puntos de bonificación moral si puedes hacer eso.
Théophile

Tal es el problema con las secuencias matemáticas. Si conoce el patrón, generalmente será más corto.

Esta secuencia es aritmética sin ningún uso (?).
user75200

@ user75200 La secuencia no es aritmética, como puede ver en las diferencias en los primeros tres elementos, pero la subsecuencia que comienza en el tercer elemento es realmente aritmética. Se utiliza en relación con el problema del sello postal.
Théophile

Respuestas:


13

APL, 7

En APL puede elegir si desea trabajar con el índice 0 o el índice 1. Para ello, configure la variable global ⎕IO ← 0

Si elegimos trabajar en el índice 0 tenemos:

+\3⌊1⌈⍳

Explicación:

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

Pruébalo en tryapl.org


¿No puede trabajar con un índice basado en 1 y luego crear una matriz de 1 a n y simplemente anteponerlo con otro 1? Si eso se puede hacer, ¿es más corto?
Optimizador

El código al que llegué fue más largo. Este fue mi código para el índice 1, 10 caracteres: + \ 3⌊1, ⍳¯1 + Además, la versión index-0 también funciona con el argumento 0, mientras que este no.
Moris Zucca

Ah Si . APL realmente brilló por aquí ...
Optimizer

9

Haskell - 11 21

Secuencia infinita perezosa

1:2:[4,7..]

Función que devuelve el número de miembros recién suministrado (suspiro)

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

Usted tiene que tomar una entrada y imprimir sólo los primeros nnúmeros.
Optimizador

44
@Optimizer Bueno, técnicamente , que tiene a "generar los primeros n elementos de la secuencia Stöhr" -no dice que no se puede generar el resto de ellos también! Tampoco dice que tenga que tomar una entrada. El código original de swish en realidad genera los primeros n términos, para cualquier n .
wchargin

1
@WChargin tratando de ser demasiado inteligente no es nuevo. Tomar la redacción del OP demasiado literalmente y producir una salida adicional de la requerida, ambas se consideran lagunas estándar.
Optimizador

2
@Optimizer En realidad, ser perezoso significa que no se generará ningún resultado adicional hasta que lo solicite, y puede solicitar los términos que desee.
swish

1
@swish no entiendo. ¿Qué es perezoso aquí?
Optimizador

7

Python 2, 37 35 bytes

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

Haciendo uso de un patrón ...


1
Puede incluir el 4en el rango:lambda n:[1,2][:n]+range(4,n*3-4,3)
Jakube

Buen hallazgo Editado a 35 ahora.
Logic Knight el

6

CJam, 14 bytes

1l~{_p_3e<+}*;

Pruébalo aquí.

Comienza en 1. Luego, 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.";

Esto se generaliza fácilmente a las secuencias h -Stöhr si reemplazamos 3 por 2 h -1 .


6

Brainfuck, 13 caracteres

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

O 30 caracteres si queremos limitarlo a n salidas:

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

1
Creo que necesita imprimir los primeros nelementos, no una secuencia infinita de ellos ...
Sp3000

@ Sp3000 ¿Se acepta generalmente el uso de códigos de acceso como entrada y salida numérica? No se puede encontrar en meta. Con eso sería bastante fácil corregir el código BF.
randomra

Personalmente, no estoy seguro de cuál es el consenso general para esto, lo siento. También tuve un pequeño problema con esto.
Sp3000

para los primeros n elementos, creo que podría hacer -> +. <[-> +. <[-> ++. <[-> +++. <]]] (29 caracteres), pero eso no es tan elegante . Y no creo que el lenguaje se limite específicamente al uso de códigos ASCII para entrada y salida.
jgosar

1
Su código tiene que responder la pregunta incluso si no es tan elegante. Sugeriría editar la publicación y corregir la respuesta a ,->+.<[->+.<[->++.<[->+++.<]]]. (Te perdiste la coma de lectura de entrada al principio.)
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])]

Directamente de la definición. No estoy seguro de cuánto puedo jugar golf, ciertamente es mucho más tiempo de lo que esperaba.


3

J, 14 caracteres

Esto simplemente codifica la [1,2, 4+3*k (k=0..n-1) ]secuencia y toma la primera N.

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

.

J, 18 caracteres

Éste usa una combinación lineal de [0,1,2,3...], [1,1,0,0...]y [0,1,1,1...]. Debería ser más corto pero parece que no puede jugar golf.

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

3

Preludio , 32 20

Editar: ... con el doble de voces ahora!

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

Esto supone el intérprete de Python con NUMERIC_OUTPUT = True. Al igual que la presentación Brainfuck, esta respuesta supone que la entrada se proporciona en forma de un punto de código. Esto es en parte para obtener más atención para esta meta discusión (y en parte, porque me encanta Prelude). Entonces, si desea imprimir los primeros 32 números, por ejemplo, debe poner un espacio en STDIN. Por supuesto, esto significa que hay un límite superior para las entradas válidas, pero esta respuesta no está ganando de todos modos, así que creo que dentro de las limitaciones de Prelude esto está bien.

Explicación

En Prelude, todas las líneas se ejecutan en paralelo, línea que tiene su propia pila, inicializada en una cantidad infinita de ceros. Solo hay un puntero de instrucción único (apuntando a las columnas), por lo que si ingresa un bucle en una voz, todas las demás voces se repetirán junto con él.

A continuación, he transpuesto el código para poder anotar líneas en lugar de columnas:

?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 una función recursiva basada en la definición del 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 el patrón 1,2, 1 + 3 * k: 58

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

Nota al margen: encontrar la secuencia h-Stöhr (verificar la suma de hasta hnúmeros en lugar de solo 2). La Rfunción intenta todas las sumas posibles de un número dado de elementos de la 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 más o menos equivalente (y compatible con 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
}

Prueba en la consola FireFox / FireBug. Función simple:

S(20)

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

Función avanzada:

S(10,5)

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


2

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

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

Se proporciona entrada al intérprete:

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

Mi primer programa> <>, sugerencias apreciadas.


¡Oh Dios! Esperaba que alguien escribiera un programa> <>.
Théophile

2

> <>, 31 bytes

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

Lee en un solo carácter, usa su punto de código (por ejemplo, espacio = 32) e imprime los números uno en cada línea.


2

Perl6 22/30

Voy a ver si Perl6 puede deducir la secuencia por mí.

Para hacer eso utilicé el REPL integrado en 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, veo el patrón que dedujo Perl. Después de 4 para obtener el siguiente valor, solo agrega 3.

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

Lo que ahorra un carácter haciendo que el código obtenga una lista infinita de los números en la secuencia Stöhr de 13 caracteres de longitud.

Este código solo hace algo útil en REPL ya que imprime la esencia del resultado para nosotros. Para que se imprima, de lo contrario, deberá indicarle explícitamente a Perl que imprima los resultados.

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

( * + 3es simplemente una forma de obtener una referencia de código que devuelve 3 agregados a su único argumento. Otras formas de escribirlo serían { $_ + 3 }, o -> $i { $i + 3 }, o { $^i + 3 }o sub ($i){ $i + 3 })


La forma más corta de crear algo invocable para generar los primeros n elementos es obtener una porción de los elementos.

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

En un contexto vacío que generaría los primeros $_valores, los tiraría rápidamente

En cualquier otra cosa que no sea el contexto vacío, crea un bloque de código anónimo (una subrutina básica sin nombre) que toma un 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;

Si realmente crees que tiene que tener un nombre para calificar como válido para este desafío, probablemente harías esto:

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

Aunque desde stambién se usa para el operador de sustitución, para llamar a esto, los parens no son opcionales. (Podría haberle dado un nombre diferente, supongo)

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

A menos que se especifique lo contrario en el desafío, los envíos a los desafíos de código de golf deben ser programas o funciones completos , no solo fragmentos.
Martin Ender

@ MartinBüttner para ser justos en 1,2,4,*+3...*realidad crea un objeto que generará los valores necesarios. No creo que muchas personas realmente creen algo invocable alrededor de algo así en Perl6.
Brad Gilbert b2gills

2

Veo que ya hay una respuesta Java MUCHO mejor, pero pasé un tiempo en esto y voy a publicarlo. incluso si apesta.

Java 313 char (+4 para ajustarlo en la pantalla)

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

siempre agradecido de recibir consejos o sugerencias sobre cómo mejorar


1

T-SQL 204

Asume que la entrada está en una variable llamada @N. Puedo hacer un procedimiento si lo desea, pero realmente no hay una buena manera de obtener STD_IN en T-SQL.

Además, ¡sí por bonificación 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 @

¡Agradable! No sé mucho sobre SQL, ¿cómo se usa @N ​​aquí? Veo que se establece cerca del principio, pero luego no parece que se haga referencia más adelante.
Théophile

Parece que @Nes la "i" del "bucle for".
Jacob

Jacob tiene razón. La @N es la "i" del bucle for, que es un bucle while en SQL. Básicamente, se une de forma cruzada a la tabla y encuentra pares que se suman a @Q. Si hay al menos dos pares (es decir, no solo un número consigo mismo), entonces lo omite. De lo contrario, lo agrega a la tabla. @ es el nombre de la tabla.
comenta

1

Mathematica, 27 bytes

Hmmm, todavía no hay respuesta de Mathematica? Aquí hay dos:

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

ambos definen una función pura sin nombre que recibe un entero y devuelve una lista de enteros. Esto se basa en la misma relación de recurrencia que mi envío de CJam. Tenga en cuenta que el Arraycódigo basado comienza desde 1/2, porque la relación de recurrencia siempre se aplica antes de que se devuelva el valor.



1

Python: ni siquiera cerca (139)

Actuando bajo el supuesto de que esto no era fácilmente calculable como lo han hecho otros, la solución más corta que he encontrado es la siguiente:

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

Versión sin golf:

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

Comparte y Disfruta.


1

Rubí - 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}

Esto usa la definición de la secuencia.

Versión más legible:

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]


Consejos de golf Ruby: en *k=1lugar de k=[1]. foo while baren lugar de while bar;foo;end. [*s..e]en lugar de (s..e).to_a. .mapen lugar de to_a.map. {|a,b|a+b}en lugar de {|i|i.inject(:+)}.
histocrat

@histocrat Gracias, eso es muy útil!
Théophile


0

TI-BASIC, 41 27 30 bytes

Para su 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)}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.