Ulam Numaraları Oluşturma


19

Girdi olarak bir tamsayı n(burada n < 10001) verildiğinde , ilk n Ulam sayılarını çıktılayacak bir program yazın . Bir Ulam numarası aşağıdaki gibi tanımlanır:

  1. U 1 = 1U 2 = 2.
  2. Çünkü n > 2U n , tam olarak bir şekilde iki farklı önceki terimin toplamı olan U n-1'den büyük olan en küçük tamsayıdır .

Örneğin, U 3 olduğu 3(2 + 1), U 4 olduğu 4(3 + 1) (terimler farklı değildir (2 + 2) sayılmaz not) ve U 5 olan 6, U ( 5 5 değil çünkü 5, 2 + 3 veya 4 + 1 olarak temsil edilebilir). İşte ilk birkaç Ulam numarası:

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

Bu kod golf, bu yüzden en kısa giriş kazanır.


Çıktı gösterildiği gibi olmalı mı (liste virgül ve boşlukla ayrılmış) mı yoksa örneğin bir dizi çıktısı alabilir miyiz?
Dennis

Ele nalmamız gereken minimum değer nedir ?
Dennis

1
@Dennis Space veya virgül ya da her ikisi de iyi. Minimum n değeri 1'dir.
Absinthe

Olduğu gibi, listemin etrafında parantez var. Bu da uygun mu yoksa kaldırmalı mıyım?
Dennis

1
@Dennis Parantezleri gayet iyi.
Absinthe

Yanıtlar:


10

CJam, 47 41 37 bayt

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

Çevrimiçi deneyin.

Örnek çalışma

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

Nasıl çalışır

Bu temel fikir şudur:

  1. Dizi ile başlayın A := [ 0 U₁ U₂ ... Uₖ ].

  2. Compute S, tüm toplamların dizisi x + yöyle x,y ∊ Ave x < y.

  3. Alanından benzersiz olmayan tüm tutarları atın S. 2'den büyük olan her Ulam numarası, hem daha küçük olanların toplamı hem de sıfır ile kendisinin toplamı olduğundan, bu Ulam sayılarını atar U₃, U₄, ... Uₖ.

  4. Kalan dizi [ U₁ U₂ Uₖ₊₁ ... ], dolayısıyla bir sonraki Ulam numarası üçüncü en küçük eleman. Bunu ekleyin Ave 1. adıma geri dönün.

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.                ";

Bir giriş 100zaten birkaç saniye sürüyor. Bence 1e5 maksimum girişinin yaşlanacağı hesaplanıyor?
Martin Ender

@ MartinBüttner: Java yorumlayıcısı çok daha hızlı, ancak yine de yavaş. Bütün kaba kuvvet algoritmaları O (n²) veya daha kötüdür. Diziler için yığın odaklı bir dil kullanmak hiçbir zaman hoş değildir (örneğin, dizilerin uzunluğunu hesaplamak tüm dizinin kopyalanmasını gerektirir), bu nedenle gerçek yürütme süresi muhtemelen O (n³) olur.
Dennis

1
@ MartinBüttner: WolframAlpha , yani 1e4 (neyse ki 1e5 değil) üç haftadan az sürmelidir.
Dennis

6

J - 46 karakter

Bağımsız ndeğişken olarak işlev alma .

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

Patlama ile açıklanıyor:

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

Orada +_*...
tomsmeding

6

T-SQL, 301 300 288 287

Biraz hafif SQL kötüye kullanımı yaptım.

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

Burada SQL Server 2008'de deneyin .

@N giriş tamsayısını tutar. "100" örneğini n olması gerektiği şekilde değiştirin. "10000" muhtemelen sonunda bitecek, ancak bunun tamamlanmasına izin vermedim. Bu girişin karakter sayısı tek haneli giriş içindir. Çıktı sorgu sonuç formunda.


5

Haskell, 70 67 karakter

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

kullanımı:

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

5

GolfScript ( 41 37 bayt)

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

Çevrimiçi demo

GolfScript'teki kartezyen ürünler oldukça uzundur, bu nedenle bu farklı bir yaklaşım gerektirir. Ulam sayılarının uzun vadeli büyümesi, nUlam sayısının yaklaşık olmasıdır 13.5n, ancak ilk 10000 nterimde , th Ulam numarası nile hemen altında olan en büyük orandır 13.3. Bu nedenle , diziye ait olanları bulmak niçin ilk 14nsayıları filtreleyebiliriz .

Dennis'e 41-> 37 için teşekkürler .


1
Bu oldukça hızlı. n = 1000GolfScript ile bir dakikadan az sürer; CJam limanının n = 10008 saniyede n = 100001 saat 20 m içinde tamamlanması . - Yaklaşımınızı benimki ile birleştirerek, yani diziye 0 ekleyerek ve daha sonra atayarak dört bayt kaydedebilirsiniz. Bu, blok yerine set birliğinin kullanılmasına izin verir ve bir değişkene olan ihtiyacı ortadan kaldırır:~.14*,4,\{1$.{2$1$-.@<*}%&,2=*|}/1><`
Dennis

@Dennis, CJam kaç karakter daha kısadır? İşlemlerin hiçbirinin daha uzun sürmediğini ve bunun için tek karakterlik bir takma adı olduğundan eminim 14.
Peter Taylor

Evet, 14sadece E. Ancak STDIN'den okumanız, set birliğini gerçekleştirmeden önce tamsayı tek bir tona dönüştürmeniz gerekir (bununla ilgili bir hata raporu göndereceğim) ve 2$CJam her yinelemeden sonra yığını değiştirdiğinden iç döngüde çalışmaz ... I Birkaç farklı püf noktası denedim, ancak en kısa olanı tam olarak 37 byte idi:li4,1$E*{__{I1$-_@<*}%&,2=I*a|}fI1><`
Dennis

5

JavaScript ES6, 100 ... 93 90 karakter

Bunu Web Konsolunda veya en son Firefox'un Scratchpad'inde çalıştırın (Nightly veya release).

EDIT 8 çok Golf! ve 94 karakter 93 90 karaktere düşürdü (@openorclose sayesinde). (İlk alt 100'üm)

İşte benim çok daha hızlı ama 3 karakter uzunluğunda (107 karakter) ve yukarıdaki ile aynı miktarda karakter olan ve aşağıdaki kaba kuvvet yönteminden çok daha küçük olan sürümüm !, (edc65 sayesinde):

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

Daha da golf yapmaya çalışacağım. Ama bunu JS: P kapsamı dışında sıkıyoruz

Bunu bir web sayfasındaki bir komut dosyası etiketinde çalıştırdığımda bazı rakamlar:

n kez
10 0.001
100 0.005
1000 2.021
10000 236.983
100000       bekleyen tldr; Çok uzun sürmedi: P

Bu, @ rink.attendant.6'nın JavaScript'teki cevabından ilham alan ilk sunumum.

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

Bunun daha da golf yapılabileceğini biliyorum. Ben de daha kaba olabilir bir kaba kuvvetli olmayan çözüm göndereceğiz.

EDIT 1 : Biraz daha golf ve n = 1 için sabit

Haskell ve J'yi her tür gereksinim için süper kullanışlı kısayollar için kıskandığımı söylemeliyim -_-


Haskell hakkında, fonksiyonel stil ve sözdizimi en çok fark (örneğin, iğrenç dev döngüler) düşünüyorum, işlevlerin miktarı her zaman güzel olmasına rağmen :-)
gururlu haskeller

1
Daha hızlı olanı daha fazla golf oynayabilir: (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]}ve belki daha da fazlası
edc65

1
1. Çift döngüden nasıl kaçındığınızı hala zar zor anlıyorum.Kudos 2.Golf ipucu: E6'da her zaman kaçınmaya çalışıyorum 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
Daha az karakter var: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

1
90 karakter: Bir 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 yerde [, 1] gerekmedikçe
openorclose 11:09

5

Perl - 71 bayt

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

Çevrimiçi deneyin!

Mesele bir olarak sayılıyor.
Toplamları saklamak için ikinci bir dizi kullanmak, bir karma değerinden önemli ölçüde daha hızlı görünüyor. Bellek kullanımı da daha az, bu da beklemiyordum.

Örnek kullanım:

$ echo 30 | perl ulam.pl

Örnek çıktı:

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

Yaklaşık çalışma süreleri:

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

2
8.6 s n == 1e4. İnanılmaz! İçin çıktı n == 1yanlış olsa da; tek bir sayı yazdırmalıdır.
Dennis

@Dennis şimdi düzeltildi.
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);}}

Kaba kuvvet bunun için iyi çalışır.

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. Sonucu yazdırmak için söz edilmeye değer Java 8 gerekiyor gibi görünüyor. 2. için çıktı 1tek bir sayı olmalıdır.
Dennis

1
Bu 10k'lık bir girişi ele alıyor mu?
Martin Ender

Döngüler için j ve k'nin parantez gerektirmediğine inanıyorum.
Michael Easter

Martin'in ifade ettiği gibi, ben de bu programın N = 10K için zamanlanmış yürütülmesini görmek istiyorum.
Michael Easter

4

APL (Genişletilmiş Dyalog) , 36 35 bayt

-1 byte Adám tarafından

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

Çevrimiçi deneyin!

{⍵↑{⍵,⊃∧(∊⊢⊆⍨⍧⍨∊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.

xxx2bir+bbirxbxbir=12bir+b{2,3}

* (Ngn / APL'de, bir sabit kullanmadan bir treni sonlandırabilir . Ancak ngn / APL'nin sayımı yoktur, bu yüzden ⍨ bir yere ihtiyacımız vardır.)


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

3

PHP 5.4+, 164

Cevaplarımla aynı yaklaşım:

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

Jöle , 20 bayt

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

Çevrimiçi deneyin!

Œ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

Son zamanlarda Golf JavaScript'i geliştirmek için CoffeeScript üzerinde çalışıyorum, bu yüzden CoffeeScript'te derlenen JavaScript yanıtım:

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]

CoffeeScript'teki döngüler ve kavrayışları çok iyi anlamıyorum , bu yüzden belki de daha fazla golf oynayabilir ama şimdilik sahip olduğum şey bu. Yeni satırlar bir karakter olarak sayılır (Unix stili).


2

JavaScript, 147 154 150 (136)

Daha önce yayınlanan @ Ypnypn'in kaba kuvvet Java çözümünden büyük ölçüde ilham aldı:

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

Orijinal versiyonumdan 4 ila 18 bayt tıraş ettiğin için @Dennis için teşekkürler

Tehlikeli sürüm ( for..indöngüler kullanılarak )

Döngüyü kullanan bir nesnenin içinden döngü yapmak , makinenizin alevlere dönüşmesine ve / veya kızgın bir öldürme makinesine dönüşmesine neden olabileceğinden bunu çalıştırmanızı önermem, ancak burada: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);
}

1 için çıktı bir singleton olmalıdır.
Dennis

@Dennis Teşekkürler, düzeltildi.
rink.attendant.6

1. z=0Döngünün içinde hareket ederseniz , sadece bir kez gerekir. 2. yaklaşımdan for(j in l)for(k in l)z+=l[j]<l[k]&l[j]+l[k]==i;çok daha kısadır l.forEach.
Dennis

2

Mathematica, 107 91 bayt

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

Spesifikasyonun doğrudan bir uygulamasıdır.

  • Tüm çiftleri bulun.
  • Tüm kopyaları silin.
  • Son Ulam numarasından küçük tüm numaraları silin.
  • Minimum değeri listeye ekleyin.

Ben de Dennis'in toplamları dahil etme hilesini uyguluyorum 0, ancak yakalama, bu, 0beklediğiniz gibi devam etmeden önce listenin üçüncü öğesini yapar , bu yüzden listeden bu öğeyi kaldırmam gerekiyor.

1000Birkaç saniye içinde bir girdi işler , ancak makul bir süre içinde 10k için bir sonuç alacağınızdan şüpheliyim. Ama diğerlerinin de bu konuda iyi performans gösterdiğini düşünmüyorum.


2

OCaml - 254 Karakter

Kod, listenin geçerli öğelerinin toplamını saklamak ve her yeni öğe hesaplandığında bunu güncellemek için bir karma tablo kullanır.

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]

Kullanımı:

OCaml tercümanı içinde:

# 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 karakter.

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

Bu benim ilk golfüm ve ~ 250 karakterden indirdim, oldukça mutluyum ama nasıl geliştirileceğine dair önerileri çok isterim!


Küçük, ama değerli: 5 ve 6 for b in U:t[a+b]+=a!=bsatırlarını ve 8 ve 9 satırlarını birleştirinwhile t[i]-2:i+=1
James Waldby - jwpat7

Önerin için teşekkürler! Ayrıca while döngüsünü bir dizine değiştirdim, ancak beklediğim kadar karakter kaydetmedi.
QuadmasterXLII

2 karakter daha: Init U to [1], ve 7. satırdan sonra gitfor
James Waldby - jwpat7

Hala değiştirerek 2 karakter kurtulabilirsiniz U,i=[1,2],2için U,i=[1],2ve input()-2için input()-1ve t=_*3*iiçin t=_*3*i;U+=[i]ve kaldır ;U+=[i]için sonunda
James Waldby - jwpat7

0

C #, 257

Kaba kuvvet yaklaşımı, LINQ kullanarak:

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

Test Demeti ile Ungolfed

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

Çok yavaş: n = 500 için 46s, n = 1000 için 6m, n = 2000 için 50m. Bu üssel oranda, n = 10K işlemenin 5 veya 6 gün süreceğine inanıyorum.
Richard II

0

Pyth, 27 25 bayt

<uaGh-sfq1lT.gksM.cG2GQS2

Burada çevrimiçi deneyin .

<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

Düzenleme: gruplamadan önce toplama yaparak 2 bayt golf. Önceki versiyon:<uaGh-mssdfq1lT.gsk.cG2GQS2


0

C, 478 bayt

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

Şimdi Tio'da 9 saniye içinde 10000 değer bulacaktı (ve orada ilk 100 değeri yazdırın). Hile, iç döngüde doğrusal arama değil, ikili arama kullanıyor ... Aşağıdakiler iyi girintili ve tam okunabilir işlevlerdir (sonunda benim için):

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

Bak, bir şeyi azaltabilir miyim ...
RosLuP

Bir şey bana golf programlamada sorun yok ama hepsi değil ...
RosLuP


@ceilingcat "z = k" benim için yanlış çünkü ikili arama (bs () fonksiyonu veya B () fonksiyonunuz) bana argüman aralıkları gibi görünüyor (doğru mu bilmiyorum ...) bin arama çağıran işlev z = k-1 olmalıdır
RosLuP

0

APL (NARS), 278 karakter, 556 bayt

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

Gönderdiğim C'nin APL'sindeki çeviri olurdu. Görünüşe göre, ∇ ... mümkün place yerine ∇∇ ne zaman kullanılacağını anlamıyorum, bir argüman bir işlev olduğunda (ve başka bir tür değil) kullanılır. "u bs x, a, b", "u" dizisindeki a..b aralığında "x" değeri için çöp kutusu araması olmalıdır; 1, indexWhereFind veya 0, indexWhereEndOfsearch döndürür. 200 p işlevi argümanıyla + - bir dakika burada ...

  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
∇∇bir dop içinde operatörün kendisini ifade ederken , operand (lar) ı ile operatörden oluşan türetilmiş fonksiyonu ifade eder. Yani, monadik bir operatörde , (⍺⍺∇∇)ikili bir operatördeki ile aynıdır (⍺⍺∇∇⍵⍵).
ADAM
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.