สร้างหมายเลข Ulam


19

ได้รับจำนวนเต็มn(ที่n < 10001) เป็น input เขียนโปรแกรมที่ออกจะเป็นครั้งแรกที่ตัวเลขลามn หมายเลข Ulam ถูกกำหนดดังนี้:

  1. U 1 = 1, U 22 =
  2. สำหรับn > 2U nเป็นจำนวนเต็มที่น้อยที่สุดซึ่งมากกว่า U n-1นั่นคือผลรวมของคำสองคำที่แตกต่างกันก่อนหน้านี้ในทางเดียว

ตัวอย่างเช่น U 3คือ3(2 + 1), U 4คือ4(3 + 1) (โปรดทราบว่า (2 + 2) ไม่นับเป็นเงื่อนไขที่ไม่ชัดเจน) และ U 5คือ6(U 5ไม่ใช่ 5 เนื่องจาก 5 สามารถแสดงเป็น 2 + 3 หรือ 4 + 1) นี่คือตัวเลข 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

นี่คือรหัสกอล์ฟดังนั้นรายการที่สั้นที่สุดชนะ


ผลลัพธ์จะต้องเป็นไปตามที่แสดง (รายการคั่นด้วยเครื่องหมายจุลภาคและช่องว่าง) หรือเราสามารถส่งออกเช่นอาร์เรย์ได้หรือไม่
เดนนิส

มูลค่าต่ำสุดที่nเราต้องรับมือคืออะไร
Dennis

1
@Dennis Space หรือเครื่องหมายจุลภาคหรือทั้งคู่ใช้ได้ ค่าต่ำสุดของ n คือ 1
absinthe

ตามที่ฉันมีวงเล็บรอบรายการของฉัน ตกลงเช่นกันหรือฉันควรลบออก
เดนนิส

1
@Dennis Brackets นั้นใช้ได้
absinthe

คำตอบ:


10

CJam, 47 41 37 ไบต์

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

ลองออนไลน์

ตัวอย่างการวิ่ง

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

มันทำงานอย่างไร

แนวคิดพื้นฐานนี้มีดังต่อไปนี้:

  1. A := [ 0 U₁ U₂ ... Uₖ ]เริ่มต้นด้วยอาร์เรย์

  2. Compute Sอาร์เรย์ของทุกสรุปx + yเช่นนั้นและx,y ∊ Ax < y

  3. Sยกเลิกทั้งหมดจำนวนเงินที่ไม่ซ้ำกันจาก เนื่องจากทุกจำนวนมากลามกว่า 2 U₃, U₄, ... Uₖเป็นทั้งผลรวมของทั้งสองคนเล็กและผลรวมของศูนย์และตัวเองทิ้งนี้ตัวเลขลาม

  4. อาร์เรย์ที่เหลือคือ[ U₁ U₂ Uₖ₊₁ ... ]ดังนั้นหมายเลข Ulam ถัดไปจึงเป็นองค์ประกอบที่เล็กที่สุดที่สาม ผนวกเข้ากับAและย้อนกลับไปที่ขั้นตอนที่ 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.                ";

อินพุตของ100ใช้เวลาหลายวินาทีแล้ว ฉันคิดว่าการป้อนข้อมูลสูงสุด 1e5 จะใช้เวลานานไหม?
Martin Ender

@ MartinBüttner: ล่าม Java เร็วกว่าเยอะ แต่ก็ยังช้าอยู่ อัลกอริทึมแรงเดรัจฉานทั้งหมดคือ O (n²) หรือแย่กว่านั้น การใช้ภาษาสแต็กสำหรับอาเรย์นั้นไม่เคยสวยเลย (เช่นการคำนวณความยาวของอาเรย์ต้องคัดลอกทั้งอาเรย์) ดังนั้นเวลาดำเนินการจริงอาจเป็น O (n³)
เดนนิส

1
@ MartinBüttner: WolframAlphaดังนั้น 1e4 (ขอบคุณไม่ใช่ 1e5) ควรใช้เวลาน้อยกว่าสามสัปดาห์
เดนนิส

6

J - 46 ตัวอักษร

ฟังก์ชั่นรับnเป็นอาร์กิวเมนต์

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

อธิบายโดยการระเบิด:

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

ฉันได้ล่วงละเมิด 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

ลองมันใน SQL Server 2008 ที่นี่

@N เก็บจำนวนเต็มเข้า เปลี่ยนตัวอย่าง "100" เป็นสิ่งที่ n ควรเป็น "10000" อาจจะเสร็จสิ้นในที่สุด แต่ฉันก็ไม่ได้ปล่อยให้มันทำสำเร็จ จำนวนถ่านของรายการนี้ใช้สำหรับการป้อนหนึ่งหลัก เอาต์พุตอยู่ในรูปแบบผลลัพธ์แบบสอบถาม



5

GolfScript ( 41 37 ไบต์)

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

การสาธิตออนไลน์

ผลิตภัณฑ์คาร์ทีเซียนใน GolfScript ค่อนข้างยาวดังนั้นวิธีนี้จึงแตกต่างกัน การเจริญเติบโตในระยะยาวของตัวเลขลามเป็นที่nTH ลามเป็นเรื่องเกี่ยวกับตัวเลข13.5nแต่ในแง่ 10000 แรกอัตราส่วนที่ยิ่งใหญ่ที่สุดระหว่างnวันที่จำนวนลามและเป็นเพียงภายใต้n 13.3เพราะnเราสามารถกรองแรก14nตัวเลขเพื่อค้นหาหมายเลขที่อยู่ในลำดับ

ด้วยความขอบคุณจากDennis ที่ 41-> 37


1
อันนี้ค่อนข้างเร็ว n = 1000ใช้เวลาไม่ถึงนาทีด้วย GolfScript พอร์ตไปยัง CJam เสร็จสมบูรณ์n = 1000ใน 8 วินาทีและn = 10000ใน 1 ชม. 20 เมตร - คุณสามารถบันทึกสี่ไบต์ด้วยการรวมวิธีการของคุณกับของฉันซึ่งรวมถึง 0 ในอาร์เรย์และทิ้งหลังจากนั้น ที่ช่วยให้การใช้ชุดยูเนี่ยนแทนบล็อกและขจัดความต้องการตัวแปร:~.14*,4,\{1$.{2$1$-.@<*}%&,2=*|}/1><`
เดนนิส

@Dennis, CJam สั้นลงกี่ตัวอักษร? ฉันคิดว่าไม่มีการดำเนินการใดที่จะใช้เวลานานขึ้นและฉันค่อนข้างแน่ใจว่ามันมีนามแฝงแบบตัวอักษร14เดียว
Peter Taylor

ใช่เป็นเพียง14 Eแต่คุณต้องอ่านจาก STDIN, แปลงจำนวนเต็มเป็นซิงเกิลตันก่อนที่จะทำการเซ็ตยูเนี่ยน (ฉันจะส่งรายงานข้อผิดพลาดเกี่ยวกับเรื่องนั้น) และ2$จะไม่ทำงานในลูปด้านในเนื่องจาก CJam แก้ไขสแต็คหลังการทำซ้ำแต่ละครั้ง ... 'ได้พยายามเทคนิคที่แตกต่างกัน แต่อย่างใดอย่างหนึ่งที่สั้นที่สุดตรง 37 ไบต์:li4,1$E*{__{I1$-_@<*}%&,2=I*a|}fI1><`
เดนนิส

5

JavaScript ES6, 100 ... 93 90 ตัวอักษร

รันสิ่งนี้ใน Web Console หรือ Scratchpad ของ Firefox ล่าสุด (ทุกคืนหรือทุกรุ่น)

แก้ไข 8 Golfed มาก !!! และทำให้มันลดลงเหลือ94 ตัวอักษร 93 90 ตัวอักษร (ขอบคุณ @openorclose) (ย่อยแรกของฉัน 100)

นี่คือเวอร์ชั่นของฉันซึ่งเร็วกว่ามากแต่ยาวกว่า 3 ตัวอักษร (107 ตัวอักษร) และมีจำนวนเท่ากันกับที่กล่าวไว้ข้างต้นและมีขนาดเล็กกว่าวิธีบังคับเดรัจฉานด้านล่าง!, (ขอบคุณ 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

ฉันจะพยายามตีกอล์ฟต่อไป แต่เรากำลังบีบมันออกจากขอบเขตของ JS: P

นี่คือตัวเลขบางส่วนเมื่อฉันเรียกใช้ภายในแท็กสคริปต์ในหน้าเว็บ:

ไม่มีเวลา
10 0.001
100 0.005
1,000 2.021
10000 236.983tldr ที่รอดำเนินการ 
100000      ไม่ยาวเกินไป: P

นี่คือการส่งครั้งแรกของฉันซึ่งเป็นแรงบันดาลใจอย่างมากจากคำตอบของ @ rink.attendant.6 ใน 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]}

ฉันรู้ว่านี่สามารถเล่นกอล์ฟได้ดียิ่งขึ้น ฉันจะโพสต์โซลูชันที่ไม่ใช้ความรุนแรงซึ่งอาจจะสั้นกว่าด้วย

แก้ไข 1 : Golfed อีกเล็กน้อยและคงที่สำหรับ n = 1

ฉันต้องบอกว่าฉันอิจฉา Haskell และ J สำหรับทางลัดที่มีประโยชน์สุด ๆ สำหรับความต้องการทุกประเภท -_-


เกี่ยวกับ Haskell ฉันคิดว่าสไตล์การใช้งานและไวยากรณ์สร้างความแตกต่างได้มากที่สุด (ตัวอย่างเช่นไม่มีลูปยักษ์ที่น่ากลัว) แม้ว่าจำนวนฟังก์ชั่นจะดีเสมอ :-)
ภูมิใจ haskeller

1
ผู้ที่เร็วกว่านี้สามารถตีกอล์ฟได้มากขึ้นแน่นอน: (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]}และอาจมากยิ่งขึ้น
edc65

1
1. ฉันยังคงแทบจะไม่เข้าใจว่าคุณหลีกเลี่ยงการวนซ้ำสองครั้งได้อย่างไรคำแนะนำของกอล์ฟ: ใน E6 ฉันพยายามหลีกเลี่ยง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
มีถ่านหนึ่งตัวน้อยกว่า: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 ตัวอักษร: 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 ถ้าต้องการ [, 1] ที่ไหนสักแห่ง
openorclose

5

Perl - 71 ไบต์

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

ลองออนไลน์!

นับ Shebang เป็นหนึ่งเดียว
การใช้อาเรย์ที่สองเพื่อเก็บผลรวมนั้นดูเหมือนจะเร็วกว่าแฮชอย่างมาก การใช้หน่วยความจำก็น้อยลงเช่นกันซึ่งฉันไม่คาดคิด

ตัวอย่างการใช้งาน:

$ echo 30 | perl ulam.pl

ตัวอย่างผลลัพธ์:

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

เวลารันไทม์โดยประมาณ:

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

2
8.6 n == 1e4สำหรับ ! ที่น่าตื่นตาตื่นใจ ผลลัพธ์สำหรับn == 1ไม่ถูกต้องแม้ว่า; ควรพิมพ์หมายเลขเดียว
เดนนิส

@Dennis ได้รับการแก้ไขแล้ว
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);}}

กำลังดุร้ายทำงานได้ดีสำหรับเรื่องนี้

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. การพิมพ์ผลลัพธ์ดูเหมือนว่าต้องใช้ Java 8 ซึ่งอาจคุ้มค่าที่จะกล่าวถึง 2. ผลลัพธ์สำหรับ1ควรเป็นตัวเลขเดียว
เดนนิส

1
สิ่งนี้จัดการอินพุต 10k หรือไม่?
Martin Ender

ฉันเชื่อว่า j และ k สำหรับลูปไม่จำเป็นต้องใช้เครื่องมือจัดฟัน
Michael Easter

ตามที่มาร์ตินบอกเป็นนัยฉันก็อยากจะเห็นการดำเนินการตามกำหนดเวลาของโปรแกรมนี้สำหรับ N = 10K
Michael Easter

4

APL (Dyalog Extended) , 36 35 ไบต์

-1 ไบต์โดยAdám

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

ลองออนไลน์!

{⍵↑{⍵,⊃∧(∊⊢⊆⍨⍧⍨∊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+axxa=12a+{2,3}

* (ใน ngn / APL ค่าคงที่สามารถจบขบวนรถไฟได้โดยไม่ต้องใช้แต่ ngn / APL ไม่มีการนับเข้าดังนั้นเราต้องการ⍨ที่ไหนสักแห่ง)


{(2 3∊⍨⍵⍧⍵)/⍵}(∊⊢⊆⍨⍧⍨∊2 3⍨)
อดัม

3

PHP 5.4+, 164

วิธีการเช่นเดียวกับคำตอบของฉัน:

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

เยลลี่ , 20 ไบต์

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

ลองออนไลน์!

Œ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

เมื่อเร็ว ๆ นี้ฉันได้ฝึกซ้อม CoffeeScript เพื่อพัฒนาจาวาสคริปต์ดังนั้นนี่คือคำตอบ JavaScript ของฉันที่คอมไพล์เป็น 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]

ฉันไม่เข้าใจลูปและความเข้าใจใน CoffeeScriptเป็นอย่างดีดังนั้นบางทีนี่อาจจะสามารถตีกอล์ฟต่อไปได้ แต่มันเป็นสิ่งที่ฉันมีในตอนนี้ การขึ้นบรรทัดใหม่จะถูกนับเป็นหนึ่งอักขระ (สไตล์ Unix)


2

JavaScript, 147 154 150 (136)

แรงบันดาลใจอย่างมากจากโซลูชัน Java brute-force Java @ Ypnypn ที่โพสต์ก่อนหน้านี้:

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

ขอบคุณ @Dennis ที่โกนหนวด 4 ถึง 18 ไบท์จากเวอร์ชั่นดั้งเดิมของฉัน

รุ่นอันตราย (ใช้for..inลูป)

ฉันไม่แนะนำให้ใช้สิ่งนี้เพราะการวนลูปผ่านวัตถุที่ใช้ลูปอาจทำให้เครื่องของคุณระเบิดเป็นเปลวไฟและ / หรือเปลี่ยนเป็นเครื่องฆ่าที่โกรธ แต่นี่คือ: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 ควรเป็นแบบซิงเกิล
เดนนิส

@Dennis ขอบคุณแก้ไขแล้ว
rink.attendant.6

1. ถ้าคุณย้ายz=0เข้าไปในวงคุณต้องการเพียงครั้งเดียว 2. for(j in l)for(k in l)z+=l[j]<l[k]&l[j]+l[k]==i;สั้นกว่าl.forEachวิธีการมาก
เดนนิส

2

Mathematica, 107 91 ไบต์

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

เป็นการใช้งานข้อมูลจำเพาะโดยตรง

  • ค้นหาคู่ทั้งหมด
  • ลบรายการซ้ำทั้งหมด
  • ลบหมายเลขทั้งหมดน้อยกว่าหมายเลข Ulam ล่าสุด
  • ผนวกขั้นต่ำไปยังรายการ

ฉันยังใช้เคล็ดลับของเดนนิสในการรวมจำนวนเงินด้วย0แต่การจับคือสิ่งนี้ทำให้องค์ประกอบที่สามของรายการ0ก่อนที่จะกลับมาทำงานอย่างที่คาดหวังดังนั้นฉันต้องลบองค์ประกอบนั้นออกจากรายการ

มันจัดการอินพุตได้1000ในไม่กี่วินาที แต่ฉันสงสัยว่าคุณจะได้ผลลัพธ์ 10k ภายในระยะเวลาที่เหมาะสม แต่ฉันไม่คิดว่าคนอื่นจะทำงานได้ดีนัก


2

OCaml - 254 ตัวละคร

รหัสใช้ตารางแฮชเพื่อจัดเก็บผลรวมขององค์ประกอบปัจจุบันของรายการและอัปเดตทุกครั้งที่มีการคำนวณองค์ประกอบใหม่

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]

การใช้งาน:

ภายในล่าม 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 ตัวอักษร

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

นี่คือสนามกอล์ฟครั้งแรกของฉันและฉันได้นำมันลงมาจาก ~ 250 ตัวอักษรฉันมีความสุขมาก แต่ชอบที่จะแนะนำวิธีการปรับปรุง!


ผู้เยาว์ แต่ก็คุ้มค่า: รวม 5 และ 6 เข้าด้วยกันกับfor b in U:t[a+b]+=a!=b8 และ 9 ถึงwhile t[i]-2:i+=1
James Waldby - jwpat7

ขอบคุณสำหรับคำแนะนำ! ฉันยังเปลี่ยน while loop เป็นดัชนี แต่ไม่ได้บันทึกตัวละครมากเท่าที่ฉันคาดไว้
QuadmasterXLII

อีก 2 ตัวอักษร: เริ่มต้น U ถึง [1] และย้ายบรรทัดที่ 7 ถึงหลังfor
James Waldby - jwpat7

คุณยังสามารถกำจัด 2 chars ได้โดยเปลี่ยนU,i=[1,2],2เป็นU,i=[1],2and input()-2to input()-1และt=_*3*ito t=_*3*i;U+=[i]and remove ;U+=[i]เมื่อสิ้นสุดการ
James Waldby - jwpat7

0

C #, 257

กำลังดุร้ายวิธีใช้ 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 พร้อมชุดทดสอบ

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

ช้ามาก: 46 วินาทีสำหรับ n = 500, 6m สำหรับ n = 1,000, 50m สำหรับ n = 2000 ในอัตราเลขยกกำลังนั้นฉันเชื่อว่าจะใช้เวลา 5 หรือ 6 วันในการประมวลผล n = 10K
Richard II

0

Pyth, 27 25 ไบต์

<uaGh-sfq1lT.gksM.cG2GQS2

ลองออนไลน์ได้ที่นี่ที่นี่

<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

แก้ไข: golfed 2 ไบต์โดยดำเนินการผลรวมก่อนการจัดกลุ่ม รุ่นก่อนหน้า:<uaGh-mssdfq1lT.gsk.cG2GQS2


0

C, 478 ไบต์

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

ใน Tio ในเวลา 9 วินาทีมันจะหาค่า 10,000 ค่า (และในนั้นจะพิมพ์ 100 ค่าแรก) เคล็ดลับคือการใช้การค้นหาแบบไม่เชิงเส้นในลูปด้านใน แต่เป็นการค้นหาแบบไบนารี่ ... ด้านล่างนี้มีฟังก์ชั่นการเยื้องและอ่านได้อย่างสมบูรณ์ (ในที่สุดสำหรับฉัน):

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

ดูว่าฉันสามารถลดบางสิ่งได้
ไหม

มีบางอย่างบอกฉันว่าในการเขียนโปรแกรมการเล่นกอล์ฟก็โอเค แต่มันก็ไม่ใช่ทั้งหมด ...
RosLuP


@ceilingcat "z = k" สำหรับฉันผิดเพราะฟังก์ชั่นการค้นหาแบบไบนารี (bs () หรือฟังก์ชั่น B () ของคุณ) ดูเหมือนว่าฉันต้องการเป็นช่วงอาร์กิวเมนต์ (ฉันไม่รู้ว่ามันถูกเกินไป ... ) ดังนั้นใน ฟังก์ชั่นที่เรียกการค้นหา bin จะต้องเป็น z = k-1
RosLuP

0

APL (NARS), 278 ถ่าน, 556 ไบต์

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

มันจะเป็นการแปลใน APL ของ C หนึ่งที่ฉันส่งไป ดูเหมือนว่าฉันไม่เข้าใจเมื่อใช้∇∇แทนที่∇∇ ... เป็นไปได้∇∇จะใช้เมื่อมีอาร์กิวเมนต์หนึ่งคือฟังก์ชันหนึ่ง (ไม่ใช่ประเภทอื่น) "u bs x, a, b" ควรเป็นการค้นหา bin ในอาร์เรย์ "u" สำหรับค่า "x" ในช่วง a..b; มันจะคืนค่า 1, ดัชนีดัชนีค้นหาหรือ 0, ดัชนีดัชนีดัชนีค้นหา ด้วยอาร์กิวเมนต์ 200 p ฟังก์ชั่นใช้เวลา - นาทีที่นี่ ...

  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
∇∇ใน dop หมายถึงตัวดำเนินการเองในขณะที่อ้างอิงถึงฟังก์ชันที่ได้รับซึ่งประกอบด้วยตัวดำเนินการที่มีตัวถูกดำเนินการ ดังนั้นในการเป็นผู้ประกอบการเอกเป็นเช่นเดียวกับ(⍺⍺∇∇)ในขณะที่ผู้ประกอบการ dyadic (⍺⍺∇∇⍵⍵)มันหมายถึง
อดัม
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.