数字键的骑士数字


33

对于标准小键盘上的非零数字

789
456
123

考虑将一个国际象棋骑士放置在任何数字上,并以任意数量的正常L形跳动来移动它,找出正的十进制整数。用这种方式可以表示哪些正整数?

其中之一是38,因为骑士可以从3那里开始,然后向左和向上移动8381并且383也是可能的。

3如果不进行跳转(允许),则它本身是可能的。5也是,但是从不能到达其他数字5,因此它是5出现该数字的唯一数字。

编写一个程序或函数,该程序或函数需要一个正的十进制整数(如果需要,可以将其作为字符串),并且如果该数字可以由骑士在数字小键盘上以上述方式表示,则打印或返回真实值,否则输出一个falsy值。

以字节为单位的最短代码获胜。抢七是较早的答案

例子

真相:

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
Luis Mendo

1
提示:如果将数字写为换行符,则骑士总是沿顺时针方向跳四个空格或逆向跳四个空格。我不知道这是否有帮助。
Fund Monica的诉讼

3
@LuisMendo包装。就像,如果您将视为无休止的清单78963214,一遍又一遍地重复。计算距离–总是一个方向或四个方向的四个距离。我应该更清楚一些,并明确地说过您必须按圆圈顺序编写它。
Fund Monica的诉讼

@QPaysTaxes哦,我以为你是圈不过123...9。抱歉
Luis Mendo 2016年

@LuisMendo不用担心。就像我说的,我应该更清楚我的意思了。
Fund Monica的诉讼

Answers:


16

Jelly,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

Ruby,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回答吗?
Martin Ender

去吧!我想相信一点。
价值墨水

谢谢,但是根据Sp3000的建议,我最终得到了一个更短的解决方案:)
Martin Ender

6

grep 58字节

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

因为真的,如果您不能击败grep ...


2
既不5也不185EMIT 1与您的命令行,而5在truthy,并185在falsy列表。
Guntram Blohm支持Monica

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')]。如果输入中的所有对都出现在查找字符串中的对中,则该函数返回true。q将一位数字输入变成空列表,所以elem始终成功。


为什么会zip<*>tail像翻转版本的那样工作zip=<<tail?我认为我不理解应用程序的概括。
xnor

@xnor:我只是用它。<*> 定义为 (<*>) f g x = f x (g x)
nimi 2016年

6

JavaScript(ES6),65 62字节

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

返回true或false。我以前曾尝试过一个递归解决方案,它需要63个字节,并且map甚至reduce还花了我73个字节。

编辑:由于@ user81655,节省了3个字节。


无法做得更好,我的最佳尝试是88字节。太棒了!
Naouak '16

@ user81655你的意思是match作品,而不是~search(但无论哪种方式,这真的是秘密的),并|可以代替||(但不是在递归版本,可悲。)
尼尔

@ user81655我指的是!i|...match工作方式,因为匹配结果(如果成功)是由两位数字组成的单个字符串的数组,|运算符最终将其强制为有效整数。
尼尔

@尼尔,对。
user81655 '16

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

MATL38 37 29字节

这使用@QPaysTaxes的想法

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

输出是2D复杂的非空数组。如果所有值的实部都不为零,则为真,否则为假。

在线尝试!


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字节

感谢@LuisMendo,减少了1个字节!
@Dennis发现了一个错误,然后解决了!谢谢!

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

以整数作为输入。输出1/0。

在线尝试!


@LuisMendo两项都对,谢谢!
烧杯

@Dennis已更新,并希望更正。谢谢你的帮助。
烧杯

我认为A最后不需要。如果MATL的向量不包含0,则它们是真实的。–
Dennis,

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 '16

@tucuxi感谢您的提示,我设法将其降低到92,\0在数组内引起了未定义的行为,因此我将其替换为x
Khaled.K,2016年

很好-另外,<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π

将输入作为字符串。为true输出一个正整数,为false输出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

通过""验证任意连续字符对的索引是否在有效查找字符串中来遍历输入(必须用封装)。我看到凯文·刘(Kevin Lau)也有类似的事情,但我是独立提出的。这些索引中的每一个都添加了+1,因为如果找不到该字符串,该.IndexOf()函数将返回-1。这会将“未找到”变成0

然后,我们-join使用*并将所有结果整数值与管道连接到iex(类似于eval)。这意味着如果找不到任何索引,则整个表达式将为0。对于特殊的输入情况,将其封装在parens中并使用-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。否则,仅当b%10无法从单位数字达到十位数()时返回true ,并且(递归地)其余输入满足相同的测试。

到达性测试是通过对骑士的巡回旅程进行线性编码,然后将每个数字转换为其在巡回旅程中的位置(从零到七)来进行的。对于数字05,我们指定位置9,该位置与其他位置断开连接。然后,相互可到达的数字相差一个(模八)。即a[x%10]-a[b%10] ±1或±7。因此,我们针对1测试了绝对差(mod 6)。

该解决方案适用于对C有效的任何字符编码(即,数字具有从0到9的连续代码)。


1

Java的8,179个 167字节

将数字键盘的整数(减5和0)放置成一个圆圈。l保存这些整数的圆索引。如果两个索引的差是+/- 3 mod 8,则在与那些索引相对应的int之间会有骑士移动。请注意,这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]切换为lambda
  • -1 [16-12-10]使用<2代替==1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.