Генерация чисел Улама


19

Учитывая целое число n(где n < 10001) в качестве входных данных, напишите программу, которая будет выводить первые n числа Улама . Число Улама определяется следующим образом:

  1. U 1 = 1, U 2 = 2.
  2. Ибо n > 2, U 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). Вот первые несколько чисел Улама:

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
@Dennis Space или запятая или оба в порядке. Минимальное значение n равно 1.
Абсент

Как есть, у меня есть скобки вокруг моего списка. Это тоже нормально или я должен их удалить?
Деннис

1
@ Денис Скобки в порядке.
Абсент

Ответы:


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ₖ₊₁ ... ], что следующий номер Улама является третьим наименьшим элементом. Добавьте его 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

Там +_*...
Томсминг

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" на то, что должно быть. «10000», вероятно, в конце концов закончится, но я не дал этому закончиться. Счет символов этой записи предназначен для однозначного ввода. Вывод в форме запроса.



5

GolfScript ( 41 37 байт)

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

Онлайн демо

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

Благодаря Денису за 41-> 37.


1
Это довольно быстро. n = 1000занимает меньше минуты с GolfScript; порт в CJam завершается n = 1000за 8 секунд и n = 10000за 1 час 20 метров. - Вы можете сохранить четыре байта, объединив свой подход с моим, а именно включив 0 в массив и отбросив его впоследствии. Это позволяет использовать set union вместо блока и устраняет необходимость в переменной:~.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 символов

Запустите это в Web Console или Scratchpad последней версии Firefox (Nightly или выпуск).

РЕДАКТИРОВАТЬ 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]}

Я знаю, что это может быть в гольфе еще дальше. Я также опубликую решение без грубого обращения, которое может быть еще короче.

РЕДАКТИРОВАТЬ 1 : Гольф немного больше и исправлено для n = 1

Я должен сказать, что я завидую Хаскелу и Дж. За такие супер удобные ярлыки для всех видов требований -_-


Что касается 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. Я до сих пор плохо понимаю, как ты избежал двойной петли. Слава 2. Гольф подсказка: в 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"

Попробуйте онлайн!

Считая Шебанг как один.
Использование второго массива для хранения сумм кажется значительно быстрее, чем хеш. Использование памяти также меньше, чего я бы не ожидал.

Пример использования:

$ 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неверен, хотя; он должен напечатать одно число.
Деннис

@ Денис теперь исправлен.
Прим

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 байт от 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.

ИксИксИкс2a+бaИксбИксaзнак равно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 в гольфе, поэтому вот мой ответ на 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)

Сильно вдохновленный разработанным @ Ypnypn решением для грубой силы Java, опубликованным ранее:

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

Это очень прямая реализация спецификации.

  • Найти все пары.
  • Удалить все дубликаты.
  • Удалить все номера меньше, чем последний номер Улама.
  • Добавьте минимум к списку.

Я также применяю хитрость Денниса в том, чтобы включать суммы с 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]

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!=bи строки 8 и 9 вwhile t[i]-2:i+=1
Джеймс Уолдби - jwpat7

Спасибо за предложение! Я также изменил цикл while на индекс, но он не сохранил столько символов, сколько я ожидал.
QuadmasterXLII

Еще 2 символа: инициализируйте 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]в конце для
Джеймс 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, 6 м для n = 1000, 50 м для 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;}

В Tio сейчас за 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


@ceilingcat "z = k" для меня неправильный, потому что бинарный поиск (функция bs () или ваша функция B ()) мне кажется нужным в качестве диапазонов аргументов (я не знаю, правильно ли это тоже ...), поэтому в функция, которая вызывает поиск по
бину,

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, который я отправил. Кажется, я не понимаю, когда использовать place вместо possible ... возможный ∇∇ используется, когда один аргумент является одной функцией (а не одним другим типом). «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
∇∇в dop относится к самому оператору, а относится к производной функции, состоящей из оператора с его операндом (-ами). Таким образом, в монадическом операторе то же самое, что в (⍺⍺∇∇)то время как в диадическом операторе это означает (⍺⍺∇∇⍵⍵).
Адам
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.