司教に強いパスワード


13

パスワードビショップの良さと混同しないでください!

文字列が与えられ、それが司教に強いパスワードを構成している場合は答えます(真/偽または2つの一貫した値)。

パスワードは、文字の各ペアがチェスボード上の正方形として解釈できるように、文字(in )と数字(in )が交互になった文字列であり、名前の付いた各正方形に白いポーンを配置すると、司教に対して強力ですパスワードでは、最初の()行の任意の正方形から最後の()行の任意の正方形まで、白人の司教が連続して何回も移動する方法はありません。a-h1-818

司教に強いパスワード

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

たとえばa1b1c1d1e1f1g1a8b8c8d8e8f8g8、位置foob4b5d4d5f4f5g3h5対応し、位置に対応しますfoo

司教に弱いパスワード

  • a4c4e4g4g5d6f6e3d2b2 (整形式だが強くはない-この例についてはジョー・キングに感謝!)
  • b1c1d1e1f1g1h1a8b8c8d8e8f8g8 (整形式だが強くない)
  • h4g4f4e4c4b4a4c3 (整形式だが強くない)
  • d4 (整形式だが強くない)
  • b4b5d4d5f4f5g2h5 (整形式だが強くない)
  • correct horse battery staple (不正な形式)
  • 1a1b1c1d1e1f1g8a8b8c8d8e8f8g (不正な形式)
  • a (不正な形式)
  • aa (不正な形式)

1
ビショップはどの色の四角になりますか?
無知の

2
最後の2番目のテストケースが仕様と矛盾しています。また文字の各ペアをチェス盤上の正方形として解釈する方法」を説明する必要があります。
シャギー

1
a1b2c3d4d5f5f4g3g4h2b5は司教に対して強くありません。司教はh5に到達し、d1に下がることができるため
の無知の実施

2
@ TRITICIMAGVS、Ourous:ポーンと司教の両方が白であるため、どちらも他方を捕まえる(着陸する、通過する、ジャンプする)ことはできません。
Quuxplusone

1
また、真実のテストケースの1つに例を追加できますか。私はパスワードの四角が白いポーンで満たされていることを理解していますが、白い司教が置かれている場所がわかりません。そして、もしどこかがうまくいけば、最初のテストケースで各行1を通過できないのはなぜ8ですか?a列はポーンで完全に満たされているため、各列に移動できませんが、問題なく各行に移動できますか?私は何かを逃しているような気がします。.:S
ケビンクルーッセン

回答:


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を使用して、数値が自動的に2桁に左詰めされ、文字列化されます。これにより、境界チェックが非常に短くなります-正規表現と一致します。'00'..'99'/[09]/

  • ヘルパー関数の内部で、新しい座標のリストを作成する際に、プロセスで[x-11, x-9, x+9, x+11]同時に割り当てます。これはたまたま真理値(訪問した正方形に印を付ける)です。z[x]9

  • 最後の行では、配列にz[81,9]が含まれていないことを確認します9。これを行うには、9z[81,9]-[9])のすべてのインスタンスを削除し、結果の配列の9番目の要素を要求し[8]ます()。配列には元々9個の要素があったことがわかっているためnil、削除された場合、を取得します1


2

Python 2330の 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のラムダ関数バージョンをg自体より短くする方法がわかりませんでした。

Quuxplusoneのおかげで-4バイト

バックトラッキングを考慮した+61バイト(ジョーキングを指摘し、ゴルフのヒントをありがとう)


いいね q=r=1よりも短くなりq=1 r=1ますよね?そしてif r:より短いif r>0:
Quuxplusone

2

Pythonの2490 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)

オンラインでお試しください!

これは「フラッドフィル」で機能します。最初にa、司教単位で、どの正方形が他の正方形に隣接するかのリストを作成します。次に、x(パスワードに基づいて)一連の除外を作成します。次に、セットを初期化しますr、到達可能な正方形の。これは、最初の行(除外を除く)から始まり、そこから外側に99回繰り返し「あふれる」、これは十分すぎるはずです。最後に、最後の行の正方形のいずれかが到達可能なセットになったかどうかをテストします。もしそうなら、私たちは弱いパスワードを持っています!そうでない場合、強力なパスワードがあります。

欠点、おそらく失格(ここでの通常の規則はわかりません):パスワードの形式が正しくない場合(「正しい馬のバッテリーステープル」など)、を返す代わりに例外をスローしますFalse。ただしTrue、パスワードが強い場合は必ず返されます!

ジョー・キングのおかげでマイナス16バイト。a使用されている1つの場所にインライン化し、一定の数学を折りたたみます。

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削除する方法を見ることができなかった2つの前にまだ空白があります。私はローカルマシンrange(99)repr(f)動作するが、tio.runのインタープリターでは動作しないことに気付きました...しかし、[1]*99とにかくそれが短いことがわかりました!そのため、さらに4バイト節約できました。
Quuxplusone

for削除する方法がわからない2 秒前の空白 —ああ!どうやらPythonは33for2つのトークンとして処理しfor33ます(1つのトークンになります)。今日、私は学びました。次にマイナス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ます。

この関数は、文字列を一度に2文字消費することで機能し、無効な部分が見つかるとすぐに文字列が無効な形式である場合、すぐにfalseを返します。文字列が処理されると、ボードの片側のすべての空の正方形にビショップを配置し、可能な限りあらゆる方法でそれらを移動し、終了位置のいずれかがターゲット行にあるかどうかを確認します。


間違って戻るTrueようa1b1c1d1e1f1g1ですか?私はそれがどのように機能するかについて何かを理解しているわけではありません。:)
Quuxplusone

2
@Quuxplusone私は頭がおかしくて、白い司教は白い正方形しか使わないと思った。説明も追加しました。
Οurous

1

Wolfram言語(Mathematica)339 316 358 353 345バイト

@Doorknobのおかげで-23バイト。

バックトラッキングを考慮した+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]

オンラインでお試しください!

私は、グラフを定義する簡単な方法があるかもしれないと思う、バックトラッキングのためのアカウントにこれのほとんどを書き直しgMathematicaがあり、GraphData[{"bishop",{8,8}}]司教は、チェス盤(上作ることができるすべての動きのグラフであるビショップグラフ)が、このグラフは、さらに接続を含みます最も近い斜めの隣人より。誰かがそれを行うより短い方法を知っているなら、私に知らせてください。グラフ構築の功績は、このMathematicaSEの回答にあります。

True強力なパスワード、False脆弱なパスワード、不正なパスワードを返します。不正な形式のパスワードのほとんどについては、大量のエラーメッセージが生成されてから返されることに注意してくださいFalse。これがルールに沿っていない場合、6バイトのコストに変更f[n_]:=...することでそれらを抑制することができf[n_]:=Quiet@...ます。

ゴルフをしていない:

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

文字列引数を取り、それぞれ長さの文字列のリストに分割し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。これらの2つの数値は、ボード上の正方形に対応する整数に変換されます。

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。パスがまったくない場合はm0になりTrue、そうでない場合はreturnになりFalseます。


いくつかのヒント:TrueFalseすることができ1>00>1それぞれ。p[1]@#&/@は、ちょうどと同等p@1/@です。Sequence@@に置き換えることができます##&@@。代わりに{LetterNumber[#[[1]]],FromDigits[#[[2]]]}&/@、を使用できます{LetterNumber@#,FromDigits@#2}&@@@
ドアノブ

@Doorknobありがとう!コードゴルフは、Mathematicaに関するあらゆる種類の新しいことを教えてくれます。私はまだ100%理解していませんp@1/@が、私は一般的なアイデアを見る。私が思うp@1 = StringPartition[#,1]&、それは少しので、私は推測する私に混乱しています、p二つの引数二つの異なる方法などの1つ取りm_やなどの他に#...&、私はこれがちょうど優先の問題であると思います。それは理にかなっていp@m = p[m]ます。
カイ

私にとっても同様です!主な変更点はf、単一の引数を取る任意の関数についてf@#&、ちょうどと同じ動作をすることですf-ここでfは、ですp[1]。(その後、[]表記をに変更しました@。これは、優先順位を除いて常に同じです。)
ドアノブ

@JoKingそれは不正です、これは私が最初に思ったよりも複雑であり、後方への動きも考慮する必要があります。ありがとう

@JoKingは、バックトラックを説明する新しいものを作成しました。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.