Générer la séquence de Stöhr


12

J'apprends Ruby et j'ai écrit mon premier code non trivial pour résoudre ce problème.

Le défi consiste à générer les n premiers éléments de la séquence de Stöhr , S , qui est définie comme suit:

S [0] = 1

S [n] est le plus petit nombre qui ne peut pas être exprimé comme la somme de deux éléments précédents distincts dans la séquence.

Ainsi, la séquence commence par 1, 2, 4, 7 et 10. L'élément suivant est 13, car 11 (= 1 + 10) et 12 (= 2 + 10) sont des sommes d'éléments précédents, mais 13 ne l'est pas.

Je recherche le code le plus court. Le mien, dans Ruby, compte 108 caractères, mais j'attendrai peut-être de voir ce que les autres trouveront avant de le publier?


J'aime les réponses jusqu'à présent. Maintenant, il est peut-être trop tard pour revenir en arrière et modifier les exigences, mais je suppose que j'aurais dû mentionner que je suis particulièrement intéressé par les solutions qui utilisent la définition de la séquence elle-même (c'est-à-dire que le code ne sait pas à l'avance que finalement les chiffres augmentent de 3). Donc: des points de bonus moral si vous pouvez le faire.
Théophile

Tel est le problème des séquences mathématiques. Si vous connaissez le schéma, il sera généralement plus court.

Cette séquence est arithmétique sans aucune utilité (?).
user75200

@ user75200 La séquence n'est pas arithmétique, comme vous pouvez le voir sur les différences entre les trois premiers éléments, mais la sous-séquence commençant au troisième élément est en effet arithmétique. Il est utilisé en relation avec le problème du timbre-poste.
Théophile

Réponses:


13

APL, 7

Dans APL, vous pouvez choisir si vous souhaitez travailler avec l'index 0 ou l'index 1. Pour ce faire, définissez la variable globale ⎕IO ← 0

Si nous choisissons de travailler dans l'index 0, nous avons:

+\3⌊1⌈⍳

Explication:

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

Essayez-le sur tryapl.org


Vous ne pouvez pas travailler avec un index basé sur 1, puis créer un tableau de 1 à n et simplement le rajouter avec un autre 1? Si cela peut être fait, est-ce plus court?
Optimizer

Le code auquel je suis arrivé était plus long. C'était mon code pour l'index 1, 10 caractères: + \ 3⌊1, ⍳¯1 + De plus, la version index-0 fonctionne également avec l'argument 0, contrairement à celui-ci.
Moris Zucca

Ah. Ouais . APL a vraiment brillé par ici ..
Optimizer

9

Haskell - 11 21

Séquence infinie paresseuse

1:2:[4,7..]

Fonction qui retourne juste le nombre de membres fourni (soupir)

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

Vous devez prendre une entrée et imprimer uniquement les premiers nchiffres.
Optimizer

4
@Optimizer Eh bien, techniquement , vous devez "générer les n premiers éléments de la séquence de Stöhr" - cela ne veut pas dire que vous ne pouvez pas aussi générer les autres! Cela ne dit pas non plus que vous devez prendre une entrée. Le code original de swish génère en fait les n premiers termes, pour tout n .
wchargin

1
@WChargin essayant d'être trop intelligent n'est pas nouveau. Prendre le libellé de l'OP trop littéralement et produire une sortie supplémentaire par rapport aux exigences est considéré comme une faille standard.
Optimizer

2
@Optimizer En fait, être paresseux signifie qu'aucune sortie supplémentaire ne sera générée jusqu'à ce que vous le demandiez, et vous pouvez demander les termes de votre choix.
swish

1
@swish je ne comprends pas. Qu'est-ce qui est paresseux ici?
Optimizer

7

Python 2, 37 35 octets

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

Utilisation d'un motif ...


1
Vous pouvez inclure le 4dans la gamme:lambda n:[1,2][:n]+range(4,n*3-4,3)
Jakube

Belle trouvaille. Modifié à 35 maintenant.
Logic Knight

6

CJam, 14 octets

1l~{_p_3e<+}*;

Testez-le ici.

Commence à 1. Ensuite, 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.";

Cela se généralise facilement aux séquences h- Stöhr si l'on remplace 3 par 2 h -1 .


6

Brainfuck, 13 caractères

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

Ou 30 caractères si nous voulons le limiter à n sorties:

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

1
Je pense que vous devez imprimer les premiers néléments, pas un flux infini d'entre eux ...
Sp3000

@ Sp3000 L'utilisation des charcodes comme entrée et sortie numériques est-elle généralement acceptée? Impossible de trouver sur méta. Avec cela, il serait assez facile de corriger le code BF.
randomra

Personnellement, je ne sais pas quel est le consensus général à ce sujet, désolé. J'ai aussi eu un petit problème avec ça.
Sp3000

pour les n premiers éléments, je pense que je pourrais faire -> +. <[-> +. <[-> ++. <[-> +++. <]]] (29 caractères), mais ce n'est pas aussi élégant . Et je ne pense pas que le langage soit spécifiquement limité à l'utilisation de codes ASCII pour l'entrée et la sortie.
jgosar

1
Votre code ont pour répondre à la question , même si ce n'est pas élégant. Je suggère de modifier le message et de corriger la réponse ,->+.<[->+.<[->++.<[->+++.<]]]. (Vous avez manqué la virgule de lecture d'entrée au début.)
randomra

4

Python, 136 octets

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

Directement de la définition. Je ne sais pas combien je peux jouer au golf - c'est certainement beaucoup plus long que prévu.


3

J, 14 caractères

Cela code en dur la [1,2, 4+3*k (k=0..n-1) ]séquence et prend la première N.

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

.

J, 18 caractères

Celui-ci utilise une combinaison linéaire de [0,1,2,3...], [1,1,0,0...]et [0,1,1,1...]. Devrait être plus court mais ne semble pas pouvoir jouer au golf.

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

3

Prélude , 32 20

Edit: ... avec deux fois plus de voix maintenant!

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

Cela suppose que l' interpréteur Python avec NUMERIC_OUTPUT = True. Comme la soumission de Brainfuck, cette réponse suppose que l'entrée est donnée sous la forme d'un point de code. C'est en partie pour attirer plus d'attention sur cette méta discussion (et en partie, parce que j'aime Prelude). Donc, si vous voulez imprimer les 32 premiers chiffres, disons, vous devez mettre un espace sur STDIN. Bien sûr, cela signifie qu'il y a une limite supérieure aux entrées valides, mais cette réponse n'est pas gagnante de toute façon, donc je pense que dans les limites de Prelude, c'est très bien.

Explication

Dans Prelude, toutes les lignes sont exécutées en parallèle, cette ligne ayant sa propre pile, initialisée à une quantité infinie de zéros. Il n'y a qu'un seul pointeur d'instruction (pointant vers les colonnes), donc si vous entrez une boucle sur une voix, toutes les autres voix boucleront avec elle.

Dans ce qui suit, j'ai transposé le code, afin de pouvoir annoter des lignes au lieu de colonnes:

?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

En tant que fonction récursive basée sur la définition du problème

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

En utilisant le motif 1,2, 1 + 3 * k: 58

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

Note latérale: trouver la séquence h-Stöhr (vérifier la somme des hnombres au lieu de seulement 2). La Rfonction essaie toutes les sommes possibles d'un nombre donné d'éléments de liste.

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 à peu près équivalent (et compatible 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
}

Testez dans la console FireFox / FireBug. Fonction simple:

S(20)

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

Fonction avancée:

S(10,5)

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


2

> <> (poisson) , 72 65 49 46 caractères

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

L'entrée est fournie à l'interpréteur:

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

Mon premier> <> programme, suggestions appréciées.


Oh super! J'espérais que quelqu'un écrirait un programme> <>.
Théophile

2

> <>, 31 octets

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

Lit dans un seul caractère, utilise son point de code (par exemple espace = 32) et imprime les chiffres un sur chaque ligne.


2

Perl6 22/30

Je vais voir si Perl6 peut déduire la séquence pour moi.

Pour ce faire, j'ai utilisé le REPL intégré à 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, je vois le motif que Perl a déduit. Après 4 pour obtenir la valeur suivante, vous ajoutez simplement 3.

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

Ce qui enregistre un caractère faisant le code pour obtenir une liste infinie des nombres dans la séquence de Stöhr de 13 caractères.

Ce code ne fait que quelque chose d'utile dans le REPL car il imprime l' essentiel du résultat pour nous. Pour le faire imprimer autrement, vous devrez explicitement dire à Perl d'imprimer les résultats.

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

( * + 3est simplement un moyen d'obtenir une référence de code qui renvoie 3 ajoutés à son seul argument. D'autres façons de l'écrire seraient { $_ + 3 }, ou -> $i { $i + 3 }, ou { $^i + 3 }ou sub ($i){ $i + 3 })


Le moyen le plus court de créer quelque chose Callable pour générer les n premiers éléments est d'obtenir une tranche des éléments.

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

Dans un contexte vide qui générerait les premières $_valeurs, puis les jeter rapidement.

Dans tout autre contexte que vide, il crée un bloc de code anonyme (un sous-programme de base sans nom) qui prend un argument.

# 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 vous pensez vraiment qu'il doit avoir un nom pour être considéré comme valide pour ce défi, vous feriez probablement ceci:

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

Bien que depuis ssoit également utilisé pour l'opérateur de substitution, pour appeler cela, les parens ne sont pas facultatifs. (Vous auriez pu lui donner un nom différent je suppose)

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

Sauf indication contraire dans le défi, les soumissions aux défis de golf de code doivent être des programmes ou des fonctions complets , pas seulement des extraits.
Martin Ender

@ MartinBüttner pour être juste 1,2,4,*+3...*crée en fait un objet qui générera les valeurs nécessaires. Je ne pense pas que beaucoup de gens créeraient quelque chose de Callable autour de quelque chose comme ça dans Perl6.
Brad Gilbert b2gills

2

Je vois qu'il y a déjà une réponse java BEAUCOUP meilleure mais j'ai passé un moment là-dessus et je vais la poster. même si ça craint.

Caractère Java 313 (+4 pour l'adapter à l'écran)

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

toujours reconnaissant d'avoir des conseils ou des conseils sur la façon d'améliorer


1

T-SQL 204

Suppose que l'entrée se trouve dans une variable appelée @N. Je peux faire une procédure si vous le souhaitez, mais il n'y a vraiment pas de bon moyen d'obtenir STD_IN en T-SQL.

Aussi, oui pour le bonus 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 @

Agréable! Je ne sais pas grand chose sur SQL - comment @N est-il utilisé ici? Je vois que c'est réglé vers le début, mais alors il ne semble pas être référencé plus tard.
Théophile

Il ressemble @Nau "i" de la "boucle for".
Jacob

Jacob a raison. Le @N est le "i" de la boucle for, qui est une boucle while en SQL. Essentiellement, il joint la table avec lui-même et trouve des paires qui s'ajoutent à @Q. S'il y a au moins deux paires (c'est-à-dire pas seulement un nombre avec lui-même), alors il le saute. Sinon, il l'ajoute à la table. @ est le nom de la table.
bmarks

1

Mathematica, 27 octets

Hmmm, toujours pas de réponse Mathematica? En voici deux:

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

les deux définissent une fonction pure sans nom qui reçoit un entier et renvoie une liste d'entiers. Ceci est basé sur la même relation de récurrence que ma soumission de CJam. Notez que le Arraycode basé sur commence à partir 1/2, car la relation de récurrence est toujours appliquée avant que la valeur ne soit renvoyée.



1

Python - même pas proche (139)

Agissant sous l'hypothèse que cela n'était pas facilement calculable comme d'autres l'ont fait, la solution la plus courte que j'ai trouvée est ci-dessous:

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

Version sans golf:

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

Partagez et profitez.


1

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

Cela utilise la définition de la séquence.

Version plus lisible:

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
}

imprimer q [10]

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


Conseils de golf Ruby: *k=1au lieu de k=[1]. foo while barau lieu de while bar;foo;end. [*s..e]au lieu de (s..e).to_a. .mapau lieu de to_a.map. {|a,b|a+b}au lieu de {|i|i.inject(:+)}.
histocrate

@histocrat Merci, c'est très utile!
Théophile

0

STATA 51

di 1 2 _r(a) 
loc b=3*$a-2
forv x=4(3)`b'{
di `x'
}

0

TI-BASIC, 41 27 30 octets

Pour votre calculatrice

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

0

GML , 67 octets

n=argument0;for(i=1;i<=n;i++){t=i;if i>2t=(i-2)*3+1show_message(t)}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.