边缘骑士是冷酷的


48

介绍

阿伦·尼姆佐维奇(Aron Nimzowitsch)是一位领先的国际象棋大师和一位有影响力的国际象棋作家。

在他的书“我的系统”中,第一章讨论了中心的重要性以及为什么要主导中心。原因很简单,当您位于中心位置时,您的棋子有更多可能的直接下一步动作,这又使玩家拥有更大的力量。

当查看骑士的不同位置及其在空板上的潜在下一步动作(以粉红色显示)时,这一点非常清楚:

在此处输入图片说明

目的

根据骑士的位置,评估骑士在空板上可能进行的直接下一步行动的次数。

输入规格

骑士的位置。

首先是x(列),然后是y(行)。0 0是左下角。

为简单起见,我将棋盘的标签更改为仅数字。对于我们的示例和测试案例,我们使用基于0的索引,但是您可以自由使用基于1的索引。

您可以使用任何类型的可能的输入格式,数组,函数参数等。

输出规格

空板上一个骑士的潜在直接下一步移动次数。

测试用例

3 4 => 8
4 6 => 6
7 7 => 2
1 0 => 3

测试用例采用基于0的索引。完整的值网格为:

2 3 4 4 4 4 3 2
3 4 6 6 6 6 4 3
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
3 4 6 6 6 6 4 3
2 3 4 4 4 4 3 2

9
不错的第一个挑战!:-)
Luis Mendo

14
“边缘上的骑士很严峻”

2
@stacey您的评论对这个难题而言将是一个很好的标题:)
starcorder

6
现在要解决一个非常棘手的问题:以上图像中的红色骑士是否都具有相同的颜色?
mbomb007 '16

Answers:


25

Python 2,35个字节

lambda x,y:50/(8+x*x/7-x+y*y/7-y)-4

在线尝试!


Python 2,39个字节

lambda x,y:50/(8-x*(7-x)/5-y*(7-y)/5)-4

在线尝试!

输入0索引的输入。

表达x*(7-x)/5需要的坐标值0..7,以

[0, 1, 2, 2, 2, 2, 1, 0]

min(x,7-x,2)这样做是一样的,但是要更长一些。)对此求和xy给出正确的模式,但数字错误

0 1 2 2 2 2 1 0
1 2 3 3 3 3 2 1
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
1 2 3 3 3 3 2 1
0 1 2 2 2 2 1 0

(请参阅Neil的解决方案,以更好地了解为什么会给出正确的模式。)

最后,a -> 50/(8-a)-4使用楼板划分的映射给出正确的值

2 3 4 4 4 4 3 2
3 4 6 6 6 6 4 3
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
3 4 6 6 6 6 4 3
2 3 4 4 4 4 3 2

具有1索引输入的另一种等长解决方案:

lambda x,y:(x*(9-x)/6+y*(9-y)/6)**2/6+2

(7-a)*a/5比短3个字节min(a,7-a,2)
尼尔

1
*l实际上总共要花一个字节,lambda a,b:"23468"[(7-a)*a/5+(7-b)*b/5]只有41个字节。
尼尔

@Neil我刚刚发现了同x*(9-x)/6一个索引的东西。
xnor

1
您为什么<strike>不像其他所有人一样使用高尔夫球来显示高尔夫进度?
疯狂的2016年

4
@疯狂我认为它看起来很丑,实际上并没有帮助。代码很重要,任何想查看其演变的人仍然需要查看编辑历史记录。当我的旧代码足够不同以致于值得展示时,我将显示此处的版本。但是,在这个问题上,这只是对同一策略的微小改进,因此我发现它更干净,只是提到了不同的可能性。
xnor

17

MATL17 14 13 12字节

感谢@Neil关闭1个字节!

8:HZ^ZP5X^=s

输入基于1。

在线尝试!

说明

这将计算从输入到棋盘上64个位置中每个位置的欧几里得距离,并找出其中的多少等于5的平方根。

由于坐标是整数值,因此我们可以确保代表5的平方根的两个浮点值(从坐标计算出并直接计算出)确实相同。

8:      % Push array [1 2 ... 8]
H       % Push 2
Z^      % Cartesian power. Gives 2D array [1 1; 1 2; ... 1 8; 2 1; ... 8 8]     
ZP      % Implicit input. Compute Euclidean distances, considering each row as a point
5X^     % Square root of 5
=s      % Compute how many squared distances equal sqrt(5). Implicit display

1
令人印象深刻,并感谢您的解释
starcorder

1
如果由于舍入误差将5的平方根与5的平方根进行比较失败,您是否至少不能将5的平方根与5的平方根进行比较?
尼尔

@Neil感谢您的想法!是的,因为计算使用整数,所以我可以确定两个“ 5的根”是相同的double数字。蚂蚁保存了一个字节
Luis Mendo

15

Mathematica 63 43字节

感谢Martin Ender的建议,节省了20个字节!

EdgeCount[8~KnightTourGraph~8,#+1+8#2/<->_]&

上面的代码在完整的骑士巡回图表上找到距给定像元1跳的平方数。


g=KnightTourGraph[8,8,VertexLabels->"Name",Axes->True]

显示完整的骑士巡回图,以及顶点名称和坐标。请注意,Mathematica默认将坐标设为基于一的索引。

图形


#+1+8#2&[r,f]converts 使用从零开始的值作为输入,返回与等级(row)r和文件(column)处的正方形相对应的顶点f

例如#+1+8#2&[2,1]返回11。


EdgeCount 给出邻域图中的边数。


等级2的边,文件1(正方形11):

IncidenceList[8~KnightTourGraph~8, 8 #2 + # + 1] &[2, 1]

(*{1 <-> 11, 5 <-> 11, 11 <-> 17, 11 <-> 21, 11 <-> 26, 11 <-> 28}*)

突出显示的边缘:

HighlightGraph[g, {1, 5, 11, 17, 21, 26, 28, Style[1 <-> 11, Thick, Blue], Style[5 <-> 11, Thick, Blue], Style[11 <-> 17, Thick, Blue], Style[11 <-> 21, Thick, Blue], Style[11 <-> 26, Thick, Blue], Style[11 <-> 28, Thick, Blue]},GraphHighlightStyle -> "DehighlightFade", PlotRangePadding -> .5]

突出


方法2:欧几里得距离

70字节

该方法较长,但可能会引起人们的兴趣。该方法是检查棋盘中心与目标单元之间的欧几里得距离。

Which[(x=Sqrt@Tr[({3.5, 3.5}-#)^2])<2.2,8,x<3,6,x<4,4,x<4.6,3,x>4.6,2]&

举例说明

Which[(x=Sqrt@Tr[({3.5, 3.5}-#)^2])<2.2,8,x<3,6,x<4,4,x<4.6,3,x>4.6,2]&@{0, 0}
Which[(x=Sqrt@Tr[({3.5, 3.5}-#)^2])<2.2,8,x<3,6,x<4,4,x<4.6,3,x>4.6,2]&@{3, 3}

2

8


为了帮助可视化到棋盘中心的距离如何足以分配一个值。

values={{2,3,4,4,4,4,3,2},{3,4,6,6,6,6,4,3},{4,6,8,8,8,8,6,4},{4,6,8,8,8,8,6,4},{4,6,8,8,8,8,6,4},{4,6,8,8,8,8,6,4},{3,4,6,6,6,6,4,3},{2,3,4,4,4,4,3,2}};
f[x_]:=Text[x,#]&/@Position[values,x]r_~w~p_:=RegionMember[{3.5`,3.5`}~Disk~r,p]
h@y_:=Which[2.2~w~y,8,3~w~y,6,4~w~y,4,4.6~w~y,3,2<3,2]

Graphics[{Circle[{4.5, 4.5}, 2.3], Circle[{4.5, 4.5}, 3], 

圈子[{4.5,4.5},4],

圆[{4.5,4.5},4.6],展平[f / @ {2,3,4,6,8},1]},轴-> True,AxesOrigin-> {-1,-1}]


数字2.2、3、4和4.6是圆的半径。

图片


1
很棒的游览图
starcorder '16

20
KnightTourGraphMathematica及其内建函数... :-)
Luis Mendo

我认为#您的源代码结尾处(在之前])有一个流浪。您应该可以使用,IncidenceList而不是使用EdgeList@NeighborhoodGraph。(或者,也有EdgeCount,但我认为最终会更长。)
Martin Ender

1
哦,等等,它实际上更短:EdgeCount[8~KnightTourGraph~8,#+1+8#2<->_]&
Martin Ender

EdgeCount很酷!
DavidC

12

JavaScript(ES6),38个字节

(x,y)=>+"23468"[((7-x)*x+(7-y)*y)/5|0]

接受0索引的输入。说明:查看到中心距离的平方:

24.5 18.5 14.5 12.5 12.5 14.5 18.5 24.5
18.5 12.5  8.5  6.5  6.5  8.5 12.5 18.5
14.5  8.5  4.5  2.5  2.5  4.5  8.5 14.5
12.5  6.5  2.5  0.5  0.5  2.5  6.5 12.5
12.5  6.5  2.5  0.5  0.5  2.5  6.5 12.5
14.5  8.5  4.5  2.5  2.5  4.5  8.5 14.5
18.5 12.5  8.5  6.5  6.5  8.5 12.5 18.5
24.5 18.5 14.5 12.5 12.5 14.5 18.5 24.5

可达平方数分为五个范围:

8    0-5
6    5-10
4   10-15
3   15-20
2   20-25

我实际上计算了24.5-(3.5-x)** 2-(3.5-y)** 2 =(7-x)* x +(7-y)* y,因为这是一个较短的计算,但它所做的只是相反的乐队的顺序。


超级简洁且非常不错的方法,因此我不必再启动自己的JS解决方案了:)
starcorder

关于公式的要点等效于半径平方。我曾认为x*(7-x)这只是一个看起来像是向下的弧形0..7并且恰好曲线拟合的操作,但这解释了为什么在x与和求和时会产生如此好的图案y
xnor

11

果冻,10个字节

8ṗ2_³²S€ċ5

1个索引。接受形式为的单个参数[x,y]在这里尝试。

8ṗ2          Cartesian square [[1,1],[1,2]…[8,8]]
   _³        Subtract the input
     ²S€     Compute the norm of each vector
        ċ5   Count fives

丹尼斯保存了一个字节!


才11个字节,哇!
starcorder

我早上看到了这个问题,这是我认为有时间的时候会在Jelly中实现的确切算法。:P
PurkkaKoodari

8

Mathematica,44个 40字节

我目前在相同的字节数下有三种解决方案:

2[3,4,6,8][[Tr@⌊3.2-.8Abs[#-4.5]⌋]]&
Tr@⌈.85(4-Abs[#-4.5])⌉/.{5->6,6->8}&
⌊Tr@⌈.85(4-Abs[#-4.5])⌉^1.1608⌋&

所有这些都是未命名的函数,它们采用一对{3, 4}基于1 的坐标。

我试图想出一个明确的公式。整个板上的一般模式如下所示:

在此处输入图片说明

这些颜色的实际值(从最亮到最暗)为2, 3, 4, 6, 8。那是:

2 3 4 4 4 4 3 2
3 4 6 6 6 6 4 3
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
3 4 6 6 6 6 4 3
2 3 4 4 4 4 3 2

我们首先通过将原点移动到中心,利用绝对值并从中减去结果来利用对称性4。这使我们0.5可以3.5从各个角开始增加坐标。为了使中心坐标相同,我们需要映射0.5并映射1.5到不同的值和2.5并映射3.5到相同的值。这可以通过乘以0.8(给定{0.4, 1.2, 2., 2.8})并将结果取底来轻松完成。因此,现在我们{0, 1, 2, 2}距市中心有距离。如果将每个单元格中的坐标相加,则会得到此表:

0 1 2 2 2 2 1 0
1 2 3 3 3 3 2 1
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
2 3 4 4 4 4 3 2
1 2 3 3 3 3 2 1
0 1 2 2 2 2 1 0

对于所有可能的结果,它都有唯一的值,因此我们仅将其用作的索引2[3,4,6,8]

在第二个版本中,我们使用吊顶而不是地板。这样234已经是正确的,但是我们得到了5and 6而不是6and 8,所以我们用替换规则来手动更正。

最后,在第三个版本中,我们扩展56向上6,并8通过幂的手段,紧接着又地板操作。


我非常喜欢使用董事会常规模式的方法,太好了!
starcorder

6

APL,21个字符

{+/,5=+/¨×⍨(⍳8 8)-⊂⍵}

用英语:

  • (⍳8 8):8x8 rank-2数组,包含所有单元的坐标;
  • +/¨×⍨(⍳8 8)-⊂⍵:给定单元格相对于板上每个单元格的欧式距离的平方;
  • 5=:0/1的矩阵,其中1出现在等于5的平方距离处;
  • +/,:求平展矩阵之和

测试(来源1):

    f←{+/,5=+/¨×⍨(⍳8 8)-⊂⍵}
    f¨1+(3 4)(4 6)(7 7)(1 0)
8 6 2 3

以这种形式:

f←{+/,5=+/¨×⍨(⍳⍺)-⊂⍵}

左参数可以指定电路板的尺寸。因此8 8 f将适用于标准方形棋盘。但是在更大的矩形板上,测试用例会得出不同的结果。例如,在12x10板上:

    g←(10 12)∘f
    g¨1+(3 4)(4 6)(7 7)(1 0)
8 8 8 3

在APL术语中,矩阵是2级数组,关于单元格的内容没有说。多年(滥用)这些术语使我对此变得不敏感。我将为更传统的读者更新说明。谢谢。
lstefano

@Istefano将“等级”用作“维数”似乎也遭受相同的折磨:-P
Luis Mendo

我会...你是对的!您可以看到,自从我学习线性代数以来已经有一段时间了。我放弃了:-)
lstefano

1
完整程序,27:≢⍸5=+/¨×⍨-∘⎕¨⍳8 8 在线尝试!
阿达姆(Adám)

@亚当你的意思是17
NGN

6

Java- 160150字节

int m(int r,int c){int m=0,i,j;for(i=0;i<3;i+=2)for(j=0;j<3;j+=2){m+=r+i>0&r+i<9&c+2*j>1&c+2*j<11?1:0;m+=r+2*i>1&r+2*i<11&c+j>0&c+j<9?1:0;}return m;}

取消高尔夫:

public static int m(int r, int c) {
    int m=0;
    for(int i=-1;i<2;i+=2)
        for(int j=-1;j<2;j+=2){
            m += r+i>-1 && r+i<8 && c+2*j>0 && c+2*j<8 ? 1:0;
            m += r+2*i>0 && r+2*i<8 && c+j>1 && c+j<8 ? 1:0;
        }
    return m;
}

除了更改for循环的边界以节省4个字节外,非高尔夫代码是相同的。通过迭代每个可能的动作并执行边界检查(> 0和<8)来工作。使用偏移量为(1、2),(2、1),(-1、2),(-2、1)等的事实,并能够针对i和j的每个值检查2个移动。

编辑:由于Leaky Nun和u902383的建议,节省了10个字节。


这也很快,很好!
starcorder

那里有错误,已修复。
ejaszewski

1
int m=0,i=-1,j;保存一些字节
Leaky Nun

1
将逻辑AND更改为按位AND,这将允许您删除其他6个字符
user902383,2016年


5

Haskell,49个48字节

w=[0..7]
x%y=sum[1|a<-w,b<-w,(a-x)^2+(b-y)^2==5]

1
您可以将[0..7]变量保存为1个字节。
xnor

5

Java,81个字符(113字节)

int r(int a,int b){return "⍄䐲㑦晃䚈衤䚈衤䚈衤䚈衤㑦晃⍄䐲".codePointAt(a*2+b/4)>>(3-b%4)*4&15;}

将整个结果表编码为unicode表,然后通过按位运算获得适当的字节。

您可以在此处在线查看:https//ideone.com/K9BojC






1

其实是18个位元组

`;7-2km`MΣ8-:50\¬¬

在线尝试!

这实现了许多其他答案一直在使用的相同公式:50/(8-x*(7-x)//5+y*(7-y))//5)-4。输入被视为一个列表:([x,y]或Python中任何可迭代的文字,如(x,y)x,y)。

说明:

`;7-2km`MΣ8-:50\¬¬
`;7-2km`M           for each value in input:
 ;7-                  make a copy, subtract from 7
    2                 push 2
     km               minimum of the three values (x, 7-x, 2)
         Σ          sum
          8-        subtract from 8
            :50\    integer divide 50 by the value
                ¬¬  subtract 2 twice

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.