Нещасливі числа!


22

Що потрібно знати:

По-перше, щасливі числа.

Щасливі номери генеруються так:

Візьміть усі натуральні числа:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20...

Потім видаліть кожне друге число.

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39...

Тепер, 3в безпеці.

Видалити кожен 3-й номер:

1, 3, 7, 9, 13, 15, 19, 21, 25, 27, 31, 33, 37, 39, 43, 45, 49, 51, 55, 59...

Тепер, 7в безпеці.

Видаліть кожен 7-й номер.

Продовжуйте та видаляйте кожне nчисло, де nє першим безпечним числом після усунення.

Остаточний список безпечних номерів - це щасливі номери.


Нещасливі числа складаються з окремих списків чисел, які є [U1, U2, U3... Un].

U1 це перший набір номерів, вилучених із щасливих "кандидатів", тож вони:

2, 4, 6, 8, 10, 12, 14, 16, 18, 20...

U2 видалено другий набір номерів:

5, 11, 17, 23, 29, 35, 41, 47, 53, 59...

І так далі і так далі ( U3третій список, U4четвертий і т.д.)


Виклик:

Ваше завдання полягає в тому, щоб отримати два входи mі nзгенерувати mчисло у списку Un.

Приклади входів і виходів:

(5, 2) -> 29
(10, 1) -> 20

Технічні характеристики:

  • Ваша програма повинна працювати mдо 1e6та nдо 100.
    • Вам гарантовано, що обидва mі nє додатними цілими числами.
    • Якщо вам цікаво, U(1e6, 100)= 5,333,213,163. (Дякую @pacholik!)
  • Ваша програма повинна обчислити це протягом 1 дня на розумному сучасному комп’ютері.

Це , тому найкоротший код у байтах виграє!

PS: Було б добре, якби хтось придумав загальну формулу їх створення. Якщо у вас є формула, будь ласка, вкажіть її у своїй відповіді!


На OEIS: A219178 та A255543
Arnauld


2
Ви реалізували код, який може насправді виконувати (1e6,1e6)?
Джонатан Аллан

2
Якщо у вас буде потреба в часі, вам потрібно вказати середовище синхронізації (наприклад, ваш комп'ютер, вільно доступний онлайн-сервер віртуального управління або "розумний сучасний комп'ютер").
Мего

1
Чи прийнятно, щоб функція не працювала у n=1випадку? Оскільки це особливо - для всіх інших випадків, індекс наступного щасливого числа на основі 0 n-1.
Myridium

Відповіді:


1

CJam , 74 байти

ri0Lri:U{1$W%{1$\(1e>/+}/)+}/2t:A0@{@:B:(_0#):D{D(_A=tD<BD>+}&@)@DU=-}h]1=

Спробуйте в Інтернеті! Час очікує на більші випадки, докладніше про обмеження часу.


Пояснення:

Наша програма безсоромно запозичує код aditsu для створення списку N щасливих чисел, заміна 1 на 2 дає приріст у кожній фазі сита. Залишки коду, що залишилися на кожному елементі, доки не буде знайдено нуль (шляхом зрізання та додавання хвоста, що не зменшується) і ефективно підраховує кроки в кожній із N фаз сита одразу.

ri                               e# read M
0Lri:U{1$W%{1$\(1e>/+}/)+}/2t:A  e# list steps (also becomes B)
0@                               e# arrange stack [B I M]
{                                e# while M
   @:B                           e#   get current B
   :(                            e#   decrement every element in B
   _0#):D                        e#   find first 0
   {                             e#   if there is a 0
      D(_A=t                     e#     reset that element in B
      D<BD>+                     e#     replace tail after 0
   }&                            e#   end if
   @)                            e#   increment I
   @DU=-                         e#   decrement M if N-th phase of sieve
}h                               e# end loop
]1=                              e# return I

Час виконання:

Якщо ви абсолютно повинні запустити програму в браузері для більшої кількості, ви можете скористатися цим інтерпретатором і дозволити продовження сценарію, якщо буде запропоновано, але це може бути занадто повільним, щоб кваліфікувати. Використання ( M , N ) = (100,100) займає ~ 247s. Ітерація програм відносно лінійна з точки зору M , тому обчислення (1e6,100) може зайняти ~ 29 днів.

Використовуючи інтерпретатор оболонок на ПК, програма обчислює (100100) у ~ 6s, а обчислює (1e4,100) у ~ 463s. Програма повинна бути здатна обчислити (1 600 000) за ~ 13-17 годин. У цьому випадку я припускаю, що програма кваліфікується.

Зверніть увагу, що всі часи були округлені як в вимірах, так і в розрахунках.


7

Perl, 87 85 82 81 байт

Включає +4 для -pX

Введіть STDIN як один рядок з n першим (зауважте, це зворотній порядок, запропонований у виклику). Отже, для обчислення U(1000000, 100):

unlucky.pl <<< "100 1000000"

Алгоритм, що базується на щасливих числах aditsu , відповідає складності часу, O(n^2)тому це досить швидко для необхідного діапазону. 100, 1000000Випадок дає 5333213163в 0,7 секунди. Через проблеми, які у Perl виникають з do$0рекурсією на основі, вона використовує багато пам'яті. Переписання його як функції дозволило б використовувати пам'ять, O(n)але на деяку кількість байт довше

unlucky.pl:

#!/usr/bin/perl -pX
$_=$a{$_}||=/\d+$/>--$_?2*$&+$^S:($_=$_.A.(do$0,$^S?0|$&+$&/~-$_:$&*$_-1),do$0)

Це працює, як показано, але використовуйте буквальне, ^Sщоб отримати заявлений бал.

Мені $^Sневідоме будь-яке раніше використання перлгольфа.


Але скільки часу це займе (1e6,100)?
Myridium

@Myridium Через вибух пам'яті, викликаний do$0нею, в основному недоступний на будь-якому реалістичному комп'ютері. Але якщо стільки пам’яті існувало близько 2 років. Я насправді не виписав і не протестував звичайну версію підпрограми, але очікую, що вона закінчиться через кілька місяців і працює навіть на комп'ютерах з дуже малою пам’яттю. Тож добре, що ці значення не знаходяться в необхідному діапазоні для цього завдання.
Тон Євангелія

Чи не складно це обчислити (1e6,100)протягом дня? Що означає, що ці значення не потрібні?
Myridium

@Myridium Зверніть увагу , що в моїй програмі nі mнаведені в зворотному порядку. 100 1000000Вхід обчислює U(1000000, 100)і видає 5,333,213,163в 0,7 секунди. Це на сьогоднішній день найшвидша програма з цих публікацій
Тон Євангелія

Ну гаразд, я очікував, що (100,1e6)це буде набагато швидше (1e6,100), і я подумав, що це пояснення блискавиці 0,7 секунди!
Myridium

7

Пітон 3, 170

from itertools import*
def L(n,k=1):
 if n<2:yield from count(2+k,2)
 t=L(n-1);l=next(t)
 for i in t:
  n+=1
  if(n%l>0)==k:yield i
U=lambda m,n:sum(islice(L(n,0),m-1,m))

Функція L генерує ряд можливих щасливих чисел (якщо k - True) або Un (якщо False). Оцінено ліниво (тому мені не потрібно генерувати нескінченні списки n-1, якщо хочу Un ).

Запуск функції U .

Швидкість

U (1 000 000; 100) на моїй машині з PyPy потрібно близько 1 години 45 хвилин. Я підозрюю, що близько чотирьох годин із CPython. (Так, 4 години 20 хвилин, якщо бути точним.)

Якби я використовував список замість генераторів, я міг би набрати деяку швидкість, але мені знадобиться список більшого розміру, ніж дозволяє мені Python. А якщо б це було, то знадобляться десятки гігабайт оперативної пам’яті.


Так, і U (1 000 000; 100) = 5,333,213,163 .


Має діяти зараз.
клісмік

3

Хаскелл

Не в змозі обчислити n = 1: 175 160 байт

Під час компіляції мені знадобилося обчислити для мого комп'ютера 2h 35m (1000000,100):

n#s=y:(n#p)where y:p=drop(n-1)s
n%s=f n s$[]where f n s=(take(n-1)s++).f n(drop n s) 
l 2=[1,3..]
l m=((l$m-1)!!(m-2))%(l$m-1)
m?n=(((l n)!!(n-1))#(l$n))!!(m-1)

Я спробував позбутися від whereмодулів, але вони, здається, впливають на швидкість, і я не впевнений, чому ... Але я думаю, що тут потрібно зробити більше обрізки.

Метод, який використовується m?nдля запиту відповіді, заданої а mта n.

Безумовно

everynth n xs = y:(everynth n ys) -- Takes every nth element from a list 'xs'
  where y:ys = drop (n-1) xs

skipeverynth n xs = f' n xs $ []  -- Removes every nth element from a list 'xs'
  where f' n xs = (take (n-1) xs ++) . f' n (drop n xs) 

l 2 = [1,3..] -- The base case of the list of lucky numbers for 'n=2'
l m = skipeverynth ((l$m-1)!!(m-2)) (l$m-1) -- Recursively defining next case as being the last one with every 'ath' element skipped. Here, 'a' is the (m-1)th elemnent of the (l (m-1)) list.
ul m = everynth ((l m)!!(m-1)) (l$m) -- This is not used other than to compute the final, required unlucky number list. It picks out every 'ath' element.

ans m n = (ul n)!!(m-1) -- The function giving the answer.

Я вважаю, що можливо поєднувати функції 'skipeverynth' і 'everynth' в одну функцію, яка повертає пару.

Я використовував код такого роду, щоб пропустити кожен n-й елемент. Я робив це кілька разів, але це було завжди набагато неефективніше, і я не міг зрозуміти, чому.

Здатний обчислити всі n: 170 байт

Це в основному те саме, але maxдля роботи з особливим випадком потрібно було перекинути пару функцій n=1.

n#s=y:(n#p)where y:p=drop(n-1)s
n%s=f n s$[]where f n s=(take(n-1)s++).f n(drop n s) 
l 1=[1..]
l m=((l$m-1)!!(max 1$m-2))%(l$m-1)
m?n=(((l n)!!(max 1$n-1))#(l$n))!!(m-1)

2

R 82 байти

f<-function(m,n){a=1:2e8
i=1
while(i<n){a=c(0,a)[c(F,rep(T,i))]
i=i+1}
a[(n+1)*m]}

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

f(5,2)
Returns 29

Для цього потрібно мати досить великий вектор, щоб залишилося достатньо чисел, щоб повернути значення. У створеному векторі вже близько 800 Мбіт, і функція може обробляти до m = 1e4 і n = 100, так що все ще далеко від мети.

Для створення досить великого вектора для обчислення f (1e6,100) знадобиться початковий вектор 1: 2e10. Завдяки процедурам розподілу даних Rs це створює вектор> 70Gb, який неможливо запустити на будь-якому комп’ютері, який я знаю, хоча код запускався.

Error: cannot allocate vector of size 74.5 Gb

Для довідки f (1e4,100) працює приблизно за 30 секунд. Виходячи з цього і на пару менших тестів f (1e6,100) знадобиться близько години.


Позначення вашої відповіді неконкурентоспроможним не виправдовує її не виконати вимоги виклику.
Мего

@Mego Ів бачив безліч відповідей, які не відповідають вимогам (у цьому виклику є принаймні ще 1). Я зашифрував це, і, як мені здається, він відповідає духу запиту кодування, я також чітко зазначив, де він провалився. Крім того, як ви згадуєте у своїх коментарях до питання, він не вказує, який тип комп'ютера він повинен перевірити. Я впевнений, що там є комп'ютери, які можуть записати 7 Гб в пам'ять і обробити її. Я не міг цього зробити, але я все-таки хотів відправити повідомлення, і я подумав, що чітка заява - це дійсний компроміс.
gtwebb

У нас є чітка політика щодо відповідей, які не відповідають специфікації виклику . Коли я говорив, я не впевнений, чому ви назвали свою відповідь неконкурентною. Якщо я правильно розумію, це повинно працювати достатньо пам'яті, але ви не змогли його перевірити, оскільки у вас недостатньо оперативної пам'яті. Це правильно?
Денніс

1
1. Ця політика буде проводиться в життя, але чотири модераторів не може перевірити всі відповіді на сайті. Якщо ви знайшли подання, яке не відповідає правилам, позначте його для уваги модератора, щоб ми могли переглянути. 2. Для участі у вас не потрібно вивчати мову гольфу. Мови виробництва, такі як R, так само вітаються. Я регулярно публікую відповіді на Python.
Денніс

1
3. У специфікації не згадуються обмеження пам'яті, але існує обмеження на 24 години. За відсутності комп'ютера з 70 гігабайт (або ви мали на увазі гігабітні біти ) для перевірки цього, важко визначити, правдива ця відповідь чи ні. Я пропоную спробувати екстраполювати час виконання так само добре, як ви можете. Якщо пройшло менше доби, видаліть не конкуруючий заголовок і включіть свою екстраполяцію в пост. Якщо це займе більше часу, ваше подання має бути оптимізовано чи видалено.
Денніс

1

Ракетка 332 байти

(λ(N m n)(let loop((l(filter odd?(range 1 N)))(i 1))(define x (list-ref l i))(if(= i (sub1 n))
(begin(set! l(for/list((j(length l))#:when(= 0(modulo(add1 j)x)))(list-ref l j)))(list-ref l(sub1 m)))
(begin(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 m n)
    (let loop ((l (filter odd? (range 1 N))) (i 1))
      (define x (list-ref l i))
      (if (= i (sub1 n))
          (begin (set! l (for/list ((j (length l)) 
                                   #:when (= 0 (modulo (add1 j) x)))
                           (list-ref l j)))
                 (list-ref l (sub1 m)))
          (begin (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 5 2)

Вихід:

29

1

Clojure, 221 байт

Могутній довгий, але розглядає справу (f 1). Без цього особливого випадку це було 183 байти. Це було занадто багато зусиль, щоб його не було розміщено.

(defn f([n](if(< n 2)(take-nth 2(drop 2(range)))(f n 1(take-nth 2(rest(range))))))([n i c](if (< n 2)c(let[N(first(drop i c))F #((if(= 2 n)= >)(mod(inc %)N)0)](f(dec n)(inc i)(filter some?(map-indexed #(if(F %)%2)c)))))))

Приклади виходів:

(pprint (map #(take 10 (f %)) (range 1 10)))
((2 4 6 8 10 12 14 16 18 20)
 (5 11 17 23 29 35 41 47 53 59)
 (19 39 61 81 103 123 145 165 187 207)
 (27 57 91 121 153 183 217 247 279 309)
 (45 97 147 199 253 301 351 403 453 507)
 (55 117 181 243 315 379 441 505 571 633)
 (85 177 277 369 471 567 663 757 853 949)
 (109 225 345 465 589 705 829 945 1063 1185)
 (139 295 447 603 765 913 1075 1227 1377 1537))

1000000 100 випадків було обчислено приблизно за 4,7 години, принаймні воно не вийшло з ладу.

java -jar target\stackoverflow-0.0.1-SNAPSHOT-standalone.jar 1000000 100
5333213163
"Elapsed time: 1.7227805535565E7 msecs"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.