Номери рушниці


45

Номери дробовика - це послідовність із досить простим визначенням, але деякою цікавою структурою. Почніть з натуральних чисел:

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

Тепер візьміть усі числа за індексами, розділеними на 2 , згрупуйте їх у пари і поміняйте числами в кожній парі:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ...
   ^     ^     ^     ^      ^       ^       ^  
    <--->       <--->        <----->         <----
1, 4, 3, 2, 5, 8, 7, 6, 9, 12, 11, 10, 13, 16, ...

Тепер зробіть те ж саме з індексами, розділеними на 3 :

1, 4, 3, 2, 5, 8, 7, 6, 9, 12, 11, 10, 13, 16, ...
      ^        ^        ^           ^          
       <------>          <--------->           
1, 4, 8, 2, 5, 3, 7, 6, 10, 12, 11, 9, 13, 16, ...

А потім для 4 , 5 , 6 тощо:

1, 4, 8, 2, 5, 3, 7, 6, 10, 12, 11, 9, 13, 16, ...
1, 4, 8, 6, 5, 3, 7, 2, 10, 12, 11, 14, 13, 16, ...
1, 4, 8, 6, 12, 3, 7, 2, 10, 5, 11, 14, 13, 16, ...
1, 4, 8, 6, 12, 14, 7, 2, 10, 5, 11, 3, 13, 16, ...
...

Після k таких кроків будуть зафіксовані перші k + 1 числа. Таким чином, ми можемо визначити нескінченну послідовність чисел Shotgun як межу відпуску k до нескінченності. Перші 66 номерів:

1, 4, 8, 6, 12, 14, 16, 9, 18, 20, 24, 26, 28, 22, 39, 15, 36, 35, 40, 38, 57, 34, 48, 49, 51, 44,
46, 33, 60, 77, 64, 32, 75, 56, 81, 68, 76, 58, 100, 55, 84, 111, 88, 62, 125, 70, 96, 91, 98, 95,
134, 72, 108, 82, 141, 80, 140, 92, 120, 156, 124, 94, 121, 52, 152, 145, ...

Факт забави: Незважаючи на те, що отриманий лише перестановкою натуральних чисел, ця послідовність не містить ніяких простих чисел.

Змагання

Задавши ціле число n > 0, знайдіть номер nth Shotgun. Ви можете написати програму або функцію, взявши введення через STDIN (або найближчу альтернативу), аргумент командного рядка або аргумент функції і повернути вихідний результат або роздрукувати його в STDOUT (або найближчій альтернативі).

Це код гольфу, тому виграє найкоротше подання (у байтах).

Табло лідерів

Це отримує більше відповідей, ніж я думав, а також кілька людей, які змагаються однією мовою. Отже, тут є фрагмент стека для створення як звичайного табло, так і огляду переможців за мовою.

Щоб переконатися, що ваша відповідь відображається, будь ласка, почніть свою відповідь із заголовка, використовуючи наступний шаблон Markdown:

# Language Name, N bytes

де Nрозмір вашого подання. Якщо ви покращите свій рахунок, ви можете зберегти старі бали у заголовку, прокресливши їх. Наприклад:

# Ruby, <s>104</s> <s>101</s> 96 bytes


1
Цей кумедний факт божевільний, цей алгоритм пересуває всі букви до кінця? Або є інші природні числа, які також не відбудуться?
Девон Парсонс

1
@DevonParsons Так, вона перетасовує всі букви "до кінця". Але я думаю, що відсутні й інші номери. Це виглядає як 10, наприклад 21, 25і 30не з’являється, наприклад.
Мартін Ендер

3
Це звучить як питання проекту Ейлера. Я не думаю, що це ... але, можливо, так і має бути.
Корі Огберн

9
Взагалі, на тій kітерації, kелемент елемента в масиві переноситься до 2kго-го положення і більше не буде торкатися до тих пір, поки 2kітерація, в цей час вона переноситься на 4kту позицію, ad infinitum. Прем'єр не переміщується, поки не настане його черга, так би мовити, тому всі прайми переміщаються вперед. Але ми можемо легко скласти список невинних жертв, просто надрукувавши перший елемент, який слід перенести під час ітерації 2 та кожної непарної ітерації. Список йде: 2, 3, 5, 7, 10, 11, 13, 21, 17, 19, 30, 23, 27, 25, 29, 31, 45, 42, 37, 54, 41, 43, 65, ...
Теофіл

3
@ Sherlock9 Готово! Якщо це буде затверджено, це буде https://oeis.org/A266679 . Щасливого Нового року!
Теофіл

Відповіді:


5

Піф, 19 22

u-G*H^_!%GH/GHrhQ2Q

Досить наївна реалізація відповіді на голфскрипт @ PeterTaylor .

Спробуйте його онлайн тут

При цьому використовуються ті ж хитрощі, щоб перетворити цикл часу в складку, як це робить інша програма Pyth нижче.


u+G**H!%GHty%/GH2rhQ2Q

Наївна копія алгоритму @ Sp3000, перекладена на Pyth.

Ви можете спробувати онлайн тут

Використовує скорочення (ім'я пітона для fold), щоб імітувати цикл while. Він перераховує те, над range(input, 2)чим працює Pyth range(2, input)[::-1]. Інші гольфи, пов'язані з Pyth, передбачають використання notзамість <2та використання yприхованого режиму подвоєння значення числових аргументів.


21

> <>, 52 45 байт

Сторінка Esolangs для> <>

i:&&:&1-?vn;
2*1-*+20.>:&:&%1(&:&*{:}&:1-&,2%

Завдяки декількома необхідними модулями та множеннями існує багато елементів копіювання та переміщення. Логіка точно така ж, як і моє рішення Python .

Здійснює введення через кодову точку від STDIN, наприклад "!" = 33 -> 75.


10
І ви отримали нагороду за самий незручний формат введення коли-небудь: P
Caridorc

+1 все одно, не хвилюйся :)
Caridorc

@ Sp3000 IMO його слід вважати лише одним
SuperJedi224

@ SuperJedi224 Насправді, згідно з цим мета-повідомлення, мабуть, -vвважається трьома: /
Sp3000

17

Python 2, 58 байт

i=n=input()
while~-i:n+=(n%i<1)*i*(n/i%2*2-1);i-=1
print n

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


Назвемо крок k+1крок i, так що на кроці будуть замінені iвсі кратні iзнаки. Нам потрібні два простих спостереження:

  • Позиція nв масиві замінюється лише на кроці, iякщо nділиться на i,
  • Щоб сказати, чи є ви меншим чи більшим числом в свопі, подивіться n/i mod 2. Якщо це 1, ви будете меншим числом (і поміняєте його), інакше вищою цифрою (і будете змінювати місцями).

Це дає нам алгоритм роботи назад. Спробуємо це з 6, починаючи з останнього кроку (кроку i = 6):

Step 6: Position 6 swaps with position 12 (6 is divisible by 6, 6/6 = 1 == 1 mod 2)

Тож тепер ми знаємо, що число прийшло з позиції 12. Потім:

Step 5: No swap (12 not divisible by 5)
Step 4: Position 12 swaps with position 16 (12 is divisible by 4, 12/4 = 3 == 1 mod 2)

Тож тепер ми знаємо, що це було з 16 до цього. Нарешті:

Step 3: No swap (16 not divisible by 3)
Step 2: Position 16 swaps with position 14 (16 divisible by 2, 16/2 = 8 == 0 mod 2)

Оскільки це перший крок (пам’ятайте, k+1), ми зробили, і число, яке опиняється в позиції 6, спочатку прийшло з позиції 14, тобто 6-й номер рушниці - 14.

Отже, для пояснення Python:

i=n=input()             Read input, and store into i (step) and n (position)
while~-i:               while i-1 != 0:, or since we're descending with i this is just while i>1:
  n+=                   Add to the current position...
    (n%i<1)*            1* whatever's next if n is divisible by i, otherwise 0* (i.e. nothing)
    i*                  How many positions n might go up/down
    (n/i%2*2-1)         n/i%2 tell us higher/lower, *2-1 maps 0 or 1 to -1 (down) or +1 (up)
  i-=1                  Decrement the step number
print n                 Output

цікавий спосіб записати i-1як~-i
mbomb007

6
@ mbomb007: Погоджено. Розумний, хоча має той самий зміст, але позбавляє від необхідності місця після while. Гарна робота, Sp3000.
Олексій А.

Найкоротше, що я міг отримати це в pyth, використовуючи скорочення:u+G**H!%GHty%/GH2rhQ2Q
FryAmTheEggman

1
@FryAmTheEggman, Sp3000, це ніхто з вас не збирається розміщувати?
Мартін Ендер

@ MartinBüttner Спочатку я не публікував це, оскільки вважав, що це занадто багато копії. Зараз я опублікую це як відповідь CW.
FryAmTheEggman

6

Хаскелл, 68 байт

n#k|mod k(2*n)<1=k-n|mod k n<1=k+n|k>0=k
s n=foldr((.).(#))id[2..n]n

Напевно, подальший гольф, особливо перший ряд. Це визначає функцію, sяка приймає nі повертає номер nрушниці.

map s [1..66]
[1,4,8,6,12,14,16,9,18,20,24,26,28,22,39,15,36,35,40,38,57,34,48,49,51,44,46,33,60,77,64,32,75,56,81,68,76,58,100,55,84,111,88,62,125,70,96,91,98,95,134,72,108,82,141,80,140,92,120,156,124,94,121,52,152,145]

Пояснення

Допоміжна функція #приймає два числа nі k, і повертає kth число у списку, визначеному, застосовуючи операцію заміни пари до кожного nth числа. Наприклад, застосувавши його до перших 20 чисел із результатами n = 4цього:

map (4#) [1..20]
[1,2,3,8,5,6,7,4,9,10,11,16,13,14,15,12,17,18,19,24]

Результат s nотримується шляхом зменшення ("складання") списку [2..n]функцією другого порядку (.).(#), яка приймає число mі функцію f(спочатку функцію ідентичності id) і повертає функцію, яка приймає kі повертає f (m # k). Наприклад, у випадку, n = 4коли список [2,3,4]зводиться до функції, яка приймає kта повертає id (4 # (3 # (2 # k))). idПотрібно лише для базового випадку n = 1, коли список порожній. Нарешті, ми даємо цій функції на вхід k = n, отримуючи nth число рушниці.



5

Рубін, 92 байти

def s(d,n)
d==1?n:s(d-1,n%d==0?n+(n%(d*2)==0?-d :d):n)
end
n=ARGV[0].to_i
print s(n,n).to_s

Моє перше зусилля з гольфовим кодом. Не ґрунтується на жодній іншій відповіді.


Тепер, коли я переглянув деякі інші, я помітив, що більшість просто визначають функцію, а не повну програму, яка приймає введення та виробляє вихід. ОП попросило провести повну програму з введенням і виходом. Чи прийнято ігнорувати такі вимоги?


84 байт

n=ARGV[0].to_i
d=n
while d>1
n+=(n%d==0?(n%(d*2)==0?-d :d):0)
d-=1
end
print n.to_s

Переглянувши інші відповіді та зрозумівши, що ітераційне рішення можливе.


2
Кілька вдосконалень для вашого байтового рішення: 1. Перейдіть ARGVдо $*чарівного глобального. 2. Не to_sпотрібне. 3. Замість того, dщоб призначити їх nокремим рядком, просто зробіть, d=n=...щоб стригти персонажа. Приємної роботи для вашого першого гольфу! :)
Дверна ручка

1
Де я прошу повну програму? "Ви можете написати програму або функцію ...";) (Це також за замовчуванням для код-гольф- викликів, але я зазвичай включаю його для повноти.)
Мартін Ендер

Щоб додати до пропозицій @ Doorknob, два набори дужок у n+=рядку непотрібні, і обидва випадки дії ==0можна сміливо змінити на <1.
Пітер Тейлор

5

Пітон 2, 97 79 символів

g=lambda n,k:n>1and g(n-1,k-(k%n<1)*n*(-1)**(k/n%2))or k
n=input()
print g(n,n)

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

редагувати: Тепер він друкує лише nчисло, а не перші nчисла. Звичайно, ітеративний підхід був би коротшим, але я не хочу копіювати код Sp3000.


Так, я думаю, що всі сходяться на цьому. Мені ця g(i,i)частина особливо дратувала ...
Sp3000

2
Мова повинна бути позначена як Python 2 через printвисловлювання.
mbomb007

@ mbomb007 Виправлено.
Якубе

4

Хаскелл, 79 байт

1#i=i
s#i|i`mod`(2*s)==0=(s-1)#(i-s)|i`mod`s==0=(s-1)#(i+s)|1<2=(s-1)#i
p n=n#n

Використання: p 66які виходи145

Не так багато для пояснення: Функція #рекурсивно обчислює кількість рушниці в положенні iкроку s. p nповертає число в позиції nкроку n.


О, я не бачив вашої відповіді, перш ніж надсилати свою. Схоже, у нас досить різні підходи.
Згарб

4

k, 41 байт

{{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]}

 / apply to an int
 {{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]} 42
111
 / apply to 1 through 66
 {{x+$[y!x;0;$[2!_x%y;y;-y]]}/[x;|2+!x-1]}'1+!66
1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38 57 34 48 49 51 44 46 33 60 77 64 32 75 56 81 68 76 58 100 55 84 111 88 62 125 70 96 91 98 95 134 72 108 82 141 80 140 92 120 156 124 94 121 52 152 145
  • {...} лямбда, x і y - неявні 1-й та 2-й аргументи
  • $[b;t;f] потрійний оператор, оцінює b з наступним t / f відповідно
  • b!a модуль b
  • _ пол, кидає результат поділу на цілий
  • % поділ
  • {...}/[x;y] prime {...} з x і застосовується над списком y, еквівалентно f [f [.. f [f [x; y0]; y1]; .. yn-1]; yn]
  • | реверс
  • ! функція iota, генеруйте список від 0 до n-1

4

Common Lisp, 113 91

(ітеративний: 91)

(defun s(n)(do((r n(1- r)))((= r 1)n)(if(= 0(mod n r))(incf n(* r(if(oddp(/ n r))1 -1))))))

(оригінал, рекурсивна: 113)

(defun s(n &optional(r n))(cond((= r 1)n)((= 0(mod n r))(s(+ n(* r(if(oddp(/ n r))1 -1)))(1- r)))(t(s n(1- r)))))

Приклад

З рекурсивною версією:

(trace s)
(s 10)

  0: (S 10)
    1: (S 20 9)
      2: (S 20 8)
        3: (S 20 7)
          4: (S 20 6)
            5: (S 20 5)
              6: (S 15 4)
                7: (S 15 3)
                  8: (S 18 2)
                    9: (S 20 1)
                    9: S returned 20
         ...
    1: S returned 20
  0: S returned 20

Тести

Перевірки та заходи для ітеративної версії:

(let ((list '(1 4 8 6 12 14 16 9 18 20 24 26 28 22 39 15 36 35 40 38 57 34 48 49 51 44
              46 33 60 77 64 32 75 56 81 68 76 58 100 55 84 111 88 62 125 70 96 91 98 95
              134 72 108 82 141 80 140 92 120 156 124 94 121 52 152 145)))
  (time
   (loop for r in list
         for n from 1
         always (= r (s n)))))

 => T

Evaluation took:
  0.000 seconds of real time
  0.000000 seconds of total run time (0.000000 user, 0.000000 system)
  100.00% CPU
  807,160 processor cycles
  32,768 bytes consed

4

Математика, 53 49 байт

(For[i=n=#,n>1,--n,If[n∣i,i+=Mod[i,2n]2-n]];i)&

Я вирішив пограти в моє рефератне рішення. Символ Unicode для «вододілів», і розраховує на 3 байта. В іншому випадку для цього використовується той же алгоритм, що і всі інші.

Він визначає неназвану функцію, яка приймає nяк єдиний параметр і повертає номер nдробовика.


4

GolfScript, 27 символів

~.,(~%{):i\.@%!~)1$i/?i*-}/

Пояснення

Якщо f(i, n)є значення в положенні nпісля i-1перетворень, у нас є

f(1, n) = n
f(i, n) = f(i - 1, n % i == 0 ? (((n / i - 1) ^ 1) + 1) * i : n)  for i > 1

де ^позначає порозрядний xor; заданий вхід n, ми хочемо обчислити f(n, n).

Перетворення з рекурсивної функції в цикл є нецікавим; що цікаво - це спосіб

n % i == 0 ? (((n / i - 1) ^ 1) + 1) * i : n

можна переписати. Більш очевидний підхід - сказати, що так і має бути

n + (n % i == 0 ? i : 0) * g(n / i)

для деяких g. Очевидно gчергується між 1і -1, оскільки позиції міняються поперемінно вгору і вниз; оскільки g(1) = 1(тому що 1поміняється 2) ми маємо

n + (n % i == 0 ? i : 0) * -1**(1 + n / i)

де **позначає експоненцію. Остаточна економія виходить від переписування цього тексту як

n - i * (n % i == 0 ? -1 : 0)**(n / i)

Розсічення

~             # Evaluate input to get n
.,(~%{        # For n-1 downto 1...
  ):i         #   Let i be that value + 1, so for i = n downto 2...
  \.@%!       #   Find n % i == 0 ? 1 : 0
  ~)          #   Negate
  1$i/?       #   Raise to the power of n/i
  i*-         #   Multiply by i and subtract
}/

Бачачи, що ви маєте найкоротші відповіді GS та CJam, чому б не отримати найкоротшу відповідь Pyth? u-G*H^_!%GH/GHrhQ2QЯкщо ви не хочете публікувати це самостійно, скажіть мені / додайте його до відповіді CW.
FryAmTheEggman

@FryAmTheEggman, я, можливо, не дуже практикуюсь у CJam, але я можу принаймні більше-менш читати. Я не маю поняття, що говорить Pyth у вашому коментарі, хоча з контексту я припускаю, що це відповідь на цю відповідь. Тож краще, щоб ви його опублікували, адже ви можете відповісти на запитання про це.
Пітер Тейлор


4

Джулія, 61 57 байт

n->(i=n;while~-i!=0 n+=(n%i<1)*i*(n÷i%2*2-1);i-=1;end;n)

Це створює неназвану функцію, яка приймає єдиний аргумент nі повертає номер nрушниці. Щоб зателефонувати, дайте ім’я, наприклад f=n->(...).

Приклади:

julia> for i = 1:10 println(f(i)) end
1
4
8
6
12
14
16
9
18
20

В даний час це засновано на дивовижній відповіді Python @ Sp3000 . Я незабаром перегляну це, бо в Джулії має бути коротший шлях, ніж те, що я тут зробив. Будь-який вклад вітається, як завжди.



3

CJam, 28 27 байт

Тож це трохи бентежить ... перед тим, як опублікувати це, я сам спробував займатися гольфом і дістався до 30 байт у CJam. Жодна з існуючих відповідей поки що не перемогла. Тим часом мені також вдалося відголити ще три байти. У коментарі є коротше рішення Pyth, але нічого більш короткого не було розміщено у відповіді, так ось воно. Можливо, це надихає людей APL / J спробувати трохи важче (чи хтось насправді розміщує рішення Pyth), перш ніж мені доведеться прийняти власну відповідь. ;)

l~__(,f-{_I_+%_+I-_zI=*+}fI

Перевірте це тут.

Пояснення

l~                          "Read input N and eval.";
  __(,                      "Duplicate twice, create range [0 1 2 ... N-2].";
      f-                    "Subtract each from N, giving [N N-1 N-2 ... 2].";
        {               }fI "For each element, storing the element in I.";
         _I_+%_+I-          "Compute 2(N % 2I)-I - the shuffling offset";
                  _zI=      "Check that this offset is ±I.";
                      *+    "Multiply the offset by this boolean and update to N.";



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.