Tạo số Ulam


19

Cho một số nguyên n(trong đó n < 10001) làm đầu vào, viết chương trình sẽ xuất các n số Ulam đầu tiên . Một số Ulam được định nghĩa như sau:

  1. U 1 = 1, U 2 = 2.
  2. n > 2, U n là số nguyên nhỏ nhất lớn hơn U n-1 , là tổng của hai số hạng khác nhau trước đó theo đúng một cách.

Ví dụ: U 33(2 + 1), U 44(3 + 1) (lưu ý rằng (2 + 2) không được tính là các thuật ngữ không khác biệt) và U 56, (U 5 không phải là 5 bởi vì 5 có thể được biểu diễn dưới dạng 2 + 3 hoặc 4 + 1). Dưới đây là một vài số Ulam đầu tiên:

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

Đây là mã golf, vì vậy mục ngắn nhất sẽ thắng.


Có phải đầu ra phải như được hiển thị (danh sách được phân tách bằng dấu phẩy và dấu cách) hoặc chúng ta có thể xuất ví dụ, một mảng không?
Dennis

Giá trị tối thiểu của nchúng ta phải xử lý là gì?
Dennis

1
@Dennis Space hoặc dấu phẩy hoặc cả hai đều tốt. Giá trị tối thiểu của n là 1.
absinthe

Như nó là, tôi có dấu ngoặc quanh danh sách của tôi. Điều đó có ổn không hay tôi nên loại bỏ chúng?
Dennis

1
@Dennis Chân đế vẫn ổn.
absinthe

Câu trả lời:


10

CJam, 47 41 37 byte

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

Hãy thử trực tuyến.

Chạy ví dụ

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

Làm thế nào nó hoạt động

Ý tưởng cơ bản này là như sau:

  1. Bắt đầu với mảng A := [ 0 U₁ U₂ ... Uₖ ].

  2. Tính toán S, mảng của tất cả các khoản tiền x + ynhư vậy x,y ∊ Ax < y.

  3. Hủy tất cả các khoản tiền không phải là duy nhất từ S. Vì mỗi số Ulam lớn hơn 2 đều là tổng của hai số nhỏ hơn và tổng bằng 0 và chính nó, điều này loại bỏ các số Ulam U₃, U₄, ... Uₖ.

  4. Mảng còn lại là [ U₁ U₂ Uₖ₊₁ ... ], vì vậy số Ulam tiếp theo là phần tử nhỏ thứ ba. Nối nó vào Avà quay lại bước 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.                ";

Một đầu vào 100đã mất vài giây. Tôi cho rằng tính toán tối đa 1e5 đầu vào sẽ mất bao lâu?
Martin Ender

@ MartinBüttner: Trình thông dịch Java nhanh hơn rất nhiều, nhưng nó vẫn chậm. Tất cả các thuật toán brute-force là O (n²) hoặc tệ hơn. Sử dụng ngôn ngữ hướng ngăn xếp cho mảng không bao giờ đẹp (ví dụ: tính toán độ dài mảng yêu cầu sao chép toàn bộ mảng), vì vậy thời gian thực hiện thực tế có lẽ là O (n³).
Dennis

1
@ MartinBüttner: WolframAlpha , vì vậy 1e4 (rất may, không phải 1e5) sẽ mất ít hơn ba tuần.
Dennis

6

J - 46 char

Hàm lấy nlàm đối số.

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

Giải thích bằng vụ nổ:

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

6

T-SQL, 301 300 288 287

Tôi đã phạm một chút lạm dụng SQL nhẹ.

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

Hãy thử nó trong SQL Server 2008 tại đây .

@N giữ số nguyên đầu vào. Thay đổi ví dụ "100" thành n nên. "10000" cuối cùng có thể sẽ hoàn thành, nhưng tôi đã không để nó chạy đến khi hoàn thành. Số char của mục này dành cho đầu vào một chữ số. Đầu ra ở dạng kết quả truy vấn.



5

GolfScript ( 41 37 byte)

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

Bản demo trực tuyến

Các sản phẩm của Cartesian trong GolfScript khá dài, vì vậy điều này cần một cách tiếp cận khác. Sự tăng trưởng dài hạn của các số Ulam là nsố Ulam thứ năm 13.5n, nhưng trong 10000 điều khoản đầu tiên, tỷ lệ lớn nhất giữa nsố Ulam thứ và nchỉ nằm dưới 13.3. Vì vậy, nchúng ta có thể lọc các 14nsố đầu tiên để tìm các số thuộc chuỗi.

Cảm ơn Dennis vì 41-> 37.


1
Điều này khá nhanh. n = 1000mất dưới một phút với GolfScript; một cổng đến CJam hoàn thành n = 1000trong 8 giây và n = 10000trong 1h 20 m. - Bạn có thể lưu bốn byte bằng cách kết hợp cách tiếp cận của bạn với của tôi, cụ thể là bao gồm 0 trong mảng và loại bỏ nó sau đó. Điều đó cho phép sử dụng tập hợp thay vì khối và loại bỏ sự cần thiết của một biến:~.14*,4,\{1$.{2$1$-.@<*}%&,2=*|}/1><`
Dennis

@Dennis, CJam có bao nhiêu ký tự ngắn hơn? Tôi cho rằng không có thao tác nào dài hơn và tôi khá chắc chắn rằng nó có bí danh một char cho 14.
Peter Taylor

Vâng, 14chỉ là E. Nhưng bạn cần đọc từ STDIN, chuyển đổi số nguyên thành số đơn trước khi thực hiện tập hợp (tôi sẽ gửi báo cáo lỗi về điều đó) và 2$sẽ không hoạt động trong vòng lặp bên trong vì CJam sửa đổi ngăn xếp sau mỗi lần lặp ... Tôi Tôi đã thử một số thủ thuật khác nhau, nhưng thủ thuật ngắn nhất chính xác là 37 byte:li4,1$E*{__{I1$-_@<*}%&,2=I*a|}fI1><`
Dennis

5

JavaScript ES6, 100 ... 93 90 ký tự

Chạy cái này trong Web Console hoặc Scratchpad của Firefox mới nhất (Hàng đêm hoặc phát hành).

EDIT 8 đã chơi golf rất nhiều !!! và giảm xuống 94 ký tự 93 90 ký tự (nhờ @openorclose). (Tiểu 100 đầu tiên của tôi)

Đây là phiên bản của tôi nhanh hơn nhiều nhưng dài hơn 3 ký tự (107 ký tự) và chính xác cùng số lượng ký tự như trên và nhỏ hơn nhiều so với phương pháp vũ phu dưới đây!, (Nhờ 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

Tôi sẽ tiếp tục cố gắng để chơi golf hơn nữa. Nhưng chúng tôi đang ép nó ra khỏi phạm vi của JS: P

Dưới đây là một số con số khi tôi chạy mã này trong thẻ script trong trang web:

n thời gian
10 0,001
100 0,005
1000 2.021
10000 236.983
100000       tldr đang chờ xử lý ; Quá lâu không chạy: P

Đây là lần gửi đầu tiên của tôi, được truyền cảm hứng rất nhiều từ câu trả lời của @ rink.attguard.6 trong 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]}

Tôi biết điều này có thể được chơi golf hơn nữa. Tôi cũng sẽ đăng một giải pháp không bruteforced, mà có thể còn ngắn hơn.

EDIT 1 : Chơi gôn nhiều hơn một chút và cố định cho n = 1

Tôi phải nói rằng tôi ghen tị với Haskell và J vì những phím tắt siêu tiện dụng như vậy cho mọi loại yêu cầu -_-


về Haskell, tôi nghĩ rằng phong cách chức năng và cú pháp tạo ra sự khác biệt lớn nhất (ví dụ, không có vòng lặp khổng lồ gớm ghiếc), mặc dù số lượng chức năng luôn luôn tốt :-)
tự hào

1
Người nhanh hơn chắc chắn có thể chơi gôn nhiều hơn: (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]}và thậm chí có thể nhiều hơn
edc65

1
1. Tôi vẫn hầu như không hiểu làm thế nào bạn tránh được vòng lặp kép.Kudos 2. Mẹo của Grolf: trong E6 tôi luôn cố gắng tránh 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ó một char ít hơn: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
openorc Đóng

1
90 ký tự: 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 Trừ khi [, 1] là cần thiết ở đâu đó
openorclose

5

Perl - 71 byte

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

Hãy thử trực tuyến!

Đếm số shebang là một.
Sử dụng một mảng thứ hai để lưu trữ các khoản tiền dường như nhanh hơn đáng kể so với hàm băm. Việc sử dụng bộ nhớ cũng ít hơn, điều mà tôi không mong đợi.

Sử dụng mẫu:

$ echo 30 | perl ulam.pl

Đầu ra mẫu:

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

Thời gian chạy gần đúng:

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

2
8,6 s cho n == 1e4. Kinh ngạc! Đầu ra cho n == 1là không chính xác mặc dù; cần in một số.
Dennis

@Dennis giờ đã sửa.
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);}}

Lực lượng vũ phu hoạt động tốt cho việc này.

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. In kết quả dường như yêu cầu Java 8, có thể đáng được đề cập. 2. Đầu ra cho 1nên là một số duy nhất.
Dennis

1
Điều này có xử lý đầu vào 10k không?
Martin Ender

Tôi tin rằng j và k cho các vòng lặp không cần niềng răng.
Michael Easter

Như Martin ngụ ý, tôi cũng muốn thấy một thời gian thực hiện chương trình này với giá trị N = 10K.
Michael Easter

4

APL (Dyalog mở rộng) , 36 35 byte

-1 byte bởi Adám

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

Hãy thử trực tuyến!

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

xxx2a+baxbxa=12a+b{2,3}

* (Trong ngn / APL, hằng số có thể kết thúc một chuyến tàu mà không cần sử dụng . Nhưng ngn / APL không có tính năng đếm số, vì vậy chúng tôi cần ở đâu đó.)


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

3

PHP 5,4+, 164

Cách tiếp cận tương tự như câu trả lời của tôi:

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

Thạch , 20 byte

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

Hãy thử trực tuyến!

Œ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

Cà phê, 119 114

Gần đây tôi đã thực hành CoffeeScript để cải thiện việc chơi golf JavaScript, vì vậy đây là câu trả lời JavaScript của tôi được biên dịch thành 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]

Tôi không hiểu rõ về các vòng lặp và sự hiểu biết trong CoffeeScript vì vậy có lẽ điều này có thể được đánh gôn hơn nữa nhưng đó là những gì tôi có cho đến bây giờ. Dòng mới được tính là một ký tự (kiểu Unix).


2

JavaScript, 147 154 150 (136)

Lấy cảm hứng mạnh mẽ từ giải pháp Java vũ phu của @ Ypnypn đã đăng trước đó:

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

Cảm ơn @Dennis vì đã cạo 4 đến 18 byte khỏi phiên bản gốc của tôi

Phiên bản nguy hiểm (sử dụng for..invòng lặp)

Tôi không khuyên bạn nên chạy cái này bởi vì việc lặp qua một đối tượng sử dụng vòng lặp có thể khiến máy của bạn bùng cháy và / hoặc biến thành một cỗ máy giết người tức giận, nhưng đây là: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)}

Bị đánh cắp

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

Đầu ra cho 1 phải là một singleton.
Dennis

@Dennis Cảm ơn, đã sửa.
rink.attguard.6

1. Nếu bạn di chuyển z=0bên trong vòng lặp, bạn chỉ cần một lần. 2. for(j in l)for(k in l)z+=l[j]<l[k]&l[j]+l[k]==i;ngắn hơn rất nhiều so với l.forEachcách tiếp cận.
Dennis

2

Toán học, 107 91 byte

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

Đó là một thực hiện rất trực tiếp của thông số kỹ thuật.

  • Tìm tất cả các cặp.
  • Xóa tất cả các bản sao.
  • Xóa tất cả các số ít hơn số Ulam cuối cùng.
  • Nối tối thiểu vào danh sách.

Tôi cũng đang áp dụng thủ thuật bao gồm các khoản tiền của Dennis 0, nhưng điều thú vị là điều này làm cho yếu tố thứ ba của danh sách 0trước khi tiếp tục như mong đợi, vì vậy tôi cần xóa yếu tố đó khỏi danh sách.

Nó xử lý đầu vào 1000trong vài giây, nhưng tôi nghi ngờ rằng bạn sẽ nhận được kết quả với giá 10 nghìn trong một khoảng thời gian hợp lý. Nhưng tôi cũng không nghĩ bất kỳ ai trong số những người khác thực hiện tốt điều đó.


2

OCaml - 254 ký tự

Mã sử ​​dụng bảng băm để lưu trữ tổng các phần tử hiện tại của danh sách và cập nhật nó mỗi khi một phần tử mới được tính toán.

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]

Sử dụng:

Trong phiên dịch 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]

Bị đánh cắp

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

Con trăn, 137 128 126 ký tự.

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

Đây là môn đánh gôn đầu tiên của tôi và tôi đã hạ nó xuống từ ~ 250 ký tự, tôi khá vui nhưng rất thích những gợi ý về cách cải thiện!


Nhỏ, nhưng đáng giá: kết hợp các dòng 5 & 6 đến for b in U:t[a+b]+=a!=bvà dòng 8 & 9 đếnwhile t[i]-2:i+=1
James Waldby - jwpat7

Cám ơn vì sự gợi ý! Tôi cũng đã thay đổi vòng lặp while thành một chỉ mục nhưng nó không lưu được nhiều ký tự như tôi mong đợi.
QuadmasterXLII

Thêm 2 ký tự: init U thành [1] và chuyển dòng 7 sang saufor
James Waldby - jwpat7

Bạn vẫn có thể thoát khỏi 2 chars bằng cách thay đổi U,i=[1,2],2để U,i=[1],2input()-2để input()-1t=_*3*iđể t=_*3*i;U+=[i]và loại bỏ ;U+=[i]vào cuối cho
James Waldby - jwpat7

0

C #, 257

Phương pháp tiếp cận mạnh mẽ, sử dụng 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, với thử nghiệm khai thác

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

Rất chậm: 46s cho n = 500, 6m cho n = 1000, 50m cho n = 2000. Với tốc độ theo cấp số nhân đó, tôi tin rằng sẽ mất 5 hoặc 6 ngày để xử lý n = 10K.
Richard II

0

Bình thường, 27 25 byte

<uaGh-sfq1lT.gksM.cG2GQS2

Hãy thử trực tuyến tại đây .

<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

Chỉnh sửa: đánh gôn 2 byte bằng cách thực hiện tính tổng trước khi nhóm. Phiên bản trước:<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;}

Trong Tio bây giờ trong 9 giây, nó sẽ tìm thấy 10000 giá trị (và trong đó in 100 giá trị đầu tiên). Thủ thuật là sử dụng không phải tìm kiếm tuyến tính trong vòng lặp bên trong mà là tìm kiếm nhị phân ... Đây là những chức năng được thụt lề và có thể đọc đầy đủ (cuối cùng đối với tôi):

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

Xem liệu tôi có thể giảm thứ gì đó không ...
RosLuP

Một cái gì đó nói với tôi rằng trong lập trình golf là ổn nhưng nó không phải là tất cả ...
RosLuP


@ceilingcat "z = k" đối với tôi là sai vì hàm tìm kiếm nhị phân (hàm bs () hoặc hàm B () của bạn dường như muốn làm phạm vi đối số (tôi không biết liệu nó có đúng không ...) hàm gọi bin tìm kiếm phải là z = k-1
RosLuP

0

APL (NARS), 278 char, 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
∇

nó sẽ là bản dịch bằng APL của C mà tôi đã gửi. Có vẻ như tôi không hiểu khi nào sử dụng ∇∇ thay cho ∇ ... có thể được sử dụng khi có một đối số là một hàm (và không phải là một loại khác). "u bs x, a, b" phải là tìm kiếm bin trong mảng "u" cho giá trị "x" trong phạm vi a..b; nó sẽ trả về 1, indexWhereFind hoặc 0, indexWhereEndOfsearch. Với đối số 200 p hàm mất + - một phút ở đây ...

  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
∇∇trong một dop đề cập đến chính toán tử trong khi đề cập đến hàm dẫn xuất bao gồm toán tử với (các) toán hạng của nó. Vì vậy, trong một toán tử đơn âm cũng giống như (⍺⍺∇∇)trong một toán tử dyadic có nghĩa là (⍺⍺∇∇⍵⍵).
Adám
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.