Створення Улам чисел


19

Враховуючи ціле число n(де n < 10001), введіть програму, яка виведе перші n числа Ulam . Номер Ulam визначається наступним чином:

  1. U 1 = 1, U 2 = 2.
  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ми маємо обробити?
Денніс

1
@ Денніс Пробіл, кома або те й інше - це добре. Мінімальне значення n дорівнює 1.
абсент

Як є, у мене в списку є дужки. Це теж добре, або я повинен їх видалити?
Денніс

1
@Dennis Brackets нормально.
абсент

Відповіді:


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. Обчисліть S, масив усіх сум x + yтаких, що x,y ∊ Aі x < 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 зайняло б віки?
Мартін Ендер

@ 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

Haskell, 70 67 символів

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

використання:

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

5

GolfScript ( 41 37 байт)

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

Демонстрація в Інтернеті

Декартові продукти в GolfScript досить довгі, тому для цього потрібен інший підхід. Довгострокове зростання чисел Улама полягає в тому, що nчисло Ulam становить приблизно 13.5n, але в перших 10000 термінах найбільше співвідношення між nчислом Улама і nтрохи нижче 13.3. Отже, враховуючи, що nми можемо відфільтрувати перші 14nчисла, щоб знайти ті, що належать до послідовності.

З подякою Деннісу за 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.
Пітер Тейлор

Так, 14просто E. Але вам потрібно прочитати з STDIN, перетворити ціле число в синглтон перед виконанням встановленого об'єднання (я подам звіт про помилку про це) і 2$не буде працювати у внутрішньому циклі, оскільки CJam модифікує стек після кожної ітерації ... I я спробував кілька різних трюків, але найкоротшим був рівно 37 байт:li4,1$E*{__{I1$-_@<*}%&,2=I*a|}fI1><`
Денніс

5

JavaScript ES6, 100 ... 93 90 символів

Запустіть це на веб-консолі чи скретч-панелі останнього Firefox (Nightly або реліз).

EDIT 8 Багато гольфували !!! і зменшив його до 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

Ось деякі цифри, коли я запускаю цей тег сценарію на веб-сторінці:

n час (и)
10 0,001
100 0,005
1000 2.021
10000 236.983
100000       очікуваних tldr; Занадто довго не працював: 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]}

Я знаю, що це може бути ще більше гольф. Я також опублікую рішення, яке не є жорстоким, яке може бути ще коротшим.

EDIT 1 : Побільшайте трохи більше та встановіть 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. Я досі ледве розумію, як ти уникнув подвійного циклу 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"

Спробуйте в Інтернеті!

Порахувавши шебанг як один.
Використання другого масиву для зберігання сум здається значно швидшим, ніж хеш. Використання пам'яті також менше, чого я б не очікував.

Використання зразка:

$ 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 тепер виправлено.
примо

4

Ява, 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?
Мартін Ендер

Я вважаю, що j та k для циклів не потрібні дужки.
Майкл Пасха

Як випливає з Мартіна, я також хотів би побачити приурочене виконання цієї програми для N = 10K.
Майкл Пасха

4

APL (Dyalog Extended) , 36 35 байт

-1 байт Адама

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

* (У ngn / APL константа може закінчувати поїзд без використання . Але ngn / APL не має рахунку, тому нам потрібно десь ⍨.)


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

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, ось ось моя відповідь на 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 @ @ 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)}

Безумовно

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

Математика, 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за кілька секунд, але я сумніваюся, що ви отримаєте результат за 10 к за розумну кількість часу. Але я не думаю, що будь-хто з інших також не справляється з цим.


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]

Безумовно

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

Пітон, 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!=bта лінії 8 і 9 доwhile t[i]-2:i+=1
Джеймс Уолдбі - jwpat7

Дякую за пропозицію! Я також змінив цикл while на індекс, але це не зберегло стільки символів, скільки я очікував.
QuadmasterXLII

Ще два знаки: init U до [1] та перехід лінії 7 до післяfor
Джеймс Уолдбі - jwpat7

Ви все ще можете позбутися 2 символів, змінивши U,i=[1,2],2в U,i=[1],2і input()-2до input()-1і t=_*3*iдо t=_*3*i;U+=[i]та видаліть ;U+=[i]наприкінці
Джеймс Уолдбі - 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));}}

Безумовно, із тестовою джгутом

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

Дуже повільно: 46s для n = 500, 6m для n = 1000, 50m для n = 2000. З такою експоненціальною швидкістю, я вважаю, що на обробку n = 10K піде 5 або 6 днів.
Річард 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

Редагувати: 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;}

У Тіо зараз за 9 секунд він знайде 10000 значень (і там надрукує перші 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

Щось кажуть мені, що в програмуванні гольфу це нормально, але це не все ...
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" має бути пошуком біна в масиві "u" для значення "x" в діапазоні a..b; він поверне 1, indexWhereFind або 0, indexWhereEndOfsearch. З аргументом 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
∇∇в допі посилається на самого оператора, тоді як посилається на похідну функцію, що складається з оператора з його операндами (ами). Так що в монадійному операторі це те саме, що (⍺⍺∇∇)і в діадичному операторі це означає (⍺⍺∇∇⍵⍵).
Адам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.