Створення щасливих чисел


22

Історія:

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

Змагання:

Ви напишете програму / функцію, яка отримає від стандартного аргументу введення / функції рядок або ціле число n. Програма / функція повертає / виводить перші n Lucky Numbers . Вдалі числа визначаються через сито так.

Почніть з натуральних чисел:

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, ...

Далі, видаліть кожне дев'яте число тощо. Отримана послідовність є щасливими числами.

Перемога:

Як зазвичай для кодегольфа, виграє найменше байтів.

Як завжди, матеріали, що використовують стандартні лазівки , дискваліфікуються.


8
Я б запропонував включити визначення в посаду, а також перші десять чи більше цифр
xnor

Класним розширенням було б те, що для кожного досліджуваного пункту (3, 7 тощо) буде виконано цю операцію стільки разів. Наприклад , для 3, видалити третій елемент в списку 3 рази, 7 - й елемент 7 разів, і т.д. (примітка це не послідовність , але ідея та ж)
Райан

@Ryan Я думаю, що ця послідовність буде надзвичайно схожа на натуральні числа :)
TheNumberOne

@TheBestOne Ви так вважаєте? Я опублікував раніше на math.stackexchange: math.stackexchange.com/questions/1153889/…
Райан

@Ryan Насправді я неправильно трактував вашу пропозицію. Як ви це заявили у своєму запитанні на math.se, я думаю, що це було б цікаво.
TheNumberOne

Відповіді:


16

Пітон 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

Пітон 2, 71 69 67

Спочатку я подумав, що це буде великим викликом для нарізки масиву Python. Однак я зіткнувся з каменем спотикання, коли виявив, що для скибочок із кроком, відмінним від 1, може бути призначений лише інший шматочок однакової довжини. Але після того, як гугл "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

Пояснення:

<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

Математика, 80 байт

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

Безпосередня реалізація визначення. Як деякі інші відповіді, починається з діапазону від 1до, а потім продовжує фільтрувати.n2


3

Перл, 86 81 78

86:

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

ОНОВЛЕННЯ: очевидно, 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

Безголівки:

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)

Безумовно

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

Ваш непільгований не дуже допомагає тут: P;)
Оптимізатор

@Optimizer ungolfed оновлено - можливо, все ще не дуже допомагає, але принаймні працює зараз
edc65

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

2

Матлаб, 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
Ну кодегольф не про використання, а скоріше про зловживання мовою ^^
недолік

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

Іди, 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)
    }
}

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


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:

(λ(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.