Numery Rycerza Numpada

33

Dla niezerowych cyfr na standardowej klawiaturze numerycznej

789
456
123

rozważ umieszczenie rycerza szachowego przy dowolnej cyfrze i przesuwanie go dowolną liczbą normalnych skoków w kształcie litery L, wykrywając dodatnią liczbę całkowitą dziesiętną. Jakie dodatnie liczby całkowite można wyrazić w taki sposób?

Jednym z nich jest to 38, że rycerz może zacząć od 3i przejść w lewo i do góry 8. 381i 383są również możliwe.

3samo jest możliwe, jeśli nie wykonano żadnych skoków (co jest dozwolone). 5jest również, ale nie można uzyskać dostępu do innych cyfr od 5, więc jest to jedyna liczba, w której 5pojawia się cyfra .

Napisz program lub funkcję, która przyjmuje dodatnią liczbę całkowitą dziesiętną (w razie potrzeby możesz ją traktować jako ciąg) i wypisuje lub zwraca prawdziwą wartość, jeśli liczba może być wyrażona przez rycerza na klawiaturze numerycznej w opisany sposób, ale w przeciwnym razie zwraca wyniki falsy wartość.

Najkrótszy kod w bajtach wygrywa. Tiebreaker to wcześniejsza odpowiedź

Przykłady

Prawda:

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
Hobby Calvina
źródło
2
Co dziś z szachowymi rycerzami ? :-D
Luis Mendo 18.04.16
1
Wskazówka: jeśli wypiszesz liczby jako linię zawijania, rycerz zawsze skacze albo o cztery pola zgodnie z ruchem wskazówek zegara, albo o cztery pola przeciw. Nie wiem czy to jest pomocne.
Pozew Fund Moniki w dniu
3
@LuisMendo Wrapping. Tak jak w przypadku, gdy traktujesz jako niekończącą się listę 78963214, powtarzaną w kółko. Policz odległości - zawsze są cztery, w jedną stronę lub w drugą. Powinienem był wyrazić jasno i wyraźnie powiedzieć, że musisz pisać w kolejności kręgu.
Pozew Fund Moniki
@QPaysTaxes Oh, myślałem, że masz na myśli krąg, ale 123...9. Przepraszamy
Luis Mendo 18.04.16
@LuisMendo Bez obaw. Tak jak powiedziałem, powinienem był jaśniej zrozumieć, co miałem na myśli.
Pozew funduszu Moniki

Odpowiedzi:

16

Galaretka, 19 15 14 bajtów

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

Wypróbuj online! lub zweryfikuj wszystkie przypadki testowe .

Jak to działa

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.
Dennis
źródło
18

Python 2, 52 bajty

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

Sprawdza, czy dowolne dwie kolejne cyfry są w ciągu '18349276167294381'. Aby uzyskać kolejne cyfry, zamiast robić zip(`n`,`n`[1:]), funkcja wielokrotnie sprawdza ostatnie dwie cyfry i usuwa ostatnią cyfrę.

xnor
źródło
13

Siatkówka , 58 40 bajtów

Dziękujemy Sp3000 za zasugerowanie tego pomysłu:

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

Wypróbuj online! (Nieznacznie zmodyfikowany, aby uruchomić cały zestaw testów na raz.)

Drukuje 1dla prawdziwych i 0fałszywych wyników.

Wyjaśnienie

M&!`..

Znajdź wszystkie pokrywające się dopasowania .., tj. Wszystkie kolejne pary cyfr, i połącz je liniami.

O%`.

Sortuj cyfry w każdym wierszu, abyśmy musieli sprawdzić tylko o połowę więcej par.

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

Usuń wszystkie wiersze odpowiadające prawidłowemu ruchowi.

^$

Policz dopasowania tego wyrażenia regularnego. Oznacza to, że jeśli wszystkie linie zostały usunięte, to jeden raz dopasowuje wynikowy pusty łańcuch, w przeciwnym razie nie pasuje i daje zero.

Martin Ender
źródło
7

Pyth - 35 28 bajtów

!s.bt/@c`C"_xÖ({ζz"2tsNYztz

Pakiet testowy .

Maltysen
źródło
7

Rubinowy, 57 bajtów

Funkcja anonimowa. Argument jest ciągiem.

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

Program z pakietem testowym:

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]]}

Właśnie zakodowałem wszystkie możliwe ruchy rycerza w łańcuch i sprawdziłem, czy co 2 cyfry w danych wejściowych istniały w tym łańcuchu.

Wartość tuszu
źródło
Och, ten ciąg wyszukiwania zaoszczędziłby mi również 17 bajtów. Czy masz coś przeciwko, jeśli użyję tego do mojej odpowiedzi Retina?
Martin Ender
Idź po to! Po prostu daj kredyt, tak myślę.
Wartość tuszu
Dzięki, ale skończyło się na jeszcze krótszym rozwiązaniu opartym na sugestii Sp3000 :)
Martin Ender
6

grep 58 bajtów

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

Ponieważ naprawdę, jeśli nie możesz pokonać grepa ...

Jak
źródło
2
Ani 5ani 185emitować 1z linii poleceń, podczas gdy 5jest w truthy, a 185na liście falsy.
Guntram Blohm wspiera Monikę
1
@GuntramBlohm naprawiono - zgubiłem się w regularnych zaprzeczeniach
Yakk
6

Haskell 46 bajtów

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

Przykład użycia: all(`elem`q"16729438183492761").q $ "183492761"->True

Jak to działa: wykorzystuje ciąg wyszukiwania znaleziony w odpowiedzi @Kevin Lau . qtworzy listę par sąsiednich znaków z łańcucha, np q "1672" -> [('1','6'),('6','7'),('7','2')]. Funkcja zwraca true, jeśli wszystkie pary z danych wejściowych pojawiają się w parach z ciągu wyszukiwania. qzamienia jednocyfrowe dane wejściowe w pustą listę, więc elemzawsze się udaje.

nimi
źródło
Dlaczego zip<*>taildziała jak odwrócona wersja zip=<<tail? Myślę, że nie rozumiem, co uogólniają aplikacje.
xnor 18.04.16
@xnor: Po prostu go używam. <*> jest zdefiniowany jako (<*>) f g x = f x (g x) .
nimi
6

JavaScript (ES6), 65 62 bajtów

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

Zwraca true lub false. Wcześniej próbowałem rozwiązania rekurencyjnego, które zajmuje 63 bajty, mapa nawet reducezajęło mi 73 bajty.

Edycja: Zapisano 3 bajty dzięki @ user81655.

Neil
źródło
Nie mogłem zrobić nic lepszego, moja najlepsza próba miała 88 bajtów. Brawo!
Naouak 18.04.16
@ user81655 Masz na myśli, że matchdziała zamiast ~search(ale tak czy inaczej, to naprawdę niedoceniane) i |może zastąpić ||(ale nie w wersji rekurencyjnej, niestety).
Neil
@ user81655 Miałem na myśli sposób, w jaki to !i|...matchdziała, ponieważ wynik dopasowania, jeśli się powiedzie, jest tablicą pojedynczego ciągu dwóch cyfr, który |operator ostatecznie wymusza na prawidłową liczbę całkowitą.
Neil,
@Neil Ah, racja.
user81655 19.04.16
6

DO, 85 81 bajtów

Gra w golfa:

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

Stara nierekurencyjna wersja (85 bajtów):

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

Stary kod z białą spacją i programem głównym:

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;
}

To akceptuje liczby rozdzielane spacjami przez standardowe wejście i wyjście 0, jeśli nie jest rycerzem-numpadem, lub 1 inaczej.

Nowa 81-bajtowa wersja rekurencyjna goli 4 bajty.

Tucuxi
źródło
5

MATL , 38 37 29 bajtów

Wykorzystuje to pomysł @QPaysTaxes .

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

Dane wyjściowe to złożona, niepusta tablica 2D. Prawdą jest, że wszystkie jej wartości mają niezerową część rzeczywistą, a fałsz w przeciwnym razie.

Wypróbuj online!

Luis Mendo
źródło
1
Czy to w ogóle dozwolone?
CalculatorFeline
Pytanie prosi o truthy lub o wartości falsy, a nie cały szereg.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
2
@CatsAreFluffy To jest nasza definicja prawdy / fałszu. Podobnie jak w MATLAB / Octave, tablice są prawdziwe w MATL, jeśli wszystkie jego elementy są prawdziwe. ( przykład )
Dennis
CC @ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Dennis
4

MATL, 25 24 33 26 bajtów

Wygolono 1 bajt dzięki @LuisMendo!
@Dennis znalazł błąd, a następnie go naprawił! Dzięki!

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

Pobiera na wejściu liczbę całkowitą. Wyjścia 1/0.

Wypróbuj online!

zlewka
źródło
@LuisMendo W obu przypadkach, dzięki!
zlewka
@Dennis Zaktualizowano i mam nadzieję, że jest poprawny. Dzięki za pomoc.
zlewka
Nie sądzę, żebyś potrzebował Ana końcu. Wektory MATL-a są prawdą, jeśli nie zawierają 0.
Dennis,
4

C, 140 92 bajtów

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

Zakładając ASCII

Szczegółowe Wypróbuj tutaj

// 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
}
Khaled.K
źródło
te tabele wyszukiwania są ogromne. Możesz znacznie poprawić swój wynik, jeśli pozbędziesz się wszystkich ograniczników {,}[]i char*zamiast tego zakodujesz go jako ciąg. Pamiętaj również, że #definenie jest to opłacalne, gdy używasz go tylko dwa razy: usunięcie go zaoszczędzi 4 bajty.
tucuxi,
@tucuxi dzięki za wskazówki, udało mi się obniżyć go do 92, ponieważ \0wewnątrz tablicy spowodował niezdefiniowane zachowanie, więc zastąpiłem gox
Khaled.K
Fajnie - nie zapomnij też użyć do <s>oldscore</s> newscoreedycji, aby odzwierciedlić poprawę wyników, a <!-- language-all: lang-c -->zanim kod zacznie poprawiać podświetlanie składni. Udało mi się również nieco zmniejszyć liczbę bajtów, porzucając całkowicie pętlę
tucuxi,
Twój „szczegółowy” wygląda zupełnie inaczej niż zwykłe rozwinięcie kodu golfowego (gdzie jest nkrótka wersja?). Ponadto prawdopodobnie powinieneś wspomnieć, że zakładasz kodowanie ASCII - otrzymasz różne liczby na maszynach EBCDIC.
Toby Speight
@TobySpeight the detailed version is supposed to show how it was built basically, yes I'm assuming ASCII which is the common case in C.
Khaled.K
3

Julia, 51 49 bytes

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

Verification

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
Dennis
źródło
3

Actually, 30 bytes

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

Takes input as a string. Outputs a positive integer for true and 0 for false.

Try it online!

Explanation:

;#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
Mego
źródło
3

PowerShell v2+, 105 96 bytes

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

Iterates through the input (which must be encapsulated with "") by verifying that the index of any sequential pair of characters is in the valid lookup string. I see Kevin Lau had something similar, but I came up with this independently. Each of those indices are added with +1, as the .IndexOf() function will return -1 if the string isn't found. This will turn "not found"s into 0.

We then -join all the resultant integer values with * and pipe that to iex (similar to eval). This will mean if any one of the indices is not found, the entire expression will result in 0. That is encapsulated in parens and -or'd with $a-eq5 for the special case of input "5" to achieve our resultant output.

Test Runs

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
AdmBorkBork
źródło
2

C, 78 bytes

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

Since everyone else has taken the input as a string, I tried doing it in integers. It works recursively from the least-significant digit (a%10); if it's the only digit, then return true. Otherwise, return true only if the tens digit (b%10) can't be reached from the units digit, and (recursively), the rest of the input satisfies the same test.

The test for reachability works by encoding the knight's tour linearly, and converting each digit to its position (zero to seven) on the tour. For digits 0 and 5, we assign position nine, which is disconnected from the other positions. Then, mutually reachable numbers differ by one (mod eight); i.e. a[x%10]-a[b%10] is either ±1 or ±7. So we test the absolute difference (mod 6) against 1.

This solution works for any character encoding that is valid for C (i.e. digits have contiguous codes from 0 to 9).

Toby Speight
źródło
1

Java 8, 179 167 Bytes

Places the number pad ints (minus 5 and 0) in a circle. l holds the circle index of these ints. If the difference of two indices is +/- 3 mod 8, then there is a knights move between the ints corresponding to those indices. Note that x is an 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;}

Update

  • -11 [16-12-10] Switched to a lambda
  • -1 [16-12-10] Use <2 instead of ==1
NonlinearFruit
źródło