Шлях Гну


23

Гольф - програма або функція, яка дає розташування гну, яка починається з квадрата на нескінченній шаховій дошці, яка пронумерована в квадратній спіралі проти годинникової стрілки, де гну завжди відвідує квадрат з найменшим числом вона може досягти того, що вона ще не відвідувала.nth 11

Натхнення: захоплений лицар та OEIS A316667 .

Редагувати: Ця послідовність тепер знаходиться на OEIS як A323763 .

Код може створювати розташування , перші розташування або генерувати послідовність, не жодного вводу.nthn

Сміливо вкажіть її місце розташування після (або до) скачок натомість, але якщо так, то, будь ласка, це чітко вкажіть у своїй відповіді та переконайтесь, що введення дає (або, якщо це доречно).nn=01[1]

Це , тому метою є створення робочого коду в якомога менше байтах на обраній вами мові.

Зауважте: гнів стає в пастці (так само, як і лицар у його розташування , площа , А верблюд - у , квадрат ) на її розташування на площі . Поведінка вашого коду може бути не визначено на більше, ніж це. (Завдяки Deadcode за код C ++, який знайшов це!)2016th20843723rd708112899744968th12851850258n

Деталь

Дошка виглядає нижче, і продовжує нескінченно:

101 100  99  98  97  96  95  94  93  92  91
102  65  64  63  62  61  60  59  58  57  90
103  66  37  36  35  34  33  32  31  56  89
104  67  38  17  16  15  14  13  30  55  88
105  68  39  18   5   4   3  12  29  54  87
106  69  40  19   6   1   2  11  28  53  86
107  70  41  20   7   8   9  10  27  52  85
108  71  42  21  22  23  24  25  26  51  84
109  72  43  44  45  46  47  48  49  50  83
110  73  74  75  76  77  78  79  80  81  82
111 112 113 114 115 116 117 118 119 120 121

Гну є «ГНУ» фея шахової фігури - нестандартне шахової фігури , які можуть рухатися як в якості лицаря (а -leaper) і в якості верблюда (а -leaper). Як така, вона могла переміститися в будь-яке з цих місць зі свого початкового місця розташування :(1,2)( 1 , 3 ) 1(1,3)
1

  .   .   .   .   .   .   .   .   .   .   .
  .   .   .   .  35   .  33   .   .   .   .
  .   .   .   .  16   .  14   .   .   .   .
  .   .  39  18   .   .   .  12  29   .   .
  .   .   .   .   .  (1)  .   .   .   .   .
  .   .  41  20   .   .   .  10  27   .   .
  .   .   .   .  22   .  24   .   .   .   .
  .   .   .   .  45   .  47   .   .   .   .
  .   .   .   .   .   .   .   .   .   .   .

Найнижча з них - і вона ще не відвідувала цю площу, тому - другий член у послідовності.1010

Далі вона могла переїхати з до будь-якого з цих місць:10

  .   .   .   .   .   .   .   .   .   .   .
  .   .   .   .   .   .  14   .  30   .   .
  .   .   .   .   .   .   3   .  29   .   .
  .   .   .   .   6   1   .   .   .  53  86
  .   .   .   .   .   .   . (10)  .   .   .
  .   .   .   .  22  23   .   .   .  51  84
  .   .   .   .   .   .  47   .  49   .   .
  .   .   .   .   .   .  78   .  80   .   .
  .   .   .   .   .   .   .   .   .   .   .

Однак вона вже відвідала площу тому її третє місцезнаходження - це площа , найнижча вона ще не відвідувала.13


Першими умовами шляху гну є:100

1, 10, 3, 6, 9, 4, 7, 2, 5, 8, 11, 14, 18, 15, 12, 16, 19, 22, 41, 17, 33, 30, 34, 13, 27, 23, 20, 24, 44, 40, 21, 39, 36, 60, 31, 53, 26, 46, 25, 28, 32, 29, 51, 47, 75, 42, 45, 71, 74, 70, 38, 35, 59, 56, 86, 50, 78, 49, 52, 80, 83, 79, 115, 73, 107, 67, 64, 68, 37, 61, 93, 55, 58, 54, 84, 48, 76, 43, 69, 103, 63, 66, 62, 94, 57, 87, 125, 82, 118, 77, 113, 72, 106, 148, 65, 97, 137, 91, 129, 85

Перші стрибків - лицарські ходи, тому перші термінів збігаються з A316667 .1112


Коментарі не для розширеного обговорення; ця розмова переміщена до чату .
Мего

Відповіді:


21

JavaScript (Node.js) ,  191 ... 166  164 байт

Збережено 2 байти завдяки @grimy .

Повертає й член.N

n=>(g=(x,y)=>n--?g(Buffer('QPNP1O?O@242Q3C3').map(m=c=>g[i=4*((x+=c%6-2)*x>(y+=c%7-2)*y?x:y)**2,i-=(x>y||-1)*(i**.5+x+y)]|i>m||(H=x,V=y,m=i))&&H,V,g[m]=1):m+1)(1,2)

Спробуйте в Інтернеті! або Дивіться відформатовану версію

Як?

Індекси спіралі

Для перетворення координат в індекс спіралі спочатку обчислюємо шар допомогою:(x,y)IL

L=max(|x|,|y|)

Що дає:

3210+1+2+333333333232222231321112303210123+13211123+23222223+33333333

Потім обчислюємо позицію у шарі за допомогою:P

P={2L+x+yif x>y(2L+x+y)if xy

Що дає:

3210+1+2+330123456210123471210125803210369+143234710+254567811+36789101112

Кінцевий індекс задається:I

I=4L2P

Примітка. Вищенаведена формула дає 0-індексовану спіраль.

У коді JS ми фактично обчислюємо відразу:4L2

i = 4 * (x * x > y * y ? x : y) ** 2

А потім відніміть допомогою:P

i -= (x > y || -1) * (i ** 0.5 + x + y)

Рухи гну

З огляду на поточне положення , 16 можливих цільових квадратів гну випробовують у такому порядку:(x,y)

321x+1+2+3391128101761213y+1541415+220+331

Ми проходимо по них, застосовуючи 16 пар підписаних значень . Кожна пара кодується як один символ ASCII.(dx,dy)

 ID | char. | ASCII code | c%6-2 | c%7-2 | cumulated
----+-------+------------+-------+-------+-----------
  0 |  'Q'  |     81     |   +1  |   +2  |  (+1,+2)
  1 |  'P'  |     80     |    0  |   +1  |  (+1,+3)
  2 |  'N'  |     78     |   -2  |   -1  |  (-1,+2)
  3 |  'P'  |     80     |    0  |   +1  |  (-1,+3)
  4 |  '1'  |     49     |   -1  |   -2  |  (-2,+1)
  5 |  'O'  |     79     |   -1  |    0  |  (-3,+1)
  6 |  '?'  |     63     |   +1  |   -2  |  (-2,-1)
  7 |  'O'  |     79     |   -1  |    0  |  (-3,-1)
  8 |  '@'  |     64     |   +2  |   -1  |  (-1,-2)
  9 |  '2'  |     50     |    0  |   -1  |  (-1,-3)
 10 |  '4'  |     52     |   +2  |   +1  |  (+1,-2)
 11 |  '2'  |     50     |    0  |   -1  |  (+1,-3)
 12 |  'Q'  |     81     |   +1  |   +2  |  (+2,-1)
 13 |  '3'  |     51     |   +1  |    0  |  (+3,-1)
 14 |  'C'  |     67     |   -1  |   +2  |  (+2,+1)
 15 |  '3'  |     51     |   +1  |    0  |  (+3,+1)

Ми відслідковуємо мінімальне зустрічається значення в та координати відповідної комірки в .m(H,V)

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

На першій ітерації ми починаємо з і . Це гарантує, що перша обрана комірка дорівнює і що це перша клітина, яка буде позначена як відвідувана.x=1y=2(0,0)


3
Стільки гольфу, що не можу дочекатися закінчення того, як працює вся магія!
Джонатан Аллан

чи довелося вам використовувати, Bufferщоб змусити кожного символу інтерпретуватись як один байт?
Йона

1
@Jonah Хоча його застаріло, Bufferконструктор все ще приймає рядок. Так, так, це досить дешевий спосіб перетворити його в список байтів - на відміну від [..."string"].map(c=>do_something_with(c.charCodeAt())).
Арнольд

1
-2 байти на кодування координат: TIO
Grimmy

@Grimy Чудово зроблено!
Арнольд

8

Кокосовий горіх , 337 276 байт

import math
def g((x,y))=
 A=abs(abs(x)-abs(y))+abs(x)+abs(y)
 int(A**2+math.copysign(A+x-y,.5-x-y)+1)
def f():
 p=x,y=0,0;s={p};z=[2,3,1,1]*2
 while 1:yield g(p);p=x,y=min(((a+x,b+y)for a,b in zip((1,1,2,-2,-1,-1,3,-3)*2,z+[-v for v in z])if(a+x,b+y)not in s),key=g);s.add(p)

Повертає генератор значень. Можливо, можна було б більше пограти в гольф. (Особливо послідовність різницевих кортежів.) Спіраль алгоритм узято з цього math.se відповіді .

Спробуйте в Інтернеті!


1
for a,b in (-> for a,b in((можливо, ви також можете покатати дельтовий кортеж кортежів)
Джонатан Аллан

1
Для qкортежів немає необхідності, і поштовий індекс коротший: 306 байт, можливо, все ще можна зіграти,
Джонатан Аллан

1
... як щодо цього 284? EDIT ... це для 278
Джонатан Аллан

1
FWIW, відповідь math.se має підміни x і y, і негативне відносно системи координат у цьому виклику (де позитивний x правильний, а y - вище). Не те, щоб це змінило симетричність, але все ж.
Deadcode

1
0.5-> .5для іншого збереження байта; A**2-> A*Aдля ще одного.
Джонатан Аллан

8

05AB1E , 77 65 58 57 52 байт

Xˆ0UF3D(Ÿ0KãʒÄ1¢}εX+}Dε·nàDtyÆ+yO·<.±*->}D¯KßDˆkèU}¯

-6 байт завдяки @Arnauld , використовуючи порт його формули.

Виводить перші значення у вигляді списку (десяткових знаків).n+1

Спробуйте в Інтернеті ( ïв нижньому колонтитулі видаляється, .0щоб зробити висновок більш компактним, але сміливо видаляйте його, щоб побачити фактичний результат).

Пояснення коду:

Xˆ             # Put integer 1 in the global_array (global_array is empty by default)
0U             # Set variable `X` to 0 (`X` is 1 by default)
F              # Loop the (implicit) input amount of times:
 3D          #  Push the list in the range [-3,3]: [-3,-2,-1,0,1,2,3]
     0K        #  Remove the 0: [-3,-2,-1,1,2,3]
       ã       #  Cartesian product with itself, creating each possible pair: [[3,3],[3,2],[3,1],[3,-1],[3,-2],[3,-3],[2,3],[2,2],[2,1],[2,-1],[2,-2],[2,-3],[1,3],[1,2],[1,1],[1,-1],[1,-2],[1,-3],[-1,3],[-1,2],[-1,1],[-1,-1],[-1,-2],[-1,-3],[-2,3],[-2,2],[-2,1],[-2,-1],[-2,-2],[-2,-3],[-3,3],[-3,2],[-3,1],[-3,-1],[-3,-2],[-3,-3]]
        ʒ   }  #  Filter this list of pairs by:
         Ä     #   Where the absolute values of the pair
          1¢   #   Contains exactly one 1
               #  (We now have the following pairs left: [[3,1],[3,-1],[2,1],[2,-1],[1,3],[1,2],[1,-2],[1,-3],[-1,3],[-1,2],[-1,-2],[-1,-3],[-2,1],[-2,-1],[-3,1],[-3,-1]])
 εX+}          #  Add the variable `X` (previous coordinate) to each item in the list
 D             #  Duplicate this list of coordinates
  ε            #  Map each `x,y`-coordinate to:
   ·           #   Double both the `x` and `y` in the coordinate
    n          #   Then take the square of each
     à         #   And then pop and push the maximum of the two
   Dt          #   Duplicate this maximum, and take its square-root
     yÆ        #   Calculate `x-y`
       +       #   And add it to the square-root
   yO          #   Calculate `x+y`
     ·         #   Double it
      <        #   Decrease it by 1
             #   And pop and push its signum (-1 if < 0; 0 if 0; 1 if > 0)
   *           #   Multiply these two together
    -          #   And subtract it from the duplicated maximum
   >           #   And finally increase it by 1 to make it 1-based instead of 0-based
  }D           #  After the map: Duplicate that list with values
    ¯K         #  Remove all values that are already present in the global_array
      ß        #  Pop the list of (remaining) values and push the minimum
       Dˆ      #  Duplicate this minimum, and pop and add the copy to the global_array
         k     #  Then get its index in the complete list of values
          è    #  And use that index to get the corresponding coordinate
           U   #  Pop and store this coordinate in variable `X` for the next iteration
             # After the outer loop: push the global_array (which is output implicitly)

Загальне пояснення:

Ми тримаємо всі результати (і тому значення, з якими ми вже стикалися) у програмі global_array, яка спочатку починається як [1].
Ми тримаємо поточну -координату в змінній , яка є спочатку .x,yX[0,0]

Список координат, до яких ми можемо дістати, виходячи з поточної координати є:x,y

[[x+3,y+1], [x+3,y-1], [x+2,y+1], [x+2,y-1], [x+1,y+3], [x+1,y+2], [x+1,y-2], [x+1,y-3], [x-1,y+3], [x-1,y+2], [x-1,y-2], [x-1,y-3], [x-2,y+1], [x-2,y-1], [x-3,y+1], [x-3,y-1]]

Список, який я згадую в поясненні коду вище, містить ці значення, до яких можна перейти, після чого додається поточний (зберігається в змінній ).x,yX

x,yx,y

T=max((2x)2,(2y)2)
R=T(xy+T)signum((x+y)21)+1

Яку ж формулу використовує @Arnauld у своїй відповіді , але написана інакше, щоб використовувати вбудовані 05AB1E для подвійних, квадратних, -1, +1 тощо.

(Якщо ви хочете побачити саме цю спіральну частину коду в дії: Спробуйте в Інтернеті .)

x,yglobal_array
global_arrayXx,y

Після того, як ми переглянемо inputкількість разів, програма виведе це global_arrayяк результат.


1
FWIW, ось порт моєї власної формули для перетворення координат у спіральні індекси. Це на 5 байт коротше, але вихід плаває. (Я не знаю, це проблема чи ні.)
Арнольд,

yy

@Arnauld Дякую, що економиться 5 додаткових байтів. :) РЕДАКЦІЯ: Про що ви вже згадували у своєму першому коментарі. ; p
Kevin Cruijssen
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.