Генерировать счастливые числа


22

История:

Люси спросила Джорджа, каков его счастливый номер. После некоторого размышления Джордж ответил, что у него есть несколько счастливых номеров. После некоторого недоразумения Люси спросила Джорджа, какие у него первые nсчастливые числа. Затем Джордж попросил вас, его приятель, написать ему программу, которая сделает всю работу за него.

Соревнование:

Вы напишите программу / функцию, которая получит из стандартного аргумента ввода / функции строку или целое число n. Затем программа / функция вернет / выведет первые n счастливые числа . Счастливые числа определяются через сито следующим образом.

Начните с положительных целых чисел:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, ...

Теперь удалите каждый второй номер:

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, ...

Второе оставшееся число - 3 , поэтому удалите каждое третье число:

1, 3, 7, 9, 13, 15, 19, 21, 25, ...

Теперь следующим оставшимся числом является 7 , поэтому удалите каждое седьмое число:

1, 3, 7, 9, 13, 15, 21, 25, ...

Далее убираем каждый девятый номер и так далее. Полученная последовательность - счастливые числа.

Выигрыш:

Как обычно для Codegolf, побеждает меньшее количество байтов.

Как обычно, заявки с использованием стандартных лазеек дисквалифицируются.


8
Я бы предложил включить определение в пост, а также первые десять или около того чисел.
xnor

Отличным дополнением будет то, что для каждого исследуемого элемента (3, 7 и т. Д.) Эта операция будет выполняться такое количество раз. Например, для 3, удалите третий элемент в списке 3 раза, 7-й элемент 7 раз и т. Д. (Обратите внимание, что это не последовательность, но идея та же самая)
Райан

@ Райан Я думаю, что эта последовательность была бы удивительно похожа на натуральные числа :)
TheNumberOne

@TheBestOne Ты так думаешь? Ранее я писал в math.stackexchange: math.stackexchange.com/questions/1153889/…
Райан

@ Райан На самом деле, я неверно истолковал ваше предложение. Как вы заявили в своем вопросе на math.se, я думаю, это было бы интересно.
TheNumberOne

Ответы:


16

Python 2, 79

n=input()
L=range(1,2**n)
for r in L:r+=r<2;map(L.remove,L[r-1::r])
print L[:n]

Волшебство итерации по списку, поскольку цикл изменяет его!

Список Lначинается со всех целых чисел 1до достаточно высокого значения. Код перебирает каждый элемент rиз L, принимая подсписок каждого r«го элемента и удаление каждого из этих значений. В результате удаленные значения не повторяются. В конце напечатайте первые nэлементы.

Выражение map(A.remove,B)- это трюк, который я долго ждал, чтобы использовать. Он вызывает A.removeкаждый элемент B, который вызывает Bудаление всех элементов A. По сути, он принимает разницу в списке, хотя он Bдолжен быть подсписком A. Требуется Python 2, так как Python 3 фактически не будет оценивать карту.

Первый цикл должен быть в специальном случае для преобразования rиз 1в 2, как r+=r<2.

Достаточно высокая верхняя граница 2**nделает программу очень медленной для больших значений n. Использование n*n+1достаточно, но стоит персонажа. Обратите внимание, что n*nэто не работает для n=1.


Вам просто нужны n**2цифры, а не2**n
Оптимизатор

3
Это одно из mapваших чудесных применений . Мне было интересно, был ли лучший способ ...
Sp3000

@Optimizer К сожалению, n**2+1если дело n=1не будет прощено.
xnor

Это использование карты является блестящим. Как использовать упорядоченный набор. Возможно, также может быть использован как map(A.index,B)найти индексы элементов B в A, map(A.count,B)чтобы найти количество элементов B в A, map(A.extend,B)чтобы добавить сплющенный список B к A. Разум поражает.
Рыцарь логики

13

Haskell, 71 69 байт

s(n:k)p=n:s[m|(i,m)<-zip[p..]k,i`mod`n>0](p+1)
f n=take n$1:s[3,5..]3

Определяет функцию f. Выражение 1:s[3,5..]3оценивается как бесконечный список счастливых чисел и fпросто берет первое nиз них take n.

f 20
[1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79]

Я мог сбрить 5 байтов с сита, используя параллельное понимание списка

s(n:k)p=n:s[m|m<-k|i<-[p..],i`mod`n>0](p+1)

но это потребовало бы передачи флага огромного компилятора -XParallelListCompв GHC, чтобы включить расширение.

Объяснение сита

s(n:k)p=               -- Sieving a list with head n and tail k with accumulator p is
 n:                    -- the head n, followed by
  s[m|                 -- the result of sieving the list of numbers m
    (i,m)<-zip[p..]k,  -- where (i,m) is drawn from [(p,k_0),(p+1,k_1),(p+2,k_2),..] and
    i`mod`n>0]         -- i does not divide n,
   (p+1)               -- using p+1 as the accumulator

Основная идея состоит в том, что оно s(n:k)pсоздает (p-1)счастливое число n, отбрасывает каждое nчисло из бесконечного хвоста k(смещается pна счет ранее произведенных чисел) и возвращается к этому списку с накопителем (p+1). В f, мы инициализируем процесс с нечетными числами, начиная с 3, и придерживаемся 1вперед, получая в точности счастливые числа.


12

Python 2, 71 69 67

Сначала я думал, что это будет большой проблемой для нарезки массивов в Python. Однако я столкнулся с камнем преткновения, когда обнаружил, что для срезов с шагом, отличным от 1, может быть назначен только другой срез одинаковой длины. Но после поиска в Google «python remove slice» моя вера была восстановлена: я обнаружил странное delутверждение, которое отлично справляется с задачей.

n=input()
l=range(n*n+9)
for v in l:del l[v&~1::v or 2]
print l[:n]

Старая версия

n=input()
l=range(1,n*n+9)
for v in l:del l[v-1%v::v+1/v]
print l[:n]

-2 байта благодаря Sp3000.


10

> <> , 121 114 111 байт

i2+:&:*1\
:})?v:2+>l{
nao2\r~1
)?vv>1+:&:&=?;:[{::nao}]$}l1-[01+}:l3-$%$l1-@@-{$[{~l1
3.\ ff+
!?:<]-1v
~]{43. >

У меня есть только несколько слов, чтобы сказать ...

... "Мое сознание болит."


объяснение

> <> является двумерным эзотерическим языком программирования и определенно не подходит для этой задачи из-за отсутствия массивов. Фактически, единственный тип данных в> <> - это странное сочетание int / float / char, и все происходит в стеке стеков.

Вот краткое изложение:

Line 1:            i2+:&:*1\

i2+:&              Read a char as input (n) and add 2, copying n+2 into the register
:*                 Duplicate and multiply, giving (n+2)^2 on the stack
1\                 Push 1 and go to the next line

Line 2:            >l{:})?v:2+

l{:})?v            Go to the next line if the stack's length is greater than (n+2)^2
:2+                Otherwise duplicate the top of the stack and add 2 to it

Line 3:            \r~1nao2

r~                 Reverse the stack and pop; stack contains the first (n+2)^2 odd integers
1nao               Print 1 (special case)
2\                 Push 2 (let's call this "i" for "iterations") and go to the next line

Line 4:            >1+:&:&=?;:[{::nao}]$}l1-[01+}:l3-$%$l1-@@-{$[{~l1)?vv

1+                 Increment i
:&:&=?;            If i is equal to n+2 (+2 because we started at 2), halt
:[{::nao}]$}       Print the i-th element down (the next lucky number) and also
                   copy it to the top of the stack, while moving i to the bottom
l1-[               Move everything but i to a new stack
0                  Push 0 (let's call this "r" for recursion depth)

Sieve loop:

1+                 Increment r
}:l3-$%$l1-@@-{$[  Move everything up to the last element to be sieved out to a new stack
{~                 Remove said last element
1)?vv              If the length is 1, go to line 6 (sieving complete)
                   Otherwise go to line 5, which repeats this sieve loop by teleporting

Line 6:            :?!v1-]

:?!v1-]            Keep unrolling and decrementing r until r is 0

Line 7:            >~]{43.             

~]                 Pop r and unroll once more (to the stack where i waits)
43.                Loop, performing everything from line 4 all over again

Вот фиктивный пример, который примерно показывает, как работает просеивание (вот kсчастливое число, с которым мы просеиваем):

[[15 13 11 9 7 5 3 1 k=3 r=0]]     -- move -->
[[15 13] [11 9 7 5 3 1 k=3 r=1]]   -- pop  -->
[[15 13] [9 7 5 3 1 k=3 r=1]]      -- move -->
[[15 13] [9 7] [5 3 1 k=3 r=2]]    -- pop  -->
[[15 13] [9 7] [3 1 k=3 r=2]]      -- move -->
[[15 13] [9 7] [3 1] [k=3 r=3]]    -- pop  -->
[[15 13] [9 7] [3 1] [r=3]]        (now we unroll)

7
Все еще лучше, чем Java;)
Оптимизатор

5
Мне нравится тот факт, что, по- naoвидимому, можно интерпретировать как «напечатать эту вещь сейчас».
Згарб

10

CJam - 25

Lri{1$W%{1$\(1e>/+}/)+}/p

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

Объяснение:

Эта реализация не удаляет числа последовательно из массива, но вычисляет каждое число на основе того, сколько было бы удалено до него.
Для каждого индекса i (от 0 до n-1) и каждого предыдущего счастливого числа l в обратном порядке мы увеличиваем i на i / (l-1), за исключением того, что для l = 1 мы используем 1 вместо 0, а также добавляем 1 в конце.
Например, для i = 4 мы имеем первые 4 числа [1 3 7 9] и вычисляем:
4 + 4 / (9-1) = 4
4 + 4 / (7-1) = 4
4 + 4 / (3 -1) = 6
6 + 6/1 = 12
12 + 1 = 13

L              empty array - the first 0 lucky numbers :)
ri             read and convert to integer (n)
{…}/           for each number (i) from 0 to n-1
    1$         copy the previous array
    W%         reverse the order
    {…}/       for each array element (l)
        1$     copy i
        \(     swap with l and decrement l
        1e>    use 1 if l=1
        /+     divide and add to i
    )+         increment and add the new lucky number to the array
p              pretty print

Интересная техника :)
TheNumberOne

6

Pyth: 23 22 байта

<u-G%@GhH+0GQ%2r1^hQ2Q

Попробуйте онлайн: Pyth Compiler / Executor

Объяснение:

<u-G%@GhH+0GQ%2r1^hQ2Q    Q = input()
             %2r1^hQ2     create the list [1, 2, ..., (Q+1)^2-1][::2]
 u          Q%2r1^hQ2     G = [1, 2, ..., (Q+1)^2-1][::2]
                           modify G for each H in [0, 1, 2, ..., Q]:
  -G%:GhH+0G                  G = G - ([0] + G)[::G[H+1]]
                               (minus is remove in Pyth)
<                    Q    print the first Q elements of the resulting list

На самом деле при уменьшении вычисляется больше, чем Qсчастливых чисел (команда удаления вызывается Q + 1 раз, Q-1 должно быть достаточно).


5

R, 58 байт

n=scan();s=r=1:n^2;for(j in 1:n)r=r[-max(2,r[j])*s];r[1:n]

С переносами строк:

n=scan()              #user input
s=r=1:n^2             #declare r and s simultaneously, both large enough to sieve
for(j in 1:n)
  r=r[-max(2,r[j])*s] #iteratively remove elements by position in vector
r[1:n]                #print

Предыдущая версия, 62 байта

function(n){
  s=r=1:n^2             #declare r and s simultaneously, both large enough to sieve
  for(j in 1:n)
    r=r[-max(2,r[j])*s] #iteratively remove elements by position in vector
  r[1:n]                #print
}

Предыдущая версия, 78 байт

n=as.numeric(readline())   #ask for user input and convert it to numeric
r=1:n^2                    #create a large enough vector to sieve
for(j in 1:n){             #loop
  r=r[-max(2,r[j])*1:n^2]  #iteratively remove elements by position in vector
}
r[1:n]                     #print

64 байта: изменить n=as.numeric(readline())на function(n){...}. Это создает объект функции, который может быть назначен и вызван. Оставьте фигурные скобки в forпетле.
Алекс А.

Спасибо @Alex! Хотя это 66, так как ему нужно имя?
freekvd

Для представления не нужно имя. Смотрите решения Matlab / Octave. Объекты R-функций похожи на безымянные / лямбда-функции в других языках, которые являются допустимыми представлениями.
Алекс А.

Как насчет n=scan(n=1)?
koekenbakker

2
Это работает! И это на 1 символ меньше. Еще короче, если бы я отбросил n = 1, функция игнорирует все элементы n после первого.
freekvd

4

CJam, 32 30 байт

3ri:N#,N{0\__I1e>)=%-+}fI(;N<p

Принимает участие от STDIN.

Объяснение кода :

3ri:N#,                          "Read the input in N and get first 3^N whole numbers";
       N{0\__I1e>)=%-+}fI        "Run the code block N times, storing index in I";
         0\__                    "Put 0 before the array and take 2 copies";
             I1e>)=              "Take min(2, I + 1) th index from the copy";
                   %             "Take every array[ min (2, I + 1)] element from the array";
                    -+           "Remove it from the list and prepend 0 to the list";
                         (;N<p   "Print number index 1 to N";

Попробуйте онлайн здесь


4

Python 2, 105 101 байт

n=input()
L=range(-1,n*n+9,2)
i=2
while L[i:]:L=sorted(set(L)-set(L[L[i]::L[i]]));i+=1
print L[1:n+1]

Просто прямая реализация.

Pyth, 39 36 35 32 байта

J%2r1h^Q2VJI>JhN=J-J%@JhN+2J;<JQ

Аналогичен подходу выше, но вещи индексируются 0, а не 1. Попробуйте онлайн .

Спасибо @Jakube за указание на сохранение байтов.


3

Mathematica, 80 байт

(For[l=Range[#^2];i=1,(m=l[[i++]]~Max~2)<=Length@l,l=l~Drop~{m,-1,m}];l[[;;#]])&

Прямая реализация определения. Как и некоторые другие ответы, начинается с диапазона от 1до, а затем продолжает фильтрацию.n2


3

Perl, 86 81 78

86:

@a=(1..($k=<>)**2);for$n(@a){$i=1;@a=map{$i++%($n+($n<2))?$_:()}@a;$k-=$k&&print"$n "}

UPDATE: очевидно, grep{...}лучше , чем map{...?$_:()} 81:

@a=(1..($k=<>)**2);for$n(@a){$i=1;@a=grep{$i++%($n+($n<2))}@a;$k-=$k&&print"$n "}

ОБНОВЛЕНИЕ: хорошо, фактически однострочник теперь. Я могу остановиться. (?) 78:

@a=(1..($k=<>)**2);for$n(@a){$k-=$i=$k&&print"$n ";@a=grep{$i++%($n+=$n<2)}@a}

3

Октава, 139 83 72

function r=l(n)r=1:2:n^2;for(i=2:n)h=r(i);r(h:h:end)=[];end;r=r(1:n);end

Ungolfed:

function r=l(n)
  r=1:2:n^2;
  for(i=2:n)
    h=r(i);
    r(h:h:end)=[];
  end
r=r(1:n);  # reduce it to only N lucky numbers
end

2

J, 60 52 байта

   ({.}.@((>:@{.,]#~0<({~{.)|i.@#)@]^:[2,1+2*i.@*:@>:)) 8
1 3 7 9 13 15 21 25

Пояснение (справа налево):

2,1+2*i.@*:@>:  generates the list 2 1 3 5 7 9... with (n+1)^2 odd numbers
^:[             repeats n times the following
@]                using the list
0<({~{.)|i.@#     is the remainder of the indexes of the lists elements with the first element positive (i.e. index divisible by first element)
]#~               keep those elements from the list
>:@{.,            concatenate a first element with the value of the current one +1
}.@             drop first element
{.              take the first n element

2,1+2*i.@*:@>:кажется слишком долго , но я могу только сократить его на 1 байты подкачки *:с !созданием список растет в геометрической прогрессии.


2

JavaScript (ES6) 96 99

Редактировать отсчет в первом цикле - спасибо @DocMax

F=n=>(i=>{
  for(o=[1];--i;)o[i]=i-~i;
  for(;++i<n;)o=o.filter((x,j)=>++j%o[i]);
})(n*n)||o.slice(0,n)

Ungolfed

F=n=>{
  for (i = n*n, o = [1]; --i;)
    o[i] = i+i+1;
  for (; ++i < n; )
    o = o.filter((x, j) => (j+1) % o[i])
  return o.slice(0,n)
}

Тест в консоли Firefox / FireBug

F(57)

Выход

[1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, 87, 93, 99, 105, 111, 115, 127, 129, 133, 135, 141, 151, 159, 163, 169, 171, 189, 193, 195, 201, 205, 211, 219, 223, 231, 235, 237, 241, 259, 261, 267, 273, 283, 285, 289, 297, 303]

1
Вы можете сохранить 1 путем F=n=>{for(o=[1],i=n*n;--i;)o[i]=2*i+1;for(;++i<n;o=o.filter((x,j)=>++j%o[i]));return o.slice(0,n)}
обратного

Твои неряхи тут не особо помогают: P;)
Оптимизатор

Обновленный @Optimizer ungolfed - возможно, все еще не очень помогает, но по крайней мере работает сейчас
edc65

Я имел в виду больше о том, что «просто изменение форматирования не поможет, пожалуйста, предоставьте комментарии :)»
Оптимизатор

2

Matlab, 104 байта

function x=f(n)
k=1;N=n;x=0;while nnz(x)<n
x=1:N;m=1;while m-nnz(x)
m=x(x>m);x(m:m:end)=[];end
N=N+2;end

Спасибо @flawr за очень подходящие комментарии и предложения.

Пример из командной строки Matlab:

>> f(40)
ans =
  Columns 1 through 22
     1     3     7     9    13    15    21    25    31    33    37    43    49    51    63    67    69    73    75    79    87    93
  Columns 23 through 40
    99   105   111   115   127   129   133   135   141   151   159   163   169   171   189   193   195   201

Благодарность! Я использовал это в прошлом, но склонен забывать
Луис Мендо

@ Flawr Хорошая мысль. Этот ответ становится более твоим, чем мой! :-)
Луис Мендо

Конечно! Я чаще зависаю в StackOverflow, но там тот же дух. Я признателен за это!
Луис Мендо

Хорошая точка зрения! Я не уверен, что все, что я изучаю, будет полезным или фактически вредным для моего стандартного использования Matlab, однако :-P
Луис Мендо

2
Ну, Codegolf не об использовании, а о злоупотреблении языком ^^
flawr

1

Bash + coreutils, 136

Я надеялся играть в гольф больше, ну да ладно. Не каждый день, когда вы добавляете рекурсивную функцию в сценарий оболочки:

f(){
mapfile -tn$2 a
(($1>$2))&&{
tr \  \\n<<<${a[@]}
sed $[${a[-1]}-$2]~${a[-1]}d
}|f $1 $[$2+1]||echo ${a[@]}
}
yes|sed -n 1~2=|f $1 2

Выход:

$ ./lucky.sh 23
1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 87 93 99
$ 

Bash + coreutils, 104

Короче, используя более простую реализацию:

a=(`seq 1 2 $[3+$1**2]`)
for((;i++<$1;));{
a=($(tr \  \\n<<<${a[@]}|sed 0~${a[i]}d))
}
echo ${a[@]:0:$1}

1

Go, 326

package main
import"fmt"
func s(k, p int,in chan int)chan int{
    o := make(chan int)
    go func(){
        for p>0{
            o<-<-in;p--
        }
        for{
            <-in
            for i:=1;i<k;i++{o<-<-in}
        }
    }()
    return o
}
func main(){
    n := 20
    fmt.Print(1)
    c := make(chan int)
    go func(c chan int){
        for i:=3;;i+=2{c<-i}
    }(c)
    for i:=1;i<n;i++{
        v := <-c
        fmt.Print(" ", v)
        c = s(v, v-i-2, c)
    }
}

Прямая реализация с использованием рутин и труб для изготовления сит.


7
Этот код гольф, пожалуйста, добавьте количество байтов.
edc65

1

MATLAB, 62 символа

n=input('');o=1:2:n^2;for i=2:n;o(o(i):o(i):end)=[];end;o(1:n)

Сначала я неверно истолковал проблему - теперь моя пересмотренная версия на самом деле короче.


0

Ракетка 196 байт

Выдает счастливые числа вплоть до:

(λ(n)(let loop((l(filter odd?(range 1 n)))(i 1))(define x(list-ref l i))(set! l(for/list((j(length l))
#:unless(= 0(modulo(add1 j)x)))(list-ref l j)))(if(>= i(sub1(length l)))l(loop l(add1 i)))))

Безголовая версия:

(define f
 (λ(n)
    (let loop ((l (filter odd? (range 1 n))) (i 1))
      (define x (list-ref l i))
      (set! l (for/list ((j (length l)) #:unless (= 0 (modulo (add1 j) x)))
                (list-ref l j)))
      (if (>= i (sub1 (length l)))
          l
          (loop l (add1 i)))))
  )

Тестирование:

(f 100)

Выход:

'(1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 87 93 99)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.