Gerar números Ulam


19

Dado um número inteiro n(onde n < 10001) como entrada, escreva um programa que produzirá os primeiros n números Ulam . Um número Ulam é definido da seguinte maneira:

  1. L 1 = 1, L 2 = 2.
  2. Pois n > 2, U n é o menor número inteiro maior que U n-1, que é a soma de dois termos anteriores distintos , exatamente de uma maneira.

Por exemplo, L 3 representa 3(2 + 1), L 4 representa 4(3 + 1) (Note-se que (2 + 2) não conta que as condições não são distintas), e L 5 seja 6, (L 5 não é 5 porque 5 pode ser representado como 2 + 3 ou 4 + 1). Aqui estão os primeiros números da 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

Isso é código de golfe, portanto a entrada mais curta vence.


A saída precisa ser a exibida (lista separada por vírgula e espaço) ou podemos produzir, por exemplo, uma matriz?
Dennis

Qual é o valor mínimo nque temos que lidar?
Dennis

11
@Dennis Espaço ou vírgula ou ambos estão bem. O valor mínimo de n é 1.
absinto

No momento, tenho colchetes em volta da minha lista. Tudo bem também ou devo removê-los?
Dennis

11
Os suportes @Dennis estão bem.
absinto

Respostas:


10

CJam, 47 41 37 bytes

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

Experimente online.

Exemplo de execução

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

Como funciona

Essa ideia básica é a seguinte:

  1. Comece com a matriz A := [ 0 U₁ U₂ ... Uₖ ].

  2. Computar S, a matriz de todas as somas x + ytais que x,y ∊ Ae x < y.

  3. Descartar todas as somas não exclusivas de S. Como todo número Ulam maior que 2 é a soma de dois menores e a soma de zero e ele próprio, isso descarta os números Ulam U₃, U₄, ... Uₖ.

  4. A matriz restante é [ U₁ U₂ Uₖ₊₁ ... ], portanto, o próximo número Ulam é o terceiro menor elemento. Anexe-o Ae volte para a etapa 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.                ";

Uma entrada de 100já leva vários segundos. Suponho que calcular a entrada máxima 1e5 levaria idades?
Martin Ender

@ MartinBüttner: O intérprete Java é muito mais rápido, mas ainda é lento. Todos os algoritmos de força bruta são O (n²) ou pior. O uso de uma linguagem orientada a pilha para matrizes nunca é bonito (por exemplo, calcular o comprimento de uma matriz exige a cópia de toda a matriz); portanto, o tempo real de execução é provavelmente O (n³).
Dennis

11
@ MartinBüttner: WolframAlpha , então 1e4 (felizmente, não 1e5) deve levar menos de três semanas.
Dennis

6

J - 46 char

Função tomada ncomo argumento.

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

Explicado por explosão:

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

+_*...
tomsmeding 9/09/14

6

T-SQL, 301 300 288 287

Eu cometi um pouco de abuso leve de 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

Experimentá-lo em SQL Server 2008 aqui .

@N mantém o número inteiro de entrada. Mude o exemplo "100" para o que n deve ser. "10000" provavelmente terminará eventualmente, mas eu não deixei isso terminar. A contagem de caracteres desta entrada é para uma entrada de um dígito. A saída está no formulário de resultado da consulta.


5

Haskell, 70 67 caracteres

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

uso:

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

5

GolfScript ( 41 37 bytes)

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

Demonstração online

Os produtos cartesianos no GolfScript são bastante longos, portanto, isso requer uma abordagem diferente. O crescimento a longo prazo dos números de Ulam é que o nnúmero de Ulam é sobre 13.5n, mas nos primeiros 10000 termos a maior proporção entre o nnúmero de Ulam e nestá abaixo 13.3. Então, dado nque podemos filtrar o primeiro14n números para encontrar aqueles que pertencem à sequência.

Com agradecimentos a Dennis por 41-> 37.


11
Isso é bem rápido. n = 1000leva menos de um minuto com GolfScript; uma porta para CJam termina n = 1000em 8 segundos e n = 10000em 1h 20 m. - Você pode salvar quatro bytes combinando sua abordagem com a minha, incluindo 0 no array e descartando-o posteriormente. Isso permite a utilização de união conjunto em vez do bloco e elimina a necessidade de uma variável:~.14*,4,\{1$.{2$1$-.@<*}%&,2=*|}/1><`
Dennis

@ Dennis, quantos caracteres mais curtos é o CJam? Suponho que nenhuma das operações fique mais longa e tenho certeza de que possui um alias de um caractere para 14.
Peter Taylor

Sim, 14é justo E. Mas você precisa ler a partir de STDIN, converter o número inteiro em um singleton antes de executar a união do conjunto (apresentarei um relatório de bug sobre isso) e 2$não funcionará no loop interno, pois o CJam modifica a pilha após cada iteração ... tentei vários truques diferentes, mas o mais curto tinha exatamente 37 bytes:li4,1$E*{__{I1$-_@<*}%&,2=I*a|}fI1><`
Dennis

5

JavaScript ES6, 100 ... 93 90 caracteres

Execute isso no console da Web ou no Scratchpad do Firefox mais recente (noturno ou versão).

EDIT 8 Golfei muito !!! e reduziu para 94 caracteres 93 90 caracteres (graças a @openorclose). (Meu primeiro sub 100)

Aqui está minha versão, que é muito mais rápida, mas tem 3 caracteres mais (107 caracteres) e é exatamente a mesma quantidade de caracteres acima e é muito menor que o método de força bruta abaixo !, (graças 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

Vou continuar tentando jogar mais. Mas estamos espremendo-o fora do escopo de JS: P

Aqui estão alguns números quando eu executo isso dentro de uma tag de script em uma página da web:

n vezes
10 0,001
100 0,005
1000 2.021
10000 236.983
100000       tldr pendente ; Muito tempo não foi executado: P

Esta é minha primeira submissão, fortemente inspirada na resposta de @ rink.attendant.6 em 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]}

Eu sei que isso pode ser jogado ainda mais. Também publicarei uma solução não forçada, que pode ser ainda mais curta.

EDIT 1 : Jogou um pouco mais e corrigiu para n = 1

Devo dizer que invejo Haskell e J por atalhos super úteis para todo tipo de requisito -_-


sobre Haskell, acho que o estilo funcional e a sintaxe fazem a maior diferença (por exemplo, sem loops gigantes hediondos), embora a quantidade de funções seja sempre boa :-)
haskeller orgulhoso

11
O mais rápido certamente pode ser jogado mais: (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 talvez até mais
edc65

11
1. Eu ainda mal entendo como você evitou o loop duplo. Parabéns 2.Golf tip: no E6 eu sempre tento evitar 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

11
Há um caractere a menos: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
openorclose

11
90 caracteres: 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 A menos que o [, 1] seja necessário em algum lugar
openorclose

5

Perl - 71 bytes

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

Experimente online!

Contando o shebang como um.
Usar uma segunda matriz para armazenar as somas parece ser significativamente mais rápido que um hash. O uso de memória também é menor, o que eu não esperava.

Uso da amostra:

$ echo 30 | perl ulam.pl

Saída de amostra:

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

Durações aproximadas:

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

2
8,6 s para n == 1e4. Surpreendente! A saída para n == 1está incorreta; deve imprimir um único número.
Dennis

@Dennis agora corrigido.
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);}}

A força bruta funciona bem para isso.

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. A impressão do resultado parece exigir o Java 8, que vale a pena mencionar. 2. A saída para 1deve ser um único número.
Dennis

11
Isso lida com uma entrada de 10k?
Martin Ender

Acredito que o j e o k para loops não precisam de chaves.
Michael Easter

Como Martin sugere, eu também gostaria de ver uma execução programada deste programa para N = 10K.
Michael Easter

4

APL (Dyalog Extended) , 36 35 bytes

-1 byte por Adám

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

Experimente 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.

Quando fazemos a tabela de adição, os elementos diagonais são duas vezes as entradas em ⍵. Elementos não diagonais são somas de elementos distintos, com cadax ocorrendo duas vezes para cada sentido xpode ser escrito como uma soma de elementos distintos. Portanto, cada númerox ocorre 2uma+b vezes, onde uma é o número de maneiras x pode ser escrito como uma soma de elementos distintos de ⍵ e b é 1 iff xé duas vezes uma entrada em ⍵. Nós queremosuma=1 1, portanto, é suficiente verificar 2uma+b{2,3}.

* (Em ngn / APL, uma constante pode terminar um trem sem usar . Mas ngn / APL não tem contagem, portanto precisamos de ⍨ em algum lugar.)


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

3

PHP 5.4+, 164

Mesma abordagem que minhas respostas:

<?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 bytes

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

Experimente 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, tenho praticado o CoffeeScript para melhorar o JavaScript no golfe, então aqui está minha resposta do JavaScript compilada no 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]

Eu não entendo muito bem loops e compreensões no CoffeeScript, então talvez isso possa ser melhorado, mas é o que tenho por enquanto. As novas linhas são contadas como um caractere (estilo Unix).


2

JavaScript, 147 154 150 (136)

Fortemente inspirado na solução Java de força bruta de @ Ypnypn postada anteriormente:

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

Obrigado por @Dennis por raspar 4 a 18 bytes da minha versão original

Versão perigosa (usando for..inloops)

Eu não recomendaria executar isso porque o loop através de um objeto que usa um loop pode fazer com que sua máquina se queime e / ou se transforme em uma máquina de matar furiosa, mas aqui está: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);
}

A saída para 1 deve ser um singleton.
Dennis

@ Dennis Obrigado, corrigido.
usar o seguinte código

1. Se você se mover z=0dentro do loop, precisará dele apenas uma vez. 2. for(j in l)for(k in l)z+=l[j]<l[k]&l[j]+l[k]==i;é muito mais curto que a l.forEachabordagem.
Dennis

2

Mathematica, 107 91 bytes

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

É uma implementação muito direta das especificações.

  • Encontre todos os pares.
  • Exclua todas as duplicatas.
  • Exclua todos os números menores que o último número Ulam.
  • Anexe o mínimo à lista.

Também estou aplicando o truque de Dennis de incluir somas 0, mas o problema é que isso torna o terceiro elemento da lista0 antes de continuar como seria de esperar, então preciso remover esse elemento da lista.

Ele lida com uma entrada 1000em alguns segundos, mas duvido que você obtenha um resultado de 10k em um período de tempo razoável. Mas também não acho que nenhum dos outros tenha um bom desempenho nisso.


2

OCaml - 254 caracteres

O código usa uma tabela de hash para armazenar a soma dos elementos atuais da lista e atualizá-la sempre que um novo elemento é calculado.

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:

No intérprete do 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

Python, 137 128 126 caracteres.

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

Este é o meu primeiro golfe, e reduzi de ~ 250 caracteres, estou muito feliz, mas adoraria sugestões de como melhorar!


Menor, mas vale a pena: combinar linhas 5 e 6 para for b in U:t[a+b]+=a!=be linhas 8 e 9 awhile t[i]-2:i+=1
James Waldby - jwpat7

Obrigado pela sugestão! Também mudei o loop while para um índice, mas ele não salvou tantos caracteres quanto eu esperava.
QuadmasterXLII

Mais 2 caracteres: o init L com [1], e movimento para a linha 7 após ofor
James Waldby - jwpat7

Você ainda pode se livrar de 2 caracteres, alterando U,i=[1,2],2a U,i=[1],2e input()-2a input()-1e t=_*3*ia t=_*3*i;U+=[i]e remova ;U+=[i]no final do para
James Waldby - jwpat7

0

C #, 257

Abordagem de força 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, Com Arnês de Teste

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

Muito lento: 46s para n = 500, 6m para n = 1000, 50m para n = 2000. A essa taxa exponencial, acredito que levará 5 ou 6 dias para processar n = 10K.
Richard II

0

Pitão, 27 25 bytes

<uaGh-sfq1lT.gksM.cG2GQS2

Experimente online aqui .

<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

Editar: golfou 2 bytes executando a soma antes de agrupar. Versão anterior:<uaGh-mssdfq1lT.gsk.cG2GQS2


0

C, 478 bytes

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

No Tio, agora em 9 segundos, ele encontraria 10000 valores (e aí imprimem os primeiros 100 valores). O truque é usar a pesquisa não linear no loop interno, mas a busca binária ... Estas são funções bem identadas e legíveis (finalmente para mim):

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

Veja se eu posso reduzir algo ...
RosLuP 15/02

Algo me diz que na programação de golfe está ok, mas não é tudo ...
RosLuP 15/02


@ceilingcat "z = k" para mim está errado porque a pesquisa binária (função bs () ou sua função B ()) parece-me querer como intervalos de argumentos (não sei se está certo também ...) a função que chama a pesquisa bin deve ser z = k-1
RosLuP

0

APL (NARS), 278 caracteres, 556 bytes

∇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
∇

seria a tradução em APL de C que enviei. Parece que eu não entendo quando usar ∇∇ no lugar de possible ... possível ∇∇ é usado quando há um argumento e uma função (e não outro tipo). "u bs x, a, b" deve ser a pesquisa de posição na matriz "u" para o valor "x" no intervalo a..b; retornaria 1, indexWhereFind ou 0, indexWhereEndOfsearch. Com o argumento 200 p function leve + - um minuto aqui ...

  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 

11
∇∇em um dop refere-se ao próprio operador, enquanto refere-se à função derivada que consiste no operador com seus operandos. Portanto, em um operador monádico é o mesmo que (⍺⍺∇∇)em um operador diádico, isso significa (⍺⍺∇∇⍵⍵).
Adám 17/02
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.