Рыцарь Расстояние

24

В шахматах Рыцарь на сетке (x, y) может перейти к (x-2, y-1), (x-2, y + 1), (x-1, y-2), (x-1, y + 2), (x + 1, y-2), (x + 1, y + 2), (x + 2, y-1), (x + 2, y + 1) за один шаг. Представьте себе бесконечную шахматную доску, на которой только Рыцарь (0, 0):

Сколько шагов требуется для перемещения Рыцаря из (0, 0) в (t x , t y )?

входные

Два целых числа: t x , t y ;

-100 <t x <100, -100 <t y <100

Выход

Минимальные шаги, необходимые для перемещения Рыцаря с (0, 0) на (t x , t y ).

правила

  • код гольф

Testcases

  x    y -> out
  0,   0 ->  0
  0,   1 ->  3
  0,   2 ->  2
  1,   1 ->  2
  1,   2 ->  1
  3,   3 ->  2
  4,   0 ->  2
 42,  22 -> 22
 84,  73 -> 53
 45,  66 -> 37
 99,  99 -> 66
-45, -91 -> 46
-81,   1 -> 42
 11,  -2 ->  7

document.write('<div>');[..."EFEDEDCDCBCBCBCBCBCBCBCBCBCBCBCBCBCDCDEDEFE;FEDEDCDCBCBABABABABABABABABABABABCBCDCDEDEF;EDEDCDCBCBABABABABABABABABABABABABCBCDCDEDE;DEDCDCBCBABA9A9A9A9A9A9A9A9A9A9ABABCBCDCDED;EDCDCBCBABA9A9A9A9A9A9A9A9A9A9A9ABABCBCDCDE;DCDCBCBABA9A9898989898989898989A9ABABCBCDCD;CDCBCBABA9A989898989898989898989A9ABABCBCDC;DCBCBABA9A98987878787878787878989A9ABABCBCD;CBCBABA9A9898787878787878787878989A9ABABCBC;BCBABA9A989878767676767676767878989A9ABABCB;CBABA9A98987876767676767676767878989A9ABABC;BABA9A9898787676565656565656767878989A9ABAB;CBA9A989878767656565656565656767878989A9ABC;BABA98987876765654545454545656767878989ABAB;CBA9A987876765654545454545456567678789A9ABC;BABA98987676565454343434345456567678989ABAB;CBA9A987876565454343434343454565678789A9ABC;BABA98987676545434323232343454567678989ABAB;CBA9A987876565434323232323434565678789A9ABC;BABA98987676545432341214323454567678989ABAB;CBA9A987876565434321232123434565678789A9ABC;BABA98987676545432323032323454567678989ABAB;CBA9A987876565434321232123434565678789A9ABC;BABA98987676545432341214323454567678989ABAB;CBA9A987876565434323232323434565678789A9ABC;BABA98987676545434323232343454567678989ABAB;CBA9A987876565454343434343454565678789A9ABC;BABA98987676565454343434345456567678989ABAB;CBA9A987876765654545454545456567678789A9ABC;BABA98987876765654545454545656767878989ABAB;CBA9A989878767656565656565656767878989A9ABC;BABA9A9898787676565656565656767878989A9ABAB;CBABA9A98987876767676767676767878989A9ABABC;BCBABA9A989878767676767676767878989A9ABABCB;CBCBABA9A9898787878787878787878989A9ABABCBC;DCBCBABA9A98987878787878787878989A9ABABCBCD;CDCBCBABA9A989898989898989898989A9ABABCBCDC;DCDCBCBABA9A9898989898989898989A9ABABCBCDCD;EDCDCBCBABA9A9A9A9A9A9A9A9A9A9A9ABABCBCDCDE;DEDCDCBCBABA9A9A9A9A9A9A9A9A9A9ABABCBCDCDED;EDEDCDCBCBABABABABABABABABABABABABCBCDCDEDE;FEDEDCDCBCBABABABABABABABABABABABCBCDCDEDEF;EFEDEDCDCBCBCBCBCBCBCBCBCBCBCBCBCBCDCDEDEFE"].forEach(c=>document.write(c==';'?'<br>':`<span class="d-${c}">${c}</span>`));
document.write('<style>body{line-height:16px;color:rgba(255,255,255,0.2);}span{display:inline-block;width:16px;font-size:16px;text-align:center;}div{white-space:pre;}');[...'0123456789ABCDEF'].map((c,i)=>document.write(`.d-${c}{background:hsl(${60-4*i},80%,${65-2*i}%)}`));

Родственный OEIS

Вот некоторые OEIS для дальнейшего чтения

  • A018837 : Количество шагов, которое должен достичь рыцарь (n, 0) на бесконечной шахматной доске.
  • A018838 : Количество шагов, которое должен достичь рыцарь (n, n) на бесконечной шахматной доске.
  • A065775 : Массив T, читаемый по диагонали: T (i, j) = наименьшее количество ходов коня на шахматной доске (бесконечно во всех направлениях), необходимое для перехода от (0,0) к (i, j).
  • A183041 : Наименьшее количество ходов коня от (0,0) до (n, 1) на бесконечной шахматной доске.
ТТГ
источник
Вы можете взять ссылку на формулу, приведенную в oeis.org/A065775
tsh
2
Могу ли я принять ввод как комплексное число x+yi?
Линн
1
@lynn я думаю, что это приемлемо.
1818 года
@ user202729 обновил фрагмент кода, чтобы показать результат.
ч. В
Очень хорошая карта.
Willtech

Ответы:

11

Wolfram Language (Mathematica) , 64 байта

Использование встроенного KnightTourGraph.

Сохранено 2 байта благодаря Mathe172 .

GraphDistance[KnightTourGraph@@({x,y}=Abs@{##}+4),y+2,(x-2)y-2]&

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

ArrayPlot @ Массив [GraphDistance [KnightTourGraph @@ ({х, у} = {Абс @ ##} + 5), 2у + 3, (х-2) у-2] &, {65,65}, - 32]

alephalpha
источник
14
Mathematica
buildins
1
Немного короче:GraphDistance[KnightTourGraph@@({x,y}=Abs@{##}+5),2y+3,(x-2)y-2]&
Лукас Ланг
Что с этим языком? Почему все эти встроенные модули предварительно загружены? Попытка завершить фразу с помощью табуляции занимает много времени?
OganM
@OganM Mathematica не поддерживает автозаполнение в интерфейсе командной строки. Автозаполнение в интерфейсе ноутбука выглядит следующим образом .
alephalpha
1
@OganM Может быть, разработчики используют Trie (структуру данных) или просто бинарный поиск в списке отсортированных встроенных модулей. Да, почему линейный поиск? | Обратите внимание, что Mathematica - это несвободный язык с закрытым исходным кодом, поэтому никто не знает, как на самом деле работает предиктор. | Настоящие программисты не нуждаются в автозаполнении. : P
user202729
7

JavaScript (ES6), 90 75 72 байта

Вдохновлен формулой, приведенной для A065775 . Медленно, как ад для (не очень) больших расстояний.

f=(x,y,z=x|y)=>z<0?f(-y,x):z>1?1+Math.min(f(x-1,y-2),f(x-2,y-1)):z*3^x&y

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

Как?

Мы определяем z как побитовое ИЛИ между x и y .

Шаг 1

Сначала мы гарантируем, что мы находимся в определенном квадранте, заставляя и x и y быть неотрицательными. Пока z <0 (что означает, что x или y отрицательны), мы обрабатываем рекурсивный вызов f (-y, x) :

(+1, -2) --> (+2, +1)
(-1, +2) --> (-2, -1) --> (+1, -2) --> (+2, +1)
(-1, -2) --> (+2, -1) --> (+1, +2)

Шаг 2

В то время как у нас z> 1 (что означает, что x или y больше 1 ), мы рекурсивно пробуем два хода, которые приближают нас к (0, 0) : f (x-1, y-2) и f ( х-2, у-1) . Мы в конечном итоге держим кратчайший путь.

Шаг 3

Когда z меньше или равно 1 , у нас остается 3 возможности, которые обрабатываются z*3^x&y(мы могли бы использовать z*3-x*yвместо):

  • x & y == 1 подразумевает x | y == 1 и означает, что x = y = 1 . Нам нужно еще два хода, чтобы достичь (0, 0) :

    2 хода

  • х & у == 0 и х | y == 1 означает, что у нас либо x = 1 / y = 0, либо x = 0 / y = 1 . Нам нужно еще три хода, чтобы достичь (0, 0) :

    3 хода

  • х & у == 0 и х | y == 0 означает, что у нас уже есть x = y = 0 .

Графика позаимствована у chess.com

Arnauld
источник
5

Python 3 , 90 байт

Спасибо ТШ за -11 байт!

def f(x,y):x=abs(x);y=abs(y);s=x+y;return(.9+max(x/4,y/4,s/6)-s/2+(s==1or x==y==2))//1*2+s

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

(встроенное форматирование кода, чтобы читателям не приходилось прокручивать. Извините, но я должен сыграть в гольф мою программу)

Очень очень эффективный


Как я мог придумать это?

1. Соотношение

Предполагается, что вся доска окрашена в шахматном порядке (то есть клетки с x+yнечетными и x+yчетными окрашены в разные цвета).

Обратите внимание, что каждый шаг должен прыгать между двумя разноцветными ячейками. Следовательно:

  • Четность количества шагов должна быть равна четности x+y.

2. Аппроксимация

Предполагается, что рыцарь начинает с координаты (0,0)и прошел nшаги, и в данный момент находится на (x,y).
Для простоты предполагается x ≥ 0, что y ≥ 0.
Мы можем заключить:

  • Так как каждый шаг xувеличивается не более чем на 2, x ≤ 2×n. Точно так же y ≤ 2×n.
  • Так как каждый шаг x+yувеличивается не более чем на 3, x+y ≤ 3×n.

Поэтому n ≥ l(x,y)где l(x,y) = max(max(x,y)/2, (x+y)/3. (обратите внимание, что нам не нужно включать -xили x-yв формулу, потому что, по предположению x ≥ 0 and y ≥ 0, так x+y ≥ max(x-y,y-x,-x-y)и x ≥ -x, y ≥ -y)

Оказывается, a(x,y) = round(0.4 + l(x,y))это хорошее приближение к n.

  • Предположим, a(x,y)что это приближение с ошибкой меньше, чем 1правильное значение

    f(x,y) = round((a(x,y) - (x+y)) / 2) * 2 + (x+y)

    (округлить при вычитании x+yи делении на 2)

3. Особые случаи, которые не соответствуют формуле

Предположим x ≥ 0и y ≥ 0. В двух особых случаях сбой алгоритма:

  • x == 1 and y == 0или x == 0 and y == 1: алгоритм неверно возвращает, в 1то время как правильный ответ 3.
  • x == y == 2: Алгоритм неверно возвращает, 2пока правильный ответ 4.

Так что, просто особые случаи. Добавьте результат, 2если значение xи yявляются одним из них.

user202729
источник
1
@tsh Но это x==y==0тоже так.
user202729
Почему max(x+y,x-y,y-x)?
1818 года
@tsh: Нет, см: х = -5, у = 5 х + у = 0, абс (х , у ) = 10 и , следовательно , х + у <абс (ху)
Нова
@ Нова "Прими x ≥ 0и y ≥ 0".
user202729
4

TI-Basic, 86 54 байта

На основе более старого решения @ user202729

Input :abs(X->C:abs(Y->D:C+Ans
Ans+2int(.9+(S=1 or C=2 and D=2)-.5Ans+max({C/4,D/4,Ans/6
Timtech
источник
2

MATL , 29 байт

`JEQ2J-htZjht_h@Z^2&sG=~}@Gg*

Ввод представляет собой комплексное число с целыми действительными и мнимыми частями.

Код очень неэффективен. Требования к памяти увеличиваются экспоненциально с выходом. Время ожидания в TIO для тестовых случаев превышает 7.

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

Луис Мендо
источник
2

Haskell, 79 72 байта

p l|elem(0,0)l=0|r<-[-2..2]=1+p[(x+i,y+j)|(x,y)<-l,i<-r,j<-r,(i*j)^2==4]

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

Принимает ввод как единый список пар чисел.

Простая грубая сила. Требуется много времени и памяти для результатов> 8. Начиная с одного списка координат элемента (вход), многократно добавляйте все позиции, которые могут быть достигнуты для каждого элемента, пока не появится (0,0)в этом списке. Следите за уровнем рекурсии и возвращайте его как результат.

Изменить: -7 байт благодаря @Lynn.

Ними
источник
72 байта
Линн
1

JavaScript (ES6), 90 78 байт

f=(x,y)=>y<0?f(x,-y):x<y?f(y,x):x+y<3?4-x-y&3:x-3|y-1?x-4|y-3?f(x-2,y-1)+1:3:2

Редактировать: Сохранено 12 байтов благодаря @supercat, указывающему, что x<0подразумевает либо либо, y<0либо x<y. Пояснение: Это рекурсивное решение. Первые два условия просто обеспечивают правильный квадрант для других условий. Третье условие генерирует ответ для координат около начала координат, в то время как последние два условия относятся к двум другим особым случаям (на 1 байт меньше, чем проверка обоих ходов):

0
32
2++
+2++
+++3+
++++++
(etc.)

Все отмеченные квадраты +можно определить, двигаясь прямо к началу координат, а затем повторяя.

Нил
источник
Вам нужен x<0тест? Если, например, -3,6, то x<yтест превратится в 6, -3, из которого y<0тест превратится в 6,3, а x<yтест - в 3,6.
суперкат
@supercat В самом деле, как сказал бы Python, x>=y>=0...
Нил
1

Котлин , 148 146 140 байт

fun s(x:Int,y:Int):Int=if(y<0)s(x,-y)else
if(x<y)s(y,x)else if(x+y<3)4-x-y and 3
else if(x!=3||y!=1)if(x!=4||y!=3)s(x-2,y-1)+1
else 3 else 2

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

JohnWells
источник
Уверен, вам не нужно :Intуказывать тип возвращаемого значения.
therealfarfetchd
Рекурсивные функции требуют возвращаемого типа, так как компилятор не достаточно умен, чтобы определить тип.
JohnWells
1
О, я пропустил рекурсивные звонки. Упс
therealfarfetchd
1

Желе , 27 26 25 23 байта

1,-pḤµ;UÆị
¢ṗS€;0i
0ç1#

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

Очень медленно; Тайм-аут на TIO для выходов более 6. Принимает комплексное число в качестве ввода.

объяснение

Код использует комплексные числа, потому что он был короче на промежуточном этапе, и он также кажется намного быстрее; Вы можете также использовать пары путем удаления Æiи замены 0с 0,0на второй линии.

1,-pḤµ;UÆị    Helper link. No arguments.
1,-             Get the pair [1,-1].
    Ḥ           Double each to get [2,-2].
   p            Cartesian product: get [[1,2],[1,-2],[-1,2],[-1,-2]].
     µ          Start a new chain with the list of pairs as argument.
       U        Reverse each pair.
      ;         Append the reversed pairs to the list.
        Æi      Convert each pair [real,imag] to a complex number.

¢ṗS€;0i    Helper link. Arguments: iterations, target
¢            Call the previous link to get knight moves as complex numbers.
 ṗ           Get the iterations-th Cartesian power of the list. This will
             yield 8^n tuples containing move sequences.
  S€         Sum each move sequence to get the resulting square.
    ;0       Add the starting square, since the zeroth iteration results
             in no move sequences.
      i      Find the target squares (1-based) index in the results, or 0.

0ç1#    Main link. Argument: target
0         Starting from 0,
   #      find the
  1       first number of iterations where
 ç        calling the previous link results in a nonzero result.
PurkkaKoodari
источник