Лицарські номери «Numpad»


33

Для ненульових цифр на стандартній нумерації

789
456
123

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

Один з них полягає в 38тому, що лицар міг стартувати 3вперед і рухатися вліво і вгору 8. 381а 383також можливі.

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

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

Виграє найкоротший код у байтах. Тирбекер - це відповідь раніше

Приклади

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

Фальсі:

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

2
Що сьогодні з шаховими лицарями ? :-D
Луїс Мендо

1
Підказка: Якщо ви записуєте цифри як обгортковий рядок, то лицар завжди стрибає або чотири пробіли за годинниковою стрілкою, або лічильник чотирьох пробілів. Я не знаю, чи це корисно.
Позов по

3
@LuisMendo Обгортання. Як і в тому випадку, якщо ви ставитесь до нескінченного списку 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 байт. Ви не заперечуєте, якщо я використовую це для своєї відповіді на сітківку?
Мартін Ендер

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

Дякую, але я закінчив ще коротше рішення на основі пропозиції Sp3000 :)
Мартін Ендер,

6

grep 58 байт

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

Тому що дійсно, якщо ви не можете перемогти греп ...


2
Ні, 5ні 185випромінюйте за 1допомогою вашого командного рядка, поки 5він знаходиться в трибуні та 185в ложному списку.
Guntram Blohm підтримує Моніку

1
@GuntramBlohm виправлено - заблукало в регулярному запереченні
Yakk

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')]. Функція повертає істину, якщо всі пари з вхідних даних з'являються в парах з рядка пошуку. qперетворює однозначні входи в порожній список, тому elemзавжди це досягає успіху.


Чому це zip<*>tailпрацює як перевернута версія zip=<<tail? Я думаю, я не розумію, які програми узагальнюють.
xnor

@xnor: Я просто його використовую. <*> визначається як (<*>) f g x = f x (g x) .
nimi

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роботи, тому що результат збігу, якщо він є успішним, це масив з однієї рядка з двох цифр, який |оператор закінчує примусовим у дійсне ціле число.
Ніл

@Neil Ага, правильно.
користувач81655

6

C, 85 81 байт

Гольф:

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, якщо не-рицар-нумед, або 1 в іншому випадку.

Нова 81-байтна рекурсивна версія голить 4 байти.


5

MATL , 38 37 29 байт

Тут використовується ідея @QPaysTaxes .

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

Вихід - 2D, складний, не порожній масив. Це правдоподібно, якщо всі його значення мають ненульову реальну частину, а хибні в іншому випадку.

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


1
Це навіть дозволено ??
CalculatorFeline

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

2
@CatsAreFluffy Це наше визначення truthy / falesy. Як і в MATLAB / Octave, масиви є truthy в MATL, якщо всі його елементи є truthy. ( приклад )
Денніс

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
Khaled.K

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

Ваш "детальний" виглядає дуже відрізняється від простого розширення коду для гольфу (де це nу короткій версії?). Крім того, вам, мабуть, слід зазначити, що ви припускаєте кодування ASCII - на машинах EBCDIC ви отримаєте різні цифри.
Toby Speight

@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π

Вводиться як рядок. Виводить додатне ціле число для істинного та 0 для помилкового.

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

Пояснення:

;#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'd з $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.