Genera la sequenza Stöhr


12

Sto imparando Ruby e ho scritto il mio primo codice non banale per risolvere questo problema.

La sfida è generare i primi n elementi della sequenza di Stöhr , S , che è definita come segue:

S [0] = 1

S [n] è il numero più piccolo che non può essere espresso come la somma di due distinti elementi precedenti nella sequenza.

Quindi la sequenza inizia con 1, 2, 4, 7 e 10. L'elemento successivo è 13, perché 11 (= 1 + 10) e 12 (= 2 + 10) sono somme di elementi precedenti, ma 13 non lo è.

Sto cercando il codice più breve. Il mio, in Ruby, è lungo 108 caratteri, ma forse aspetterò di vedere cosa ne pensano gli altri prima di pubblicarlo?


Mi piacciono le risposte finora. Ora, forse è troppo tardi per tornare indietro e cambiare i requisiti, ma suppongo che avrei dovuto menzionare che sono particolarmente interessato alle soluzioni che usano la definizione della sequenza stessa (cioè, il codice non sa in anticipo che alla fine i numeri aumentano di 3). Quindi: punti bonus morali se puoi farlo.
Théophile il

Questo è il problema con le sequenze matematiche. Se conosci lo schema, di solito sarà più breve.

Questa sequenza è aritmetica senza alcun uso (?).
user75200

@ user75200 La sequenza non è aritmetica, come si può vedere dalle differenze nei primi tre elementi, ma la sottosequenza che inizia dal terzo elemento è effettivamente aritmetica. Viene utilizzato in relazione al problema del francobollo.
Théophile il

Risposte:


13

APL, 7

In APL puoi scegliere se vuoi lavorare con l'indice 0 o l'indice 1. Puoi farlo impostando la variabile globale ⎕IO ← 0

Se scegliamo di lavorare nell'indice 0 abbiamo:

+\3⌊1⌈⍳

Spiegazione:

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

Provalo su tryapl.org


Non puoi lavorare con un indice basato su 1 e quindi creare un array da 1 a n e semplicemente anteporre ad un altro 1? Se ciò può essere fatto, è più breve?
Ottimizzatore

Il codice che ho avuto è stato più lungo. Questo era il mio codice per l'indice 1, 10 caratteri: + \ 3⌊1, ⍳¯1 + Inoltre, la versione index-0 funziona anche con l'argomento 0, mentre questo no.
Moris Zucca,

Ah. si . APL ha davvero brillato qui ..
Ottimizzatore

9

Haskell - 11 21

Sequenza infinita pigra

1:2:[4,7..]

Funzione che restituisce solo il numero fornito di membri (sospiro)

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

È necessario prendere un ingresso e stampare solo i primi nnumeri.
Ottimizzatore il

4
@Optimizer Beh, tecnicamente , si deve a "generare i primi n elementi della sequenza Stöhr" -non dico che non è possibile generare il resto di loro, come pure! Non dice nemmeno che devi prendere un input. il codice originale di swish in realtà genera i primi n termini, per qualsiasi n .
mercoledì

1
@WChargin che prova ad essere troppo intelligente non è una novità. Considerare la formulazione del PO in modo troppo letterale e produrre un output extra del necessario, entrambi sono considerati scappatoie standard.
Ottimizzatore il

2
@Optimizer In realtà, essere pigri significa che non verrà generato alcun output aggiuntivo fino a quando non lo chiedi e puoi chiedere tutti i termini che desideri.
Swish,

1
@swish non capisco. Cosa è pigro qui?
Ottimizzatore il

7

Python 2, 37 35 byte

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

Facendo uso di un modello ...


1
Puoi includere 4nella gamma:lambda n:[1,2][:n]+range(4,n*3-4,3)
Jakube,

Bella scoperta. Modificato a 35 ora.
Logic Knight,

6

CJam, 14 byte

1l~{_p_3e<+}*;

Provalo qui.

Inizia da 1. Quindi, 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.";

Questo si generalizza facilmente alle sequenze h -Stöhr se sostituiamo 3 con 2 h -1 .


6

Brainfuck, 13 caratteri

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

O 30 caratteri se vogliamo limitarlo a n output:

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

1
Penso che sia necessario stampare i primi nelementi, non un flusso infinito di essi ...
Sp3000,

@ Sp3000 L'utilizzo di charcodes come input e output numerici è generalmente accettato? Impossibile trovare su meta. Con ciò sarebbe abbastanza facile correggere il codice BF.
randomra,

Personalmente non sono sicuro di quale sia il consenso generale per questo, mi dispiace. Ho avuto un po 'di problemi anche con questo.
Sp3000,

per i primi n elementi, penso di poter fare -> +. <[-> +. <[-> ++. <[-> +++. <]]] (29 caratteri), ma non è così elegante . E non credo che il linguaggio sia specificamente limitato all'uso di codici ASCII per input e output.
jgosar,

1
Il tuo codice deve rispondere alla domanda anche se non è così elegante. Vorrei suggerire di modificare il post e correggere la risposta a ,->+.<[->+.<[->++.<[->+++.<]]]. (Hai perso l'inserimento della virgola all'inizio.)
randomra,

4

Python, 136 byte

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

Direttamente dalla definizione. Non sono sicuro di quanto posso giocare a golf - è sicuramente molto più lungo di quanto mi aspettassi.


3

J, 14 caratteri

Questo semplicemente codifica la [1,2, 4+3*k (k=0..n-1) ]sequenza e prende il primo N.

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

.

J, 18 caratteri

Questo si usa una combinazione lineare di [0,1,2,3...], [1,1,0,0...]e [0,1,1,1...]. Dovrebbe essere più corto ma non riesco a giocare a golf.

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

3

Preludio , 32 20

Modifica: ... con il doppio delle voci ora!

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

Questo presuppone l' interprete Python con NUMERIC_OUTPUT = True. Come l'invio di Brainfuck, questa risposta presuppone che l'input sia dato sotto forma di un punto di codice. Questo è in parte per attirare maggiormente l'attenzione su questa meta discussione (e in parte perché amo Prelude). Quindi, se vuoi stampare i primi 32 numeri, diciamo, devi mettere uno spazio su STDIN. Ovviamente, questo significa che c'è un limite massimo per gli input validi, ma questa risposta non sta vincendo comunque, quindi penso che entro i limiti di Prelude questo vada bene.

Spiegazione

In Preludio, tutte le linee vengono eseguite in parallelo, la cui linea ha il proprio stack, inizializzata su una quantità infinita di zero. C'è solo un singolo puntatore di istruzione (che punta alle colonne), quindi se si inserisce un loop su una voce, tutte le altre voci si collegheranno con esso.

Di seguito ho trasposto il codice, in modo da poter annotare le righe anziché le colonne:

?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

Come funzione ricorsiva basata sulla definizione 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 il motivo 1,2, 1 + 3 * k: 58

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

Nota a margine: trovare la sequenza h-Stöhr (verificando la somma di fino a hnumeri anziché solo 2). La Rfunzione cerca tutte le possibili somme di un determinato numero di elementi dell'elenco.

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 approssimativamente equivalente (e compatibile 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
}

Test nella console FireFox / FireBug. Funzione semplice:

S(20)

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

Funzione avanzata:

S(10,5)

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


2

> <> (pesce) , 72 65 49 46 caratteri

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

L'input viene fornito all'interprete:

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

Il mio primo programma> <>, suggerimenti apprezzati.


Oh bene! Speravo che qualcuno avrebbe scritto un programma> <>.
Théophile il

2

> <>, 31 byte

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

Legge in un singolo carattere, usa il suo punto di codice (es. Spazio = 32) e stampa i numeri uno su ogni riga.


2

Perl6 22/30

Vedrò se Perl6 può dedurre la sequenza per me.

Per fare ciò ho usato il REPL integrato in 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 ...

Vedo il modello dedotto da Perl. Dopo 4 per ottenere il valore successivo basta aggiungere 3.

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

Ciò consente di salvare un carattere creando il codice per ottenere un elenco infinito di numeri nella sequenza Stöhr lunga 13 caratteri.

Questo codice fa solo qualcosa di utile nel REPL poiché stampa l' essenza del risultato per noi. Per farlo stampare altrimenti dovresti dire esplicitamente a Perl di stampare i risultati.

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

( * + 3è semplicemente un modo per ottenere un riferimento al codice che restituisce 3 aggiunto al suo unico argomento. Altri modi per scrivere sarebbe { $_ + 3 }, o -> $i { $i + 3 }, o { $^i + 3 }o sub ($i){ $i + 3 })


Il modo più breve per creare qualcosa di Callable per generare i primi n elementi è quello di ottenere una fetta degli elementi.

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

Nel vuoto contesto ciò genererebbe i primi $_valori, quindi li getterebbe via prontamente.

In qualcosa di diverso dal contesto vuoto crea un blocco di codice anonimo (una subroutine di base senza un nome) che accetta un argomento.

# 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 pensi davvero che debba avere un nome per essere considerato valido per questa sfida, probabilmente lo faresti:

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

Sebbene poiché ssia utilizzato anche per l'operatore di sostituzione, per chiamare questo i genitori non sono opzionali. (Avresti potuto dargli un nome diverso suppongo)

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

Salvo quanto diversamente specificato nella sfida, gli invii alle sfide del codice golf devono essere programmi o funzioni completi , non solo frammenti.
Martin Ender,

@ MartinBüttner per essere onesti in 1,2,4,*+3...*realtà crea un oggetto che genererà i valori necessari. Non penso che molte persone creerebbero qualcosa di callable attorno a qualcosa del genere in Perl6.
Brad Gilbert b2gills

2

Vedo che c'è già una risposta java MOLTO migliore, ma ho passato un po 'di tempo su questo e ho intenzione di pubblicarlo. anche se fa schifo.

Char Java 313 (+4 per adattarlo allo schermo)

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 di avere consigli o suggerimenti su come migliorare


1

T-SQL 204

Presuppone che l'input sia in una variabile chiamata @N. Posso fare una procedura se vuoi, ma non c'è davvero un buon modo per ottenere STD_IN in T-SQL.

Inoltre, yay per bonus morale!

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 @

Bello! Non so molto su SQL: come viene utilizzato @N qui? Vedo che è impostato vicino all'inizio, ma poi non sembra essere referenziato in seguito.
Théophile il

Sembra che @Nsia la "i" della "for loop".
Jacob,

Jacob ha ragione. @N è la "i" del ciclo for, che è un ciclo while in SQL. Sostanzialmente si incrocia con la tabella e trova coppie che si aggiungono a @Q. Se ci sono almeno due coppie (cioè non solo un numero con se stesso), allora lo salta. Altrimenti, lo aggiunge alla tabella. @ è il nome della tabella.
segna il

1

Mathematica, 27 byte

Hmmm, ancora nessuna risposta Mathematica? Eccone due:

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

entrambi definiscono una funzione pura senza nome che riceve un numero intero e restituisce un elenco di numeri interi. Questo si basa sulla stessa relazione di ricorrenza della mia presentazione CJam. Si noti che il Arraycodice basato su inizia da 1/2, poiché la relazione di ricorrenza viene sempre applicata prima che il valore venga restituito.



1

Python - neanche vicino (139)

Agendo sul presupposto che questo non fosse facilmente calcolabile come altri hanno fatto, la soluzione più breve che ho trovato è di seguito:

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

Versione senza golf:

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

Condividi e divertiti.


1

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

Questo utilizza la definizione della sequenza.

Versione più leggibile:

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
}

stampa q [10]

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


Suggerimenti per il golf Ruby: *k=1invece di k=[1]. foo while barinvece di while bar;foo;end. [*s..e]invece di (s..e).to_a. .mapinvece di to_a.map. {|a,b|a+b}invece di {|i|i.inject(:+)}.
istocratico

@histocrat Grazie, è molto 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 byte

Per la tua calcolatrice

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

0

GML , 67 byte

n=argument0;for(i=1;i<=n;i++){t=i;if i>2t=(i-2)*3+1show_message(t)}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.