Genera numeri Ulam


19

Dato un numero intero n(dove n < 10001) come input, scrivere un programma che produrrà i primi n numeri Ulam . Un numero Ulam è definito come segue:

  1. U 1 = 1, U 2 = 2.
  2. Perché n > 2, U n è il numero intero più piccolo che è maggiore di U n-1 che è la somma di due termini precedenti distinti esattamente in un modo.

Ad esempio, U 3 è 3(2 + 1), U 4 è 4(3 + 1) (nota che (2 + 2) non conta poiché i termini non sono distinti), e U 5 è 6, (U 5 non è 5 perché 5 può essere rappresentato come 2 + 3 o 4 + 1). Ecco i primi numeri Ulam:

1, 2, 3, 4, 6, 8, 11, 13, 16, 18, 26, 28, 36, 38, 47, 48, 53, 57, 62, 69, 72, 77, 82, 87, 97, 99

Questo è il golf del codice, quindi vince l'ingresso più breve.


L'output deve essere come mostrato (elenco separato da virgola e spazio) o possiamo ad esempio generare un array?
Dennis,

Qual è il valore minimo nche dobbiamo gestire?
Dennis,

1
@Dennis Space o virgola o entrambi vanno bene. Il valore minimo di n è 1.
assenzio

Così com'è, ho parentesi attorno alla mia lista. Anche quello va bene o dovrei rimuoverli?
Dennis,

1
@Dennis Le staffe vanno bene.
assenzio

Risposte:


10

CJam, 47 41 37 byte

li4,1${__m*{_~<\:+*}%$2/z:^$2=+}*1><`

Provalo online.

Esempio di esecuzione

$ cjam <(echo 'li4,1${__m*{_~<\:+*}%$2/z:^$2=+}*1><`') <<< 26
[1 2 3 4 6 8 11 13 16 18 26 28 36 38 47 48 53 57 62 69 72 77 82 87 97 99]

Come funziona

Questa idea di base è la seguente:

  1. Inizia con l'array A := [ 0 U₁ U₂ ... Uₖ ].

  2. Calcola S, la matrice di tutte le somme in modo x + ytale che x,y ∊ Ae x < y.

  3. Scarta tutte le somme non uniche da S. Poiché ogni numero Ulam maggiore di 2 è sia la somma di due più piccoli sia la somma di zero e di se stessa, questo scarta i numeri Ulam U₃, U₄, ... Uₖ.

  4. L'array rimanente è [ U₁ U₂ Uₖ₊₁ ... ], quindi il prossimo numero Ulam è il terzo elemento più piccolo. Aggiungilo Ae torna al passaggio 1.

li                                    " Read one integer (I) from STDIN.                  ";
  4,                                  " Push the array A = [ 0 1 2 3 ].                   ";
    1${                        }*     " Do the following I times:                         ";
       __m*                           " Push the Cartesian product A × A.                 ";
           {       }%                 " For each pair (x,y) in A × A:                     ";
            _~<\:+*                   " Compute (x + y) * (x < y).                        ";
                     $2               " Sort the resulting array.                         ";
                       /              " Split it into chunks of length 2.                 ";
                        z             " Transpose the resulting two-dimensional array.    ";
                         :^           " Compute the symmetric difference of its rows.     ";
                           $          " Sort the resulting array.                         ";
                            2=        " Extract its third element.                        ";
                              +       " Push it on the array A.                           ";
                                 1>   " Discard the first element of A (0).               ";
                                   <  " Discard all but the first I elements of A.        ";
                                    ` " Push a string representation of A.                ";

Un input di 100richiede già diversi secondi. Suppongo che calcolare l'input massimo 1e5 richiederebbe anni?
Martin Ender,

@ MartinBüttner: l'interprete Java è molto più veloce, ma è ancora lento. Tutti gli algoritmi a forza bruta sono O (n²) o peggio. L'uso di un linguaggio orientato allo stack per gli array non è mai carino (ad esempio, calcolare una lunghezza degli array richiede la copia dell'intero array), quindi il tempo di esecuzione effettivo è probabilmente O (n³).
Dennis,

1
@ MartinBüttner: WolframAlpha , quindi 1e4 (per fortuna, non 1e5) dovrebbe richiedere meno di tre settimane.
Dennis,

6

J - 46 char

Funzione che assume ncome argomento.

_2}.(,]<./@-.~</~({.+_*1<#)/.~@#&,+/~)@[&0&1 2

Spiegato dall'esplosione:

    (                                )          NB. procedure for a list:
                                  +/~           NB.   take an addition table
              </~              #&,              NB.   select the top right half (no diag)
                 (        )/.~@                 NB.   for each unique value:
                       1<#                      NB.     if more than one present
                  {.+_*                         NB.     add infinity to it
      ]    -.~                                  NB.   remove existing Ulam numbers
       <./@                                     NB.   take the smallest
     ,                                          NB.   append to Ulam numbers
                                      @[&0      NB. repeat this procedure:
                                          &1 2  NB.   n times starting with [1, 2]
_2}.                                            NB. drop the last two numbers

C'è +_*...
tomsmeding,

6

T-SQL, 301 300 288 287

Ho commesso un leggero abuso di SQL.

DECLARE @N INT=100,@T INT=1DECLARE @ TABLE(I INT,U INT)INSERT @ VALUES(1,1),(2,2)#:IF @T>2INSERT @ SELECT TOP 1@T,A.U+B.U FROM @ A,@ B WHERE A.U>B.U GROUP BY A.U+B.U HAVING COUNT(*)=1AND A.U+B.U>ALL(SELECT U FROM @)ORDER BY 2SET @T+=1IF @T<=@N GOTO # SELECT U FROM @ WHERE I<=@N ORDER BY I

Provalo in SQL Server 2008 qui .

@N contiene il numero intero di input. Cambia l'esempio "100" in quello che dovrebbe essere n. "10000" probabilmente finirà alla fine, ma non l'ho lasciato correre fino al completamento. Il conteggio dei caratteri di questa voce è per un input di una cifra. L'output è nel modulo del risultato della query.


5

Haskell, 70 67 caratteri

u n=take n$1:2:[x|x<-[1..],[_]<-[[y|y<-u$n-1,z<-u$n-1,y<z,y+z==x]]]

utilizzo:

>u 6
[1,2,3,4,6,8]

5

GolfScript ( 41 37 byte)

~.14*,3,\{1$.{2$1$-.@<*}%&,2=*|}/0-<`

Demo online

I prodotti cartesiani in GolfScript sono piuttosto lunghi, quindi questo ha un approccio diverso. La crescita a lungo termine dei numeri di Ulam è che il nnumero di Ulam è circa 13.5n, ma nei primi 10000 termini il rapporto più grande tra il nnumero di Ulam ed nè appena sotto 13.3. Quindi, dato nche possiamo filtrare i primi 14nnumeri per trovare quelli che appartengono alla sequenza.

Grazie a Dennis per 41-> 37.


1
Questo è abbastanza veloce. n = 1000impiega meno di un minuto con GolfScript; una porta per CJam si completa n = 1000in 8 secondi e n = 10000in 1h 20 m. - Puoi salvare quattro byte combinando il tuo approccio con il mio, vale a dire includendo 0 nell'array e scartandolo in seguito. Ciò consente di utilizzare set union anziché il blocco ed elimina la necessità di una variabile:~.14*,4,\{1$.{2$1$-.@<*}%&,2=*|}/1><`
Dennis

@Dennis, quanti caratteri più brevi è la CJam? Presumo che nessuna delle operazioni si allunghi, e sono abbastanza sicuro che abbia un alias di un carattere per 14.
Peter Taylor,

Sì, 14è giusto E. Ma devi leggere da STDIN, convertire il numero intero in un singleton prima di eseguire set union ( 2$invierò una segnalazione di bug al riguardo) e non funzionerà nel ciclo interno poiché CJam modifica lo stack dopo ogni iterazione ... I ho provato diversi trucchi, ma il più breve era esattamente 37 byte:li4,1$E*{__{I1$-_@<*}%&,2=I*a|}fI1><`
Dennis

5

JavaScript ES6, 100 ... 93 90 caratteri

Eseguilo in Web Console o Scratchpad dell'ultima versione di Firefox (Nightly o versione).

EDIT 8 Golf molto !!! e ridotto a 94 caratteri 93 90 caratteri (grazie a @openorclose). (Il mio primo sub 100)

Ecco la mia versione che è molto più veloce ma è più lunga di 3 caratteri (107 caratteri) ed è esattamente la stessa quantità di caratteri di cui sopra ed è molto più piccola del metodo della forza bruta qui sotto !, (grazie a edc65):

u=n=>(s=>{for(r=[i=l=1];c=l<n;i+=c&&i-2?1:s[r[l++]=i]=1)r.map(j=>c-=j<i/2&s[i-j])})([])||r

Continuerò a provare a golf ulteriormente. Ma lo stiamo spingendo fuori dallo scopo di JS: P

Ecco alcuni numeri quando eseguo questo all'interno di un tag di script in una pagina Web:

n volte
10 0,001
100 0,005
1000 2.021
10000 236.983
100000       tldr in sospeso ; Troppo a lungo non funzionava: P

Questa è la mia prima presentazione che è fortemente ispirata dalla risposta di @ rink.attendant.6 in JavaScript.

u=n=>{for(l=[1,g=2],i=3;g<n;++i){z=1;for(j of l)for(k of l)z-=j<k&j+k==i;!z?l[g++]=i:0}return n>1?l:[1]}

So che si può giocare a golf ancora di più. Pubblicherò anche una soluzione non bruta, che potrebbe essere ancora più breve.

EDIT 1 : golfato un po 'di più e risolto per n = 1

Devo dire che invidio Haskell e J per scorciatoie così super utili per ogni tipo di esigenza -_-


riguardo a Haskell, penso che lo stile funzionale e la sintassi facciano la differenza (per esempio, nessun loop gigante orribile), sebbene la quantità di funzioni sia sempre piacevole :-)
orgoglioso haskeller

1
Il più veloce può sicuramente essere giocato a golf di più: (104) u=n=>{for(s=[,1,1],r=[i=1,l=2];c=l<n;!c?s[r[l++]=i]=1:0,i++)for(j of r)c-=j<i/2&s[i-j];return n>1?r:[1]}e forse anche di più
edc65

1
1. Riesco ancora a malapena a capire come hai evitato il doppio loop. Complimenti 2. Suggerimento per il golf: in E6 cerco sempre di evitare return. 100:u=n=>(s=>{for(r=[i=1,l=2];c=l<n;i+=!c?s[r[l++]=i]=1:1)for(j of r)c-=j<i/2&s[i-j]})([,1,1])|n>1?r:[1]
edc65,

1
C'è un u=n=>(s=>{for(r=[i=l=1];c=l<n;i+=c&&i-2?1:s[r[l++]=i]=1)for(j of r)c-=j<i/2&s[i-j]})([,1])||r
personaggio in

1
90 caratteri: a u=n=>(s=>{for(r=[i=l=1];c=l<n;i+=c&&i-2?1:s[r[l++]=i]=1)r.map(j=>c-=j<i/2&s[i-j])})([])||r meno che [, 1] non sia necessario da qualche parte
openorclose l'

5

Perl - 71 byte

#!perl -p
@a=$b[2]=1;1while$b[++$a]^1||$_>map(++$b[$_+$a],@a)&&push@a,$a;$_="@a"

Provalo online!

Contando lo shebang come uno.
L'uso di un secondo array per memorizzare le somme sembra essere significativamente più veloce di un hash. Anche l'utilizzo della memoria è inferiore, cosa che non mi sarei aspettato.

Esempio di utilizzo:

$ echo 30 | perl ulam.pl

Uscita campione:

1 2 3 4 6 8 11 13 16 18 26 28 36 38 47 48 53 57 62 69 72 77 82 87 97 99 102 106 114 126

Durata approssimativa:

n = 100     0.015s
n = 1000    0.062s
n = 10000   4.828s

2
8,6 s per n == 1e4. Sorprendente! L'output per n == 1non è corretto; dovrebbe stampare un singolo numero.
Dennis,

@Dennis ora risolto.
primo

4

Java, 259

import java.util.*;class C{public static void main(String[]a){List<Integer>l=new ArrayList<>();l.add(1);l.add(2);for(int i=3,z=0;l.size()<new Long(a[0]);i++,z=0){for(int j:l){for(int k:l){if(j<k&j+k==i)z++;}}if(z==1)l.add(i);}l.forEach(System.out::println);}}

La forza bruta funziona bene per questo.

import java.util.*;
class C {
    public static void main(String[] a) {
        List<Integer>l = new ArrayList<>();
        l.add(1);
        l.add(2);
        for (int i = 3, z = 0; l.size() < new Long(a[0]); i++, z = 0) {
            for (int j : l) {
                for (int k : l) {
                    if (j < k & j + k == i)
                        z++;
                }
            }
            if (z == 1)
                l.add(i);
        }
        l.forEach(System.out::println);
    }
}

1. La stampa del risultato sembra richiedere Java 8, che potrebbe essere degno di nota. 2. L'output per 1dovrebbe essere un singolo numero.
Dennis,

1
Questo gestisce un input di 10k?
Martin Ender,

Credo che j e k per i loop non abbiano bisogno di parentesi graffe.
Michael Easter,

Come suggerisce Martin, anch'io vorrei vedere un'esecuzione a tempo di questo programma per N = 10K.
Michael Easter,

4

APL (Dyalog Extended) , 36 35 byte

-1 byte di Adám

{⍵↑{⍵,⊃∧(∊⊢⊆⍨⍧⍨∊2 3⍨)⍵~⍨,+⍀⍨⍵}⍣⍵⍳2}

Provalo online!

{⍵↑{⍵,⊃∧(∊⊢⊆⍨⍧⍨∊2 3⍨)⍵~⍨,+⍀⍨⍵}⍣⍵⍳2}      Monadic function taking an argument n:

{⍵,⊃∧(∊⊢⊆⍨⍧⍨∊2 3⍨)⍵~⍨,+⍀⍨⍵}   Helper function to compute the next Ulam number
                                    given  (the first few Ulam numbers)
                        +⍀⍨⍵      Make an addition table from ⍵.
                       ,          Flatten into a list.
                   ⍵~⍨            Remove all entries already in ⍵.

     (∊⊢⊆⍨2 3∊⍨⍧⍨)               Helper function taking an argument x:
                ⍧⍨                  The count of elts of x in itself                 
           2 3∊⍨                    1s where those counts are in (2 3), else 0s.*
       ⊢⊆⍨                          Partition x, removing values corresponding to 0s.
                                   Join the partitions into a single list.

    (∊⊢⊆⍨⍧⍨∊2 3⍨)                Keep all elements that occur exactly 2 or 3 times.
                                  (i.e. that occur once as a
                                  sum of distinct elements of ⍵).
                             Sort ascending.
                             Take the first value (the next Ulam #).
 ⍵,                           Append that value to ⍵.

{⍵↑{...}⍣⍵⍳2}
{  {...}⍣⍵  }                 Call the helper function n times
           2                 starting with (1 2). First n+2 Ulam numbers.
 ⍵↑                           Keep the first n elements.

XXX2un'+Bun'XBXun'=12un'+B{2,3}

* (In ngn / APL, una costante può terminare un treno senza usare . Ma ngn / APL non ha un conteggio, quindi abbiamo bisogno di ⍨ da qualche parte.)


{(2 3∊⍨⍵⍧⍵)/⍵}(∊⊢⊆⍨⍧⍨∊2 3⍨)
Adám,

3

PHP 5.4+, 164

Stesso approccio delle mie risposte:

<?function u($n){for($l=[1,2],$i=3;count($l)<$n;++$i){$z=0;foreach($l as $j){foreach($l as $k){$z+=$j<$k&$j+$k==$i;}}if($z==1)$l[]=$i;}return array_slice($l,0,$n);}

3

Gelatina , 20 byte

Œc§ḟµḟœ-Q$Ṃɓ;
2RÇ⁸¡ḣ

Provalo online!

Œc§ḟµḟœ-Q$Ṃɓ;    Helper link that appends the next number to x, a list of Ulam numbers:
Œc                  All unordered pairs of x
  §                 Sum each pair
   ḟ                Filter out the numbers already present in x.
    µ               Let this list be y. Then apply the following chain:

     œ-Q$Ṃ          Find the minimum of all unique elements.
     ḟ                Take y and filter out the elements in
      œ-Q$            the multiset difference between y and its unique elements.
          Ṃ           Then find the Ṃinimum of the result.

           ɓ;    Append (ɓ reverses argument order) the result to 


2RÇ⁸¡ḣ           Main link:
2R               Start with [1,2].
  Ç⁸¡            Apply the helper link (Ç) n (⁸) times to generate n+2 Ulam #s.
     ḣ           Keep the first n values.

2

CoffeeScript, 119 114

Ultimamente ho praticato CoffeeScript per migliorare il golf JavaScript, quindi ecco la mia risposta JavaScript compilata in CoffeeScript:

u=(n)->l=[1,2];i=3;z=0;(for j in l
 for k in l
  z+=j<k&j+k==i
l.push(i) if z==1;++i;z=0)while l.length<n;l[..n-1]

Non capisco molto bene i cicli e le comprensioni in CoffeeScript, quindi forse questo può essere ulteriormente approfondito, ma è quello che ho per ora. Le newline sono contate come un personaggio (stile Unix).


2

JavaScript, 147 154 150 (136)

Fortemente ispirato alla soluzione Java di @ Ypnypn a forza bruta pubblicata in precedenza:

function u(n){for(l=[1,2],i=3;l.length<n;++i){z=0;l.forEach(function(j){l.forEach(function(k){z+=j<k&j+k==i})});if(z==1)l.push(i)}return l.slice(0,n)}

Grazie per @Dennis per aver rasato 4 a 18 byte dalla mia versione originale

Versione pericolosa (utilizzando for..inloop)

Non consiglierei di eseguirlo perché il looping di un oggetto che utilizza un loop potrebbe causare lo scoppio della macchina in fiamme e / o la trasformazione in una macchina per uccidere arrabbiata, ma eccola qui:instanceof Arrayfor..in

function u(n){for(l=[1,2],i=3;l.length<n;++i){z=0;for(j in l)for(k in l)z+=l[j]<l[k]&l[j]+l[k]==i;if(z==1)l.push(i)}return l.slice(0,n)}

Ungolfed

function u(n) {
    var l = [1, 2],
        i = 3,
        j, k, z;

    for (; l.length < n; ++i) {
        z = 0; 
        l.forEach(function (j) {
            l.forEach(function (k) {
                if (j < k & j + k === i) {
                    z++;
                }
            });
        });
        if (z === 1) {
            l.push(i);
        }
    }

    return l.slice(0, n);
}

L'output per 1 dovrebbe essere un singleton.
Dennis,

@Dennis Grazie, corretto.
rink.attendant.6

1. Se ti sposti z=0all'interno del loop, ne hai bisogno solo una volta. 2. for(j in l)for(k in l)z+=l[j]<l[k]&l[j]+l[k]==i;è molto più breve l.forEachdell'approccio.
Dennis,

2

Mathematica, 107 91 byte

Nest[#~Append~Min@Cases[Tally[Tr/@#~Subsets~2],{n_,1}:>n]&,{1,2},i=Input[]]~Drop~{3}~Take~i

È un'implementazione molto diretta delle specifiche.

  • Trova tutte le coppie.
  • Elimina tutti i duplicati.
  • Elimina tutti i numeri in meno dell'ultimo numero Ulam.
  • Aggiungi il minimo all'elenco.

Sto anche applicando il trucco di Dennis di includere le somme 0, ma il trucco è che questo rende il terzo elemento dell'elenco 0prima di riprendere come ci si aspetterebbe, quindi devo rimuovere quell'elemento dall'elenco.

Gestisce un input di 1000in pochi secondi, ma dubito che otterrai un risultato per 10k in un ragionevole lasso di tempo. Ma non penso che nessuno degli altri si comporti bene su questo.


2

OCaml - 254 personaggi

Il codice utilizza una tabella hash per memorizzare la somma degli elementi correnti dell'elenco e aggiornarlo ogni volta che viene calcolato un nuovo elemento.

open Hashtbl let h=create 7 let()=add h 3 1 let rec r n i l=if n=0then List.rev l else if mem h i&&find h i=1then(List.iter(fun x->if mem h(x+i)then replace h(x+i)2else add h(x+i)1)l;r(n-1)(i+1)(i::l))else r n(i+1)l let u n=if n=1then[1]else r(n-2)3[2;1]

Uso:

All'interno dell'interprete OCaml:

# u 26;;
- : int list =
[1; 2; 3; 4; 6; 8; 11; 13; 16; 18; 26; 28; 36; 38; 47; 48; 53; 57; 62; 69;
 72; 77; 82; 87; 97; 99]

Ungolfed

open Hashtbl
let h = create 7
let() = add h 3 1
let rec r n i l =
  if n=0 then List.rev l
  else if mem h i && find h i=1 then
    begin
      List.iter
        (fun x-> if mem h(x+i) then replace h (x+i) 2 else add h (x+i) 1)
        l;
      r (n-1) (i+1) (i::l)
    end
  else r n (i+1) l

let u n = if n=1 then [1] else r (n-2) 3 [2;1]

2

Pitone, 137 128 126 caratteri.

U,i=[1,2],2
for _ in [[0]]*(input()-2):
 t=_*3*i
 for a in U:
  for b in U:t[a+b]+=a!=b
 i=t[i+1:].index(2)+i+1;U+=[i]
print U

Questo è il mio primo golf e l'ho ridotto da ~ 250 caratteri, sono abbastanza felice ma mi piacerebbe avere suggerimenti su come migliorare!


Minore, ma utile: combina le linee 5 e 6 for b in U:t[a+b]+=a!=be le linee 8 e 9 awhile t[i]-2:i+=1
James Waldby - jwpat7,

Grazie per il suggerimento! Ho anche cambiato il ciclo while in un indice ma non ha salvato tutti i caratteri che mi aspettavo.
QuadmasterXLII

Altri 2 caratteri: inizializza U su [1] e sposta la linea 7 dopofor
James Waldby - jwpat7,

Puoi ancora sbarazzarti di 2 caratteri cambiando U,i=[1,2],2in U,i=[1],2e input()-2verso input()-1e t=_*3*iverso t=_*3*i;U+=[i]e rimuovere ;U+=[i]alla fine di per
James Waldby - jwpat7

0

C #, 257

Approccio a forza bruta, usando LINQ:

using System.Linq;class U{void F(int n){var u=n<2?new int[]{1}:new int[]{1,2};for(int i=3;u.Length<n;++i)if(u.SelectMany(x=>u,(a,b)=>new{A=a,B=b}).Count(x=>x.A>x.B&&x.A==i-x.B)==1)u=u.Union(new int[]{i}).ToArray();System.Console.Write(string.Join("",u));}}

Ungolfed, con test Harness

using System.Linq;
class Ulam
{
    void F(int n)
    {
        //handle special case where n = 1 (ugh)
        var u = n < 2 ? new int[] { 1 } : new int[] { 1, 2 };
        for (int i=3; u.Length<n; ++i)
            if (u.SelectMany(x => u, (a, b) => new { A = a, B = b })
                     .Count(x => x.A > x.B && x.A == i - x.B) == 1)
                u = u.Union(new int[] { i }).ToArray();
        System.Console.Write(string.Join(" ",u));
    }
    public static void Main(string[] args)
    {
        new Ulam().F(1);
        System.Console.WriteLine();
        new Ulam().F(2);
        System.Console.WriteLine();
        new Ulam().F(3);
        System.Console.WriteLine();
        new Ulam().F(26);
        System.Console.WriteLine();
    }
}

Molto lento: 46s per n = 500, 6m per n = 1000, 50m per n = 2000. A quel ritmo esponenziale, credo che occorreranno 5 o 6 giorni per elaborare n = 10K.
Riccardo II,

0

Pyth, 27 25 byte

<uaGh-sfq1lT.gksM.cG2GQS2

Provalo online qui .

<uaGh-sfq1lT.gksM.cG2GQS2Q   Implicit: Q=eval(input())
                             Trailing Q inferred
 u                    Q      Perform the following Q times...
                       S2    ... with G initialised to [1,2]:
                 .cG2          Get all 2-element combinations of G
               sM              Sum each pair
            .gk                Group them by value
                                 The groups are sorted by the result of the sum
       f                       Filter the groups, as T, keeping those where:
          lT                     Length of T
        q1                       Equal to 1
      s                        Flatten list
     -               G         Remove elements of the above which are already in G
    h                          Take the first of the remaining elements
                                 This is the smallest, as the grouping also sorted them
  aG                           Append this to G
<                        Q   Take the first Q elements, implicit print

Modifica: golfato 2 byte eseguendo la somma prima del raggruppamento. Versione precedente:<uaGh-mssdfq1lT.gsk.cG2GQS2


0

C, 478 byte

#define R return
bs(x,v,l,h,r)unsigned x,*v,l,h,*r;{unsigned m;for(;l<=h;){m=(l+h)/2;if(x<v[m])h=m-1;else if(x>v[m])l=m+1;else{*r=m;R 1;}}*r=m;R 0;}
#include<stdlib.h>
unsigned*f(unsigned w){unsigned*u=0,i,k,m,y,z;if(w>1E6||w==0)R u;u=malloc(w*sizeof*u);if(!u)R u;k=0;u[k++]=1;if(w==1)R u;m=u[k++]=2;if(w==2)R u;l:for(i=0,y=0,z=k-1,++m;i<k;y+=bs(m-u[i],u,i+1,z,&z),++i)if(y>1||u[i]+(i+1!=k?u[i+1]:0)>m)break;if(m==0){free(u);u=0;R u;}if(y!=1)goto l;u[k++]=m;if(k< w)goto l;R u;}

In Tio ora in 9 secondi troverà 10000 valori (e lì dentro stampa i primi 100 valori). Il trucco sta usando non la ricerca lineare nel loop interno ma la ricerca binaria ... Queste di seguito sono funzioni ben rientrate e completamente leggibili (finalmente per me):

bsCopy(x,v,l,h,r)unsigned x,*v,l,h,*r;
{unsigned m;
 for(;l<=h;){m=(l+h)/2;if(x<v[m])h=m-1;else if(x>v[m])l=m+1;else{*r=m;R 1;}}
 *r=m;R 0;// in *r if return 0 the min index that fail else the index of find x
}

unsigned*fCopy(unsigned w)
{unsigned*u=0,i,k,m,y,z;
 if(w>1E6||w==0)R u;
 u=malloc(w*sizeof*u);
 if(!u)R u;
 k=0;u[k++]=1;if(w==1)R u;
   m=u[k++]=2;if(w==2)R u;//below I suppose m-u[i] is in the range (if exist in u) (i+1)..z 
 l: for(i=0,y=0,z=k-1,++m;i<k;y+=bsCopy(m-u[i],u,i+1,z,&z),++i)
          if(y>1||u[i]+(i+1!=k?u[i+1]:0)>m)break;
   if(m==0){free(u);u=0;R u;}
          if(y!=1)goto l;
   u[k++]=m;if(k< w)goto l;
 R u;
}

Vedi se riesco a ridurre qualcosa ...
RosLuP,

Qualcosa mi dice che nella programmazione del golf è ok ma non è tutto ...
RosLuP


@ceilingcat "z = k" per me è sbagliato perché la ricerca binaria (funzione bs () o la tua funzione B ()) mi sembra volere come intervalli di argomenti (non so se sia giusto anche ...) quindi in la funzione che chiama la ricerca bin deve essere z = k-1
RosLuP

0

APL (NARS), 278 caratteri, 556 byte

∇u←p w;m;y;i;k;z;r;bs
bs←{(x l h)←⍵⋄l>h:0,h⋄x<⍺[t←⌊2÷⍨l+h]:⍺∇x,l,t-1⋄x>⍺[t]:⍺∇x,(t+1),h⋄1,t}
u←⍬  ⋄→0×⍳(w>1E6)∨w≤0
u←u,1⋄→0×⍳w=1
u←u,2⋄→0×⍳w=2⋄k←m←2
i←1⋄y←0⋄m+←1⋄z←k
→7×⍳(y>1)∨i>k⋄→7×⍳m<u[i]+{i=k:0⋄u[i+1]}⋄r←u bs(m-u[i]),(i+1),z⋄y+←↑r⋄z←2⊃r⋄i+←1⋄→6
→5×⍳y≠1⋄u←u,m⋄k+←1⋄→5×⍳k<w
∇

sarebbe la traduzione in APL di C che ho inviato. Sembra che non capisca quando usare ∇∇ al posto di possible ... possibile ∇∇ viene usato quando c'è un argomento è una funzione (e non un altro tipo). "u bs x, a, b" dovrebbe essere la ricerca bin nell'array "u" per il valore "x" nell'intervallo a..b; restituirebbe 1, indexWhereFind o 0, indexWhereEndOfsearch. Con la funzione argomento 200 p prendere + - un minuto qui ...

  p 100
1 2 3 4 6 8 11 13 16 18 26 28 36 38 47 48 53 57 62 69 72 77 82 87 97 99 102 106 114 126 
  131 138 145 148 155 175 177 180 182 189 197 206 209 219 221 236 238 241 243 253 
  258 260 273 282 309 316 319 324 339 341 356 358 363 370 382 390 400 402 409 412 
  414 429 431 434 441 451 456 483 485 497 502 522 524 544 546 566 568 585 602 605 
  607 612 624 627 646 668 673 685 688 690 
  p¨1 2 3 4
1  1 2  1 2 3  1 2 3 4 

1
∇∇in dop si riferisce all'operatore stesso mentre si riferisce alla funzione derivata consistente dell'operatore con i suoi operandi. Quindi in un operatore monadico è lo stesso che (⍺⍺∇∇)in un operatore diadico (⍺⍺∇∇⍵⍵).
Adám,
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.