抵制主教的密码


13

不要与密码主教善良相混淆!

给定一个字符串,请回答(真实/虚假或两个一致的值),如果它构成了对主教不利的密码。

密码是针对主教强,如果它是由交替字母(在串a-h)和数字(中1-8),使得每对字符可以被解释为在棋盘的正方形,如果你把一个白色的棋子上每平方命名使用密码,那么白色主教就无法以任何连续的顺序从第一1行中的任何正方形移动到最后一行中的任何正方形8

例子

对主教的密码很强

  • a1b1c1d1e1f1g1h1
  • a8b8c8d8e8f8g8h8
  • a1b2c3d4d5f5f4g3g4h2b5
  • h4g4f4e4c4b4a4c3e3
  • a1b1c1d1e1f1g1a8b8c8d8e8f8g8
  • b4b5d4d5f4f5g3h5

例如,a1b1c1d1e1f1g1a8b8c8d8e8f8g8对应于位置富b4b5d4d5f4f5g3h5对应于位置富

针对主教的密码薄弱

  • a4c4e4g4g5d6f6e3d2b2 (格式正确但不强壮-感谢Jo King提供的示例!)
  • b1c1d1e1f1g1h1a8b8c8d8e8f8g8 (格式正确但不强壮)
  • h4g4f4e4c4b4a4c3 (格式正确但不强壮)
  • d4 (格式正确但不强壮)
  • b4b5d4d5f4f5g2h5 (格式正确但不强壮)
  • correct horse battery staple (格式错误)
  • 1a1b1c1d1e1f1g8a8b8c8d8e8f8g (格式错误)
  • a (格式错误)
  • aa (格式错误)

1
主教继续进行什么颜色的方块?
无知的体现,

2
您的第二个测试用例与您的规格相矛盾。您还需要解释如何每对字符可以被解释为在棋盘方 ”。
毛茸茸的

1
a1b2c3d4d5f5f4g3g4h2b5对主教的态度不强,因为主教可以到达h5,然后下降到d1
无知的体现

2
@TRITICIMAGVS,乌鲁斯:我已经澄清说,典当和主教都是白色的,所以都不允许捕捉(或着陆,穿越或跳过)对方。
Quuxplusone

1
另外,您可以为其中一个真实的测试用例添加示例吗?因为我知道密码的方块充满了白色的棋子,但是我不知道白色的主教在哪里放置。如果可以的话,为什么不能在第一个测试用例中1遍历每一行8呢?由于a列已完全填充了典当,因此它无法行进到每一列,但是它可以行进到每一行而没有问题,不是吗?我有一种思念的感觉..:S
凯文·克鲁伊森

Answers:


4

红宝石,115个 182 163字节

->s{z=('00'..'99').map{|x|x=~/[09]/||s[(x[1].ord+48).chr+x[0]]};(11..18).map &g=->x{z[x]||[x-11,x-9,x+z[x]=9,x+11].map(&g)};s=~/^([a-h][1-8])*$/&&(z[81,9]-[9])[8]}

在线尝试!

回报1为强和nil弱。(+67字节用于考虑“回溯”。)

->s{
 z=                             # this is the board
 ('00'..'99').map{|x|           # coordinates are described as y*10 + x
  x=~/[09]/||                   # truthy if out of bounds...
  s[(x[1].ord+48).chr+x[0]]     # ...or impassable
 }                              # now only the passable squares are falsey
 (11..18).map                   # for each x position at y=1,
  &g=->x{                       # call helper function on that square
   z[x]||                       # if the square is passable (i.e. falsey),
    [x-11,x-9,x+z[x]=9,x+11]    # mark it impassable by setting to 9 (truthy)
     .map(&g)                   # call helper recursively for each neighbor
  }
 s=~/^([a-h][1-8])*$/           # make sure the input was valid,
 &&(z[81,9]-[9])[8]             # and check that the last row was never reached
}

使用了一些技巧:

  • 代替数字范围0..99,我们使用字符串范围,'00'..'99'以便将数字自动左填充到2位数字并进行字符串化。这使得边界检查非常短-与正则表达式匹配/[09]/

  • 在辅助函数内部,在构建新坐标列表的[x-11, x-9, x+9, x+11]同时,我们在此过程中同时分配z[x]9,这恰好是真实值(标记访问的平方)。

  • 在最后一行,我们要检查数组z[81,9]是否不包含9。为此,我们删除了9z[81,9]-[9])的所有实例,然后要求结果数组([8])的第9个元素。由于我们知道数组最初有9个元素,如果删除了任何元素,我们将得到nil,而如果所有元素都保留了,我们将获取数组的最后一个元素(碰巧总是1)。


2

Python 2中330个 318 313 309 370字节

import numpy as n
b=n.ones([8,8])
q=r=1
s=input()
l=len(s)
def g(x,y=0,p=0):
    if b[y,x]and p<32:
        if y<7:
            if x<7:
                g(x+1,y+1,p+1)
                if y:g(x+1,y-1,p+1)
            if x:
                g(x-1,y+1,p+1)
                if y:g(x-1,y-1,p+1)
        else:global q;q=0
for i in range(l/2):
    x=ord(s[2*i])-97;y=ord(s[2*i+1])-49
    if y>8or y<0 or l%2or x>8or x<0:r=0
    if r:b[7-y,x]=0
map(g,range(8))
print q&r

在线尝试!

在线尝试实用版本!(原始可能需要4 ^ 32次操作才能完全检查,我建议使用此操作-相同数量的字节)

这不是一个超短的解决方案-我不知道如何使g的lambda函数版本比g本身更短。

-4个字节,得益于Quuxplusone

+61字节用于回溯(感谢指出Jo King和高尔夫技巧)


真好 q=r=1会比短q=1 r=1,对吗?和if r:比短if r>0:
Quuxplusone

2

Python 2中490 476 474

def f(p):
 a=[set(ord(c)-33 for c in s)for s in"* )+ *, +- ,. -/ .0 / \"2 !#13 \"$24 #%35 $&46 %'57 &(68 '7 *: )+9; *,:< +-;= ,.<> -/=? .0>@ /? 2B 13AC 24BD 35CE 46DF 57EG 68FH 7G :J 9;IK :<JL ;=KM <>LN =?MO >@NP ?O BR ACQS BDRT CESU DFTV EGUW FHVX GW JZ IKY[ JLZ\\ KM[] LN\\^ MO]_ NP^` O_ R QS RT SU TV UW VX W".split()];x=set((ord(p[i+1])-49)*8+ord(p[i])-97 for i in range(0,len(p),2))
 r=set(range(8))-x
 for i in range(99):r=set().union(*[a[c]for c in r])-x
 return all(c<56 for c in r)

在线尝试!

这通过“注水填充”进行。首先,我们按abishopwise 创建一个列表,列出哪些正方形与其他正方形相邻。然后,我们创建一组x排除项(基于密码)。然后,我们初始化一组r可到达的正方形,该正方形从第一行开始(减去任何排除项),然后从那里向外“泛滥” 99次,这应该绰绰有余了。最后,我们进行测试以查看最后一行中的任何正方形是否最终出现在我们的可及集中。如果是这样,我们的密码很弱!如果没有,我们将使用强密码。

缺点,也许是取消资格(我在这里不知道通常的规则):如果密码格式错误(例如“正确的电池钉”),那么我们将抛出异常而不是返回False。但是,True如果密码很强,我们总是会返回的!

减去16个字节,感谢Jo King。我们a在一个使用的地方内联,并不断地折叠一些数学。

def f(p):
 x=set(ord(p[i])-489+8*ord(p[i+1])for i in range(0,len(p),2));r=set(range(8))-x
 for i in[1]*99:r=set().union(*[[set(ord(k)-33for k in s)for s in"* )+ *, +- ,. -/ .0 / \"2 !#13 \"$24 #%35 $&46 %'57 &(68 '7 *: )+9; *,:< +-;= ,.<> -/=? .0>@ /? 2B 13AC 24BD 35CE 46DF 57EG 68FH 7G :J 9;IK :<JL ;=KM <>LN =?MO >@NP ?O BR ACQS BDRT CESU DFTV EGUW FHVX GW JZ IKY[ JLZ\\ KM[] LN\\^ MO]_ NP^` O_ R QS RT SU TV UW VX W".split()][c]for c in r])-x
 return all(c<56for c in r)

@JoKing谢谢!for我看不到如何删除两个空格前还有两个空格。我发现用本地计算机range(99)上的repr(f)工作代替而不是tio.run的解释器上的工作...但是后来我发现总的来说[1]*99更短!这样又节省了4个字节。
Quuxplusone

for我看不到如何删除两个空格之前的空格 -哦!显然,Python将其33for视为两个令牌(而for33将是一个令牌)。今天我学到了。然后再减去2个字节。
Quuxplusone

1

干净,285字节

import StdEnv,Data.List
$_[_]=1<0
$a[x,y:l]=case[[u,v]\\u<-[0..7],v<-[0..7]|u==toInt x-97&&v==toInt y-49]of[p]= $[p:a]l;_=1<0
$a _=all(\[_,y]=y<7)(iter 64(nub o\e=e++[k\\[u,v]<-e,p<-[-1,1],q<-[-1,1],k<-[[abs(u+p),abs(v+q)]]|all((<>)k)a&&all((>)8)k])(difference[[e,0]\\e<-[0..7]]a))

$[]

在线尝试!

$[]$ :: [[Int]] [Char] -> Bool组成的第一个参数,给人\ [Char] -> Bool

该函数通过一次消耗字符串两个字符来工作,如果字符串看到无效部分,则立即返回false(如果字符串格式无效)。处理完字符串后,它将在主面板一侧的每个空白方块上放置一个主教,并以各种可能的方式移动它们64次,并检查目标行中是否有任何末端位置。


似乎错误地返回Truea1b1c1d1e1f1g1?并非我对它的工作原理一无所知。:)
Quuxplusone

2
@Quuxplusone我脑子发疯了,以为白人主教只用白色正方形。我还添加了一个解释。
Οurous

1

Wolfram语言(数学)339个 316 358 353 345字节

-23个字节,感谢@Doorknob。

+42字节用于回溯。

p[m_]:=StringPartition[#,m]&;l=Range@8;f[n_]:=Check[w=(8#2+#1-8)&@@@({LetterNumber@#,FromDigits@#2}&@@@(p@1/@p[UpTo@2]@n));g=Graph[Sort/@UndirectedEdge@@@Position[Outer[EuclideanDistance@##&,#,#,1],N@Sqrt@2]&@GraphEmbedding@GridGraph@{8,8}//Union]~VertexDelete~w;c:=#~Complement~w&;m=0;Do[m+=Length@FindPath[g,i,j],{i,c@l},{j,c[l+56]}];m==0,0>1]

在线尝试!

我重写了大部分内容以说明回溯,我认为可能有一种更简单的方法来定义图g,Mathematica拥有GraphData[{"bishop",{8,8}}]主教可以在棋盘上进行的所有动作的图(Bishop Graph),但是该图还包括一些连接。比最近的对角邻居。如果有人知道更短的方法,请告诉我。图形构建功劳归功于这个MathematicaSE答案

返回True强密码,False弱密码/格式错误的密码。请注意,对于大多数格式错误的密码,它将产生一堆错误消息,然后返回False。如果这不符合规则,则可以通过更改f[n_]:=...f[n_]:=Quiet@...花费6个字节来抑制它们。

取消高尔夫:

p[m_] := StringPartition[#, m] &;

f[n_] :=
 Check[
  w = (8 #2 + #1 - 
       8) & @@@ ({LetterNumber@#, FromDigits@#2} & @@@ (p@1 /@ 
        p[UpTo@2]@n));
  r = GridGraph[{8, 8}];
  g = Graph[Sort /@ UndirectedEdge @@@
             Position[Outer[EuclideanDistance@## &, #, #, 1],N@Sqrt@2] &@
              GraphEmbedding@r // Union]~VertexDelete~w;
  s = Complement[{1,2,3,4,5,6,7,8},w];
  e = Complement[{57,58,59,60,61,62,63,64},w];
  m = 0;
  Do[m += Length@FindPath[g, i, j], {i, s}, {j, e}];
  If[m == 0,True,False]
  , False]

分解:

p[m_]:=StringPartition[#,m]& 

接受一个字符串参数,并将其拆分为每个length的字符串列表m

Check[...,False]

返回False是否产生任何错误消息,这就是我们捕获格式错误的字符串的方式(即假设它们格式正确,不可避免地会产生错误)。

(8*#2 + #1 - 8) & @@@ ({LetterNumber@#, FromDigits@#2} & @@@ (p@1 /@ 
        p[UpTo@2]@n));

注意到棋子位置的串并分割它使得"a2h5b"成为{{"a","2"},{"h","5"},{"b"}},然后LetterNumber将信转换为数字(a -> 1等)和FromDigits数字转换成整数。如果字符串格式不正确,则此步骤将产生错误,并由Check返回,将捕获该错误False。然后将这两个数字转换为对应于板上正方形的整数。

r = GridGraph[{8, 8}];
g = Graph[
     Sort /@ UndirectedEdge @@@ 
          Position[Outer[EuclideanDistance@## &, #, #, 1], 
           N@Sqrt@2] &@GraphEmbedding@r // Union]~VertexDelete~w;

构造所有近邻对角线边的图,其中删除了当子位置。

s = Complement[{1,2,3,4,5,6,7,8},w];
e = Complement[{57,58,59,60,61,62,63,64},w];

这些分别是未占用的起点和终点的列表

m=0
Do[m += Length@FindPath[g, i, j], {i, s}, {j, e}];
If[m == 0,True,False]

循环遍历起点和终点,每对顶点FindPath将是它们之间路径的列表。如果它们之间没有路径,它将是一个空列表,因此Length@返回0。如果根本没有路径,m则将为零,然后我们返回True,否则返回False


一些提示:TrueFalse可以分别为1>00>1p[1]@#&/@等同于p@1/@Sequence@@可以替换为##&@@。相反{LetterNumber[#[[1]]],FromDigits[#[[2]]]}&/@,您可以使用{LetterNumber@#,FromDigits@#2}&@@@
Doorknob

@Doorknob谢谢!高尔夫打法正在教会我有关Mathematica的各种新事物。我仍然不是100%理解p@1/@,但我了解总体思路。我想p@1 = StringPartition[#,1]&,这对我来说有点困惑,因为p以两种不同的方式接受两个参数,一个为as m_,另一个为#...&,我想这只是一个优先事项。但这是有道理的p@m = p[m]
Kai

对我来说也是如此!主要的变化有,对于任何函数f接受单个参数,f@#&具有相同的行为只是f-在这里,fp[1]。(然后我将[]表示法更改为@,除优先级外,该表示法始终相同。)
Doorknob

@JoKing这是不正确的,这比我最初想的要复杂,还必须考虑向后运动。谢谢
Kai

@JoKing编写了一个新的帐户,该帐户负责回溯。
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.