Numpad's Knight Numbers


33

Для ненулевых цифр на стандартной цифровой клавиатуре

789
456
123

рассмотрите возможность размещения шахматного рыцаря на любую цифру и перемещайте его с любым количеством нормальных L-образных прыжков, отслеживая положительное десятичное целое число. Какие натуральные числа можно выразить таким образом?

Один из них 38, так как рыцарь мог начать с 3и двигаться влево и вверх к 8. 381и 383тоже возможно.

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

Напишите программу или функцию, которая принимает положительное десятичное целое число (при желании вы можете взять его в виде строки) и печатать или возвращать истинное значение, если число может быть выражено рыцарем на цифровой клавиатуре описанным способом, но в противном случае выводит falsy значение.

Самый короткий код в байтах побеждает. Tiebreaker является более ранним ответом

Примеры

Truthy:

1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 18, 38, 61, 81, 294, 349, 381, 383, 729, 767, 38183, 38383, 18349276, 183492761, 618349276

Falsy:

10, 11, 50, 53, 55, 65, 95, 100, 180, 182, 184, 185, 186, 187, 188, 189, 209, 305, 2009, 5030, 3838384, 4838383, 183492760


1
Подсказка: если вы напишите числа в виде переносной строки, то рыцарь всегда прыгает либо на четыре пробела по часовой стрелке, либо на четыре пробела. Я не знаю, полезно ли это.
Фонд Моника иск

3
@LuisMendo Wrapping. Как и в случае, если вы рассматриваете это как бесконечный список 78963214, повторяется снова и снова. Посчитайте расстояния - это всегда четыре, так или иначе. Я должен был быть более ясным и прямо сказал, что вы должны написать это в порядке круга.
Фонд Моника иск

@QPaysTaxes О, я думал, что вы имели в виду круг, но 123...9. Извините
Луис Мендо

@ LuisMendo Не беспокойся. Как я уже сказал, мне следовало бы понять, что я имел в виду.
Фонд Моника иск

Ответы:


16

Желе, 19 15 14 байт

Doȷ’d3ạ2\P€=2P

Попробуйте онлайн! или проверьте все контрольные примеры .

Как это работает

Doȷ’d3ạ2\P€=2P  Main link. Argument: n (integer)

D               Convert n to base 10 (digit array).
  ȷ             Yield 1000.
 o              Logical OR. This replaces each 0 with 1000.
   ’            Decrement each digit.
    d3          Divmod; replace each digit k with [k:3, k%3].
      ạ2\       Pairwise reduce by absolute difference.
                For each pair of adjacent digits [i, j], this computes
                [abs(i:3 - j:3), abs(i%3 - j%3)].
         P€     Compute the product of each result.
                n is a Numpad's Knight Number iff all products yield 2.
           =2   Compare each product with 2.
             P  Multiply the resulting Booleans.

18

Python 2, 52 байта

f=lambda n:n<6or`n%100`in'18349276167294381'*f(n/10)

Проверяет, что любые две последовательные цифры находятся в строке '18349276167294381'. Чтобы получить последовательные цифры, вместо того, чтобы делать zip(`n`,`n`[1:]), функция многократно проверяет последние две цифры и удаляет последнюю цифру.


13

Сетчатка , 58 40 байт

Спасибо Sp3000 за предложение этой идеи:

M&!`..
O%`.
A`16|18|27|29|34|38|49|67
^$

Попробуйте онлайн! (Немного изменен для одновременного запуска всего набора тестов.)

Отпечатки 1для правдивых и 0ложных результатов.

объяснение

M&!`..

Найдите все совпадающие совпадения .., то есть все последовательные пары цифр, и объедините их с помощью перевода строки.

O%`.

Сортируйте цифры в каждой строке, чтобы нам нужно было проверить только половину числа пар.

A`16|18|27|29|34|38|49|67

Удалите все линии, которые соответствуют действительному ходу.

^$

Подсчитайте совпадения этого регулярного выражения. То есть, если все строки были удалены, это совпадает с полученной пустой строкой один раз, иначе это не соответствует и дает ноль вместо этого.



7

Рубин, 57 байт

Анонимная функция. Аргумент - это строка.

->n{(0..n.size).count{|i|!"16729438183492761"[n[i,2]]}<1}

Программа с набором тестов:

f=->n{(0..n.size).count{|i|!"16729438183492761"[n[i,2]]}<1}

a=%w{1 2 3 4 5 6 7 8 9 16 18 38 61 81 294 349 381 383 729 767 38183 38383 18349276 183492761 618349276
10 11 50 53 55 65 95 100 180 182 184 185 186 187 188 189 209 305 2009 5030 3838384 4838383 183492760}

a.each {|e|p [e, f[e]]}

Я только что закодировал все возможные ходы коня в строку и проверил, существуют ли каждые 2 цифры на входе в этой строке.


О, эта строка поиска также сэкономит мне 17 байт. Вы не возражаете, если я воспользуюсь этим для ответа на Retina?
Мартин Эндер

Действуй! Просто дайте кредит, я думаю.
Чернила стоимости

Спасибо, но я получил еще более короткое решение, основанное на предложении Sp3000 :)
Мартин Эндер,

6

grep 58 байт

grep "^((?=18|16|29|27|34|38|49|43|61|67|72|76|81|83|94|92).)*.$"

Потому что на самом деле, если вы не можете победить grep ...


2
Ни 5ни 185Испустите 1с командной строкой, в то время как 5находится в truthy, и 185в falsy списке.
Гунтрам Блом поддерживает Монику

1
@GuntramBlohm исправлено - потерялся в обычном отрицании
Якк

6

Haskell 46 байтов

q=zip<*>tail
all(`elem`q"16729438183492761").q

Пример использования: all(`elem`q"16729438183492761").q $ "183492761"->True

Как это работает: используется строка поиска, найденная в ответе @Kevin Lau . qСоставляет список пар соседних символов из строки, например q "1672" -> [('1','6'),('6','7'),('7','2')]. Функция возвращает true, если все пары из входных данных появляются в парах из строки поиска. qпревращает однозначные вводы в пустой список, поэтому elemвсегда получается.


Почему zip<*>tailработает как перевернутая версия zip=<<tail? Я думаю, что я не понимаю, что обобщают аппликативы.
xnor

@xnor: я просто использую это. <*> определяется как (<*>) f g x = f x (g x) .
Ними

6

JavaScript (ES6), 65 62 байта

s=>[...s].every((c,i)=>!i|"16729438183492761".match(s[i-1]+c))

Возвращает истину или ложь. Ранее я пробовал рекурсивное решение, которое занимает 63 байта, mapи даже, reduceно они заняли у меня 73 байта.

Редактировать: 3 байта сохранены благодаря @ user81655.


Не мог сделать лучше, моя лучшая попытка была на 88 байтов. Браво!
Науак

@ user81655 Вы имеете в виду matchработает вместо ~search(но в любом случае, это действительно закулисно) и |может заменить ||(но, к сожалению, не в рекурсивной версии.)
Нейл

@ user81655 Я имел в виду, как это !i|...matchработает, потому что результат совпадения, в случае успеха, представляет собой массив из одной строки из двух цифр, который |оператор в результате приводит к действительному целому числу.
Нил

@ Нил Ах, да.
user81655

6

C 85 81 байт

Golfed:

i;f(char*b){i=*b++-49;return*b?(*b=="8749x7214"[i]||*b=="6983x1632"[i])&&f(b):1;}

Старая нерекурсивная версия (85 байт):

i;f(char*b){for(;(i=*b++-49),*b&&*b=="8749x7214"[i]||*b=="6983x1632"[i];);return!*b;}

Старый код с пробелами и основной программой:

i;
f(char*b){
    for (; (i=*b++-49), *b     // i = index of digit + 1 in following arrays
        &&*b=="8749x7214"[i]   // 1st possible jump for 1..9
        ||*b=="6983x1632"[i];  // 2nd possible jump for 1..9
    );
    return !*b;
}

main(){
    char b[16];
    while(scanf("%s", b) == 1) printf("%d",f(b));
    return 0;
}

Это принимает разделенные пробелом числа через стандартный ввод и выводит 0, если не-numpad-knight, или 1 в противном случае.

Новая 81-байтовая рекурсивная версия экономит 4 байта.


5

MATL , 38 37 29 байт

Это использует идею @QPaysTaxes .

I:8JK5:7Pvj!Uttnqh?)d|2:EQm}h

Выходными данными является двумерный сложный непустой массив. Это правда, если все его значения имеют ненулевую вещественную часть, и ложно в противном случае.

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


1
Это даже разрешено ??
CalculatorFeline

Вопрос просит в truthy или в falsy стоимости, а не весь массив.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

2
@CatsAreFluffy Это наше определение истины / фальши. Как и в MATLAB / Octave, массивы верны в MATL, если все его элементы верны. ( пример )
Деннис

CC @ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Деннис


4

MATL, 25 24 33 26 байт

Скинул 1 байт благодаря @LuisMendo!
@Dennis нашел ошибку, а затем исправил ее! Благодарность!

'bSVYXbTUZW'j47-)d2^48\1=A

Принимает целое число в качестве входных данных. Выходы 1/0.

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


@ LuisMendo Правильно в обоих случаях, спасибо!
мензурка

@Dennis Обновлено, и, надеюсь, исправить. Спасибо за вашу помощь.
стакан

Я не думаю, что вам нужно Aв конце. Векторы MATL правдивы, если они не содержат 0.
Деннис

4

C 140 92 байта

c;L(char*i){while(*i&&(!c||*i=="6743x1212"[c-49]||*i=="8989x7634"[c-49]))c=*i++;return !*i;}

Предполагая ASCII

Подробно Попробуй здесь

// valid transition from x to n[x-'1'][0 or 1]

int n[9][2] =
{
    {'6','8'},{'7','9'},{'4','8'},
    {'3','9'},{'x','x'},{'1','7'},
    {'2','6'},{'1','3'},{'2','4'}
};

// i is a pointer to where to start on a string

bool L(char * i)
{
    char c = 0;

    // move if not \0 and (not-first-char or is a valid move)

    while((*i) && (!c || (*i)==n[c-'1'][0] || (*i)==n[c-'1'][1]))
    {
        c = (*i++);
    }

    return !(*i); // success if it's \0
}

эти таблицы поиска огромны. Вы можете значительно улучшить свой счет, если избавитесь от всех разделителей {,}[]и char*вместо этого закодируете его в виде строки. Также обратите внимание, что вы #defineне экономически эффективны, когда используете его только дважды: удаление его сэкономит вам 4 байта.
Tucuxi

@tucuxi спасибо за советы, мне удалось снизить его до 92, поскольку \0внутри массива x
возникло

Хорошо - также не забывайте использовать <s>oldscore</s> newscoreпри редактировании, чтобы отразить улучшения оценки, и <!-- language-all: lang-c -->прежде чем ваш код начнет исправлять подсветку синтаксиса. Мне также удалось немного уменьшить количество байтов, полностью сбросив цикл
tucuxi

Ваше «детальное» выглядит очень иначе, чем простое расширение гольф-кода (где nкороткая версия?). Кроме того, вам, вероятно, следует упомянуть, что вы принимаете кодировку ASCII - вы получите разные числа на машинах EBCDIC.
Тоби Спейт

@TobySpeight подробная версия должна показать, как она была построена в принципе, да, я предполагаю, что ASCII является распространенным случаем в C.
Khaled.K

3

Юлия, 51 49 байтов

n->diff(["@1634@8725"...][digits(n)+1]).^2%48⊆1

верификация

julia> f=n->diff(["@1634@8725"...][digits(n)+1]).^2%48⊆1
(anonymous function)

julia> all(map(f,(1,2,3,4,5,6,7,8,9,16,18,38,61,81,294,349,381,383,729,767,38183,38383,18349276,183492761,618349276)))
true

julia> any(map(f,(10,11,50,53,55,65,95,100,180,182,184,185,186,187,188,189,209,305,2009,5030,3838384,4838383,183492760)))
false

3

На самом деле, 30 байтов

;#pXZdX`Σ"67294381";'1+R+íu`Mπ

Принимает ввод в виде строки. Выводит положительное целое число для true и 0 для false.

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

Объяснение:

;#pXZdX`Σ"67294381";'1+R+íu`Mπ
                                 (implicit) push input
;#pXZdx                         push zip(n[:-1], n[1;]) (pairs of digits)
       `Σ"67294381";'1+R+íu`M   map:
        Σ                         join digits
         "67294381";'1+R+         push "16729438183492761" (the magic string used in many other solutions)
                         íu       0-based index (-1 if not found), increment so 0 is not found and >=1 is the 1-based index
                             π  product

3

PowerShell v2 +, 105 96 байт

param($a)((1..$a.length|%{'27618349294381672'.IndexOf($a[$_-1]+$a[$_])+1})-join'*'|iex)-or$a-eq5

Выполняет итерацию по входным данным (которые должны быть инкапсулированы ""), проверяя, что индекс любой последовательной пары символов находится в допустимой строке поиска. Я вижу, что у Кевина Лау было нечто подобное , но я придумал это самостоятельно. Каждый из этих индексов добавляется с помощью +1, поскольку .IndexOf()функция вернется, -1если строка не найдена. Это превратит «не найденные» в 0.

Затем мы получим -joinвсе результирующие целочисленные значения с *и передаем iex(аналогично eval). Это будет означать, что если какой-либо из индексов не будет найден, результатом будет все выражение 0. То заключено в круглых скобках , и -or«д с $a-eq5для частного случая ввода "5"для достижения нашего результирующего выходного сигнала.

Тестовые прогоны

PS C:\Tools\Scripts\golfing> 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 18, 38, 61, 81, 294, 349, 381, 383, 729, 767, 38183, 38383, 18349276, 183492761, 618349276 | %{.\numpad-knight-numbers.ps1 "$_"}
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True

PS C:\Tools\Scripts\golfing> 10, 11, 50, 53, 55, 65, 95, 100, 180, 182, 184, 185, 186, 187, 188, 189, 209, 305, 2009, 5030, 3838384, 4838383, 183492760 | %{.\numpad-knight-numbers.ps1 "$_"}
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False
False

2

C 78 байтов

char*a="9614397052";f(x){int b=x/10;return!b||abs(a[x%10]-a[b%10])%6==1&f(b);}

Поскольку все остальные воспринимают ввод как строку, я попытался сделать это целыми числами. Работает рекурсивно из наименее значащей цифры ( a%10); если это единственная цифра, верните true. В противном случае возвращайте значение true только в том случае, если цифра десятков ( b%10) не может быть достигнута из цифры единицы, и (рекурсивно) остальная часть входных данных удовлетворяет тому же критерию.

Тест на достижимость работает путем линейного кодирования тура коня и преобразования каждой цифры в ее позицию (от нуля до семи) в туре. Для цифр 0и 5мы назначаем девятую позицию, которая не связана с другими позициями. Тогда взаимно достижимые числа отличаются на единицу (мод восемь); то a[x%10]-a[b%10]есть либо ± 1, либо ± 7. Итак, мы проверяем абсолютную разницу (мод 6) против 1.

Это решение работает для любой кодировки символов, которая действительна для C (т. Е. Цифры имеют смежные коды от 0 до 9).


1

Java 8, 179 167 байт

Помещает числовые значения (минус 5 и 0) по кругу. lсодержит индекс круга этих целых. Если разность двух индексов составляет +/- 3 mod 8, то рыцари двигаются между интами, соответствующими этим индексам. Обратите внимание, что xэто int[].

x->{if(x.length<2)return 1;int[] l={0,0,1,2,7,0,3,6,5,4};int o=l[x[1]];for(int i:x){int n=l[i];if(i%5==0||(Math.abs(n-o)!=3&&Math.abs(n-o)!=5))return 0;o=n;}return 1;}

Обновить

  • -11 [16-12-10] переключился на лямбду
  • -1 [16-12-10] Используйте <2вместо==1
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.