A Numpad's Knight Numbers
Python 2, 52 bytes
f=lambda n:n<6or`n%100`in'18349276167294381'*f(n/10)
Checks that any two consecutive digits are in the string '18349276167294381'
. To get consecutive digits, rather than doing zip(`n`,`n`[1:])
, the function repeatedly checks the last two digits and removes the last digit.
Jelly, 19 15 14 bytes
Doȷ’d3ạ2\P€=2P
Try it online! or verify all test cases.
How it works
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.
Retina, 58 40 bytes
Thanks to Sp3000 for suggesting this idea:
M&!`..
O%`.
A`16|18|27|29|34|38|49|67
^$
Try it online! (Slightly modified to run the entire test suite at once.)
Prints 1
for truthy and 0
for falsy results.
Explanation
M&!`..
Find all overlapping matches of ..
, i.e. all consecutive pairs of digits, and join them with linefeeds.
O%`.
Sort the digits in each line, so that we only need to check half as many pairs.
A`16|18|27|29|34|38|49|67
Remove all lines which correspond to a valid move.
^$
Count the matches of this regex. That is, if all lines were removed, this matches the resulting empty string once, otherwise it fails to match and gives zero instead.