クイーンズパズルを確認する


16

女王がチェスで何をしているのかわからなければ、それは大した問題ではありません。それはただの名前です:)

入力は、クイーンをいくらか含む任意の幅と高さの正方形になります。入力ボードは次のようになります(このボードの幅と高さは8です)。

...Q....
......Q.
..Q.....
.......Q
.Q......
....Q...
Q.......
.....Q..

このボードにはクイーンが8人います。たとえば、ここに7、1、または10があると、ボードは無効になります。

ここでは.、空のスペースにaを使用Qし、女王にa を使用します。代わりに、希望する非空白文字を代わりに使用することもできます。

この入力は有効であることが確認できます。真実の値を印刷(または返す)する必要があります(有効でない場合は、偽の値を印刷(または返す)必要があります)。他と同じ行、列、対角線、または対角線にクイーンがいないため有効です。

例(括弧内に出力しないでください):

...Q....
......Q.
..Q.....
.......Q
.Q......
....Q...
Q.......
.....Q..

1

...Q.
Q....
.Q...
....Q
..Q..

0

Q.
Q.

0

..Q
...
.Q.

0 (this is 0 because there are only 2 queens on a 3x3 board)


..Q.
Q...
...Q
.Q..

1

Q

1 (this is valid, because the board is only 1x1, so there's no queen that can take another)

クイーンが別の行、列、対角線または対角線にない場合にのみ入力が有効であることを強調します。

ルール

  • 空の入力を受け取ることはありません
  • 入力に含まれるクイーンの数がボードの面積の平方根より少ない場合、有効ではありません。
  • 2x2または3x3ボードには有効なソリューションはありませんが、幅と高さが自然数である他のすべてのサイズの正方形ボードにはソリューションがあります。
  • 入力は、PPCGルールに従って、任意の合理的な形式にすることができます
  • 入力は常にsqaureになります
  • 例では1と0を使用しましたが、真実または偽の値(Why yes, sir, that is indeed the caseandなどWhy no, sir, that is not the case)を使用できます

これは、最短のコードが勝ちます!



1
{(x, y, v)}v中には、[., Q]有効な入力フォーマットでありますか?
PidgeyUsedGust

@DuctrTapeそれはあまり意味がないと思う。
Okx

2
@Okxつまり、入力として座標と値のリストを受け取ることを求めています。たとえば(0, 0, Q), (0, 1, .), (1, 0, Q), (1, 1, .)、3番目のテストケースになります。
Mego

改行なしで文字列を使用できますか?
タイタス

回答:


7

カタツムリ、14バイト

&
o.,\Q!(z.,\Q

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

2D決定問題のための2Dパターンマッチング言語のようなものはありません。:)

説明

&最初の行には、入力内のすべての可能な位置から一致するように2行目のパターンを必要と一致モードオプションです。その場合、プログラムは印刷し1、そうでない場合は印刷し0ます。

パターン自体については)、最後に暗黙的があることに注意してください。

o       ,, Move in any orthogonal direction (up, down, left or right).
.,\Q    ,, Make sure that there's a Q somewhere in that direction from the
        ,, starting position of the match.
!(      ,, After finding the Q, make sure that the following part _doesn't_ match:
  z     ,,   Move in any orthogonal or diagonal direction.
  .,\Q  ,,   Try to find another Q in a straight line.
)

これがうまくいく理由は、ネガティブな先読みから始めて見るのが最も簡単です:すでに見つけQた他のものから直線上にないQことを確認することにより、Nクイーン以下であることを確認します(そうでなければ、 1列に2つになると、別の女王を見つけずにこれらの女王を見つけることはできません)。次に、最初の部分では、任意の位置から直交方向に到達可能なクイーンが存在することを確認し、正確にN個のクイーンが存在することを確認します。行方不明の場合は、クイーンなしの行と列があります。これらの交差点から始めて、直交方向にのみ進むことで女王を見つけることは不可能でしょう。


6

ゼリー、17または15バイト

ỴµUŒD;ŒD;ZVṀ;V=1Ṃ

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

クイーンおよび¹空白スペースに使用します。(これは主に入力を文字列にすることを禁止しているため、入力を文字列にすることの禁止の結果です.Jellyでは文字列を整数に変換することは難しく、評価が最も簡単な方法であり、1と0、 "add 1"()および "add 0"(¹)を使用すると、リスト内のクイーンを評価してカウントできるため、いくつかの合計およびマップ命令を省略できます。)真偽値はJellyの標準値であり10

編集:この答えを書いてから質問が変更され、入力をマトリックスとして取得できるようになりました。これにより、先頭を削除してỴµ2バイト節約できます。また、入力形式をより一般的なものに変更して、評価するのでSはなく合計することもおそらく可能ですが、Vバイトを節約するとは思わず、このファンキーな形式が好きです。

説明

ỴµUŒD;ŒD;ZVṀ;V=1Ṃ
Ỵ                    Split on newlines.
 µ                   Set this value as the default for missing arguments.
     ;  ;            Concatenate the following three values:
  UŒD                - the antidiagonals;
      ŒD             - the diagonals;
         Z           - and the columns.
          V          Evaluate (i.e. count the queens on) all of those.
           Ṁ         Take the largest value among the results.
            ;V       Append the evaluation (i.e. queen count) of {each row}.
              =1     Compare each value to 1.
                Ṃ    Take the minimum (i.e. most falsey) result.

したがって、基本的な考え方は、各対角線、対角線、および列に最大1つのクイーンが存在するようにすることです。そして、各列にちょうど1人の女王。これらの条件は、4種類のラインのそれぞれに最大で1つのクイーンと、ボードのサイドの長さに等しいクイーンの数を必要とするのに十分です。

ちなみに、Jellyはおそらく対角線の組み込みを行うことができますが、AFAICTは対角線を持たないようです。そのため、ボードを反映してから対角線を取得するために解決する必要があります。

別の興味深い注意点は、(すべて等しい)に変更=1ṂするEと、一般化されたnクイーンチェッカーが得られることです。これは、各行、列、対角線、および対角線がk個以下のクイーンを含み、ボードが正確に含むn × nボードも受け入れますkn queens。kを1に制限すると、実際には2バイトかかります。


ルールが更新され、「PPCGルールに従って、入力は任意の合理的な形式である可能性があります」と短くなりました:)編集-指摘したとおりです。
ジョナサンアラン

5

オクターブ、57 70 67 51 52バイト

@LuisMendo fliprot90おかげで代わりに1バイトを保存しましたが、1x1の場合にバグが見つかりました

@(A)all(sum([A A' (d=@spdiags)(A) d(flip(A))],1)==1)

1はクイーンを表し、0は空のスペースを表すバイナリ行列として入力を受け取ります。

入力行列とその転置を最初に連結する匿名関数を作成します。

spdiags引数と同じ行数で行列を作成し、対角線を列に変換します(必要に応じてゼロが埋め込まれます)。したがってspdiags、入力行列を連結して対角線を取得し、行列をspdiags水平に反転して対角線を取得します。

次に、連結マトリックスの各列の合計を取得し、各列が正確に1であることを確認します。

ideoneでのサンプル実行。


flip代わりに使用できると思いますrot90
ルイスメンドー

@LuisMendoうん、それも動作します。ありがとう!
ビーカー

また、避けることはできませんall()か?
ルイスメンドー

@LuisMendoうーん...たぶん...しかし夕食後まで待たなければならない;)
ビーカー

4

MATL38 34バイト

@beakerのおかげで4バイトオフ!

sG!sGt&n_w&:&XdsGP5M&Xdsv2<GnGzU=*

入力は、行区切り記号としてセミコロンを使用したゼロと1の2D配列です。

これは、1の列ベクトルを真実として出力し、少なくとも1つのゼロを含む列ベクトルを偽として出力します。

オンラインでお試しください!フッターコードは、if真実性または虚偽を示すブランチです。

または、すべてのテストケースを確認します

説明

s      % Input binary matrix implicitly. Sum of columns. Gives a row vector
G!     % Paste input again. Transpose
s      % Sum of columns (rows in the original matrix). Gives a row vector
G      % Paste input again
t&n    % Duplicate. Push number of rows and number of columns (will be equal)
_w     % Negate, flip
&:     % Binary range. Gives [-n -n+1 ... n] for input of size n×n
&Xd    % Get diagonals -n through n. This gives all diagonals as colums
s      % Sum of each column (diagonals of original matrix). Gives a row vector
GP     % Paste input again. Flip vertically
5M     % Push [-n -n+1 ... n] again
&Xd    % Get diagonals -n through n (anti-diagonals of original matrix)
s      % Sum of each column. Gives a row vector
v      % Concatenate everything into a column vector
2<     % True for elements that are less than 2
Gn     % Paste input again. Number of elements
Gz     % Paste input again. Number of nonzeros (i.e. of queens)
U      % Square
=      % True if equal
*      % Mutiply, element-wise

入力としてバイナリ行列を取得できるようになったので、2バイトを節約できます。
ビーカー

2

J、37バイト

(+/&,=#)*1=[:>./+//.,+//.&|.,+/,+/&|:

引数としてブール行列を取る匿名関数列。

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

( +/ラベルの合計&が行の集計に等しい,=#)

* および(点灯時間)

11は=等しいの最大値を[:>./

+//.対角線上の合計,と(lit. catenated)

+/合計/.斜め&|.,

+/合計,

+/合計&|:転置


2

SnakeEx、67バイト

m:({q<>}({q<R>}[{q<RF>}{n<RF>}].)*{e<>}<R>)%{4}
e:.$
q:_*Q_*$
n:_+$

入力の_代わりに使用し.ます。真実の場合は1つ以上の一致、偽の場合は0の一致を返します。ヘッダーのリンクでオンライン通訳を見つけることができます。

説明

SnakeExは、2-Dパターンマッチングチャレンジの言語です。グリッドマッチングの周りを移動する「蛇」を定義します。ヘビは他のヘビを産み出し、言語を非常に強力にします。

このプログラムを下から見てみましょう。

n:_+$

これは、n1つ以上のアンダースコアに一致するスネークを定義し、次にグリッドのエッジに定義します。これは8つの基本的な方向のいずれかであることに注意してください。方向は、ヘビがスポーンするときに決定されます。

q:_*Q_*$

n上記と同様に、これはq、任意の数の下線、単一のQ、任意の数の下線、およびグリッドの端に一致する蛇として定義されます。つまり、クイーンが1つだけの行/列/対角線です。

e:.$

e 1つのキャラクターとグリッドの端に一致するヘビです。

m:({q<>}({q<R>}[{q<RF>}{n<RF>}].)*{e<>}<R>)%{4}

メインのヘビm は、これらのビルディングブロックを使用してボード全体をチェックします。概念的には、グリッドの外側の端の周りを走り、他の蛇を生成して、すべての列と行に正確に1つのクイーンがあり、すべての対角線に最大1つのクイーンがあることを確認します。スポーンされたヘビのいずれかが一致しない場合、一致全体が失敗します。分解しましょう。

  • ( )%{4}括弧内の内容を4回、各側に1回実行します。(以下では、特定の側面、たとえばグリッドの上端を左上隅から右に向かって描くと便利です。)
  • {q<>}qメインのヘビが動いているのと同じ方向にヘビをスポーンします。これにより、現在のエッジが「厳密に1つのクイーン」ルールを満たしていることが確認されます。スポーンされたヘビはメインヘビのマッチポインターを動かさないので、エッジの先頭にいることに注意してください。
  • ( )* 括弧内の0個以上に一致します。
  • {q<R>}qメインのヘビの方向から右に曲がったヘビを生成します。(たとえば、メインの蛇が上端に沿って右に移動している場合、この蛇は下に移動します。)これにより、各列/行がチェックされます。
  • [ ] 括弧内のオプションのいずれかと一致します。
    • {q<RF>}メインのヘビの方向からq右に45度回転したヘビを生成します(つまりRF8 度以上)。q対角は正確に一つの女王が含まれている場合は、ヘビが一致します。
    • {n<RF>}n代わりにヘビを生成します。n対角線は何の女王が含まれていない場合は蛇が一致します。
  • . 任意の文字に一致し、一致ポインターを前方に移動します。
  • できるだけ多くの水平線と対角線を確認した後、spawningによってエッジにいることを確認します{e<>}
  • 最後に<R>、メインのヘビを右に回し、次のエッジに合わせる準備をします。

奇妙なもの

  • マッチングが外側のコーナーから開始されるようにするためのプログラムには何もありません。実際、真実のテストケースはいくつかの一致を生成しますが、その一部はどこかで開始されます。それにもかかわらず、私が試した偽のケースはどれも偽陽性を生成していません。
  • 言語仕様を正しく読んでいるのであればX、の代わりに(すべての対角線方向の分岐)を使用できたはずですRF。残念ながら、オンラインインタープリターは、それが構文エラーだと言いました。私も試してみました*(全方向に分岐)が、それは通訳をハングアップさせました。
  • 理論的に_*Q?_*$は、対角線で「最大1人の女王」を一致させるために、次のようなものが機能するはずですが、それは通訳もハングアップさせます。私の推測では、空の一致の可能性が問題を引き起こすということです。

2

ルビー、120バイト

文字列としての入力が必要な元の仕様に基づくラムダ関数。

->s{t=k=0
a=[]
s.bytes{|i|i>65&&(a.map{|j|t&&=((k-j)**4).imag!=0};a<<k)
k=i<11?k.real+1:k+?i.to_c}
t&&~a.size**2>s.size}

Qを複素数に変換し、互いに減算します。任意の2つのクイーンの座標の差が水平、垂直、または斜めの場合、4乗すると、実数が得られ、配置は無効になります。

テストプログラムでゴルフをしていない

f=->s{                                 #Take input as string argument.
  t=k=0                                #k=coordinate of character. t=0 (truthy in ruby.)
  a=[]                                 #Empty array for storing coordinates.
  s.bytes{                             #Iterate through all characters as bytes.
    |i|i>65&&(                         #If alphabetical, compare the current value of k to the contents of a
      a.map{|j|t&&=((k-j)**4).imag!=0} #If k-j is horizontal, vertical or diagonal, (k-j)**4 will be real and t will be false
      a<<k)                            #Add the new value of k to the end of a.
    k=i<11?k.real+1:k+?i.to_c          #If not a newline, increment the imaginary part of k. If a newline, set imaginary to 0 and increment real
  }                                    #s.size should be a*a + a newlines. ~a.size = -1-a.size, so ~a.size**2 = (a.size+1)**2
t&&~a.size**2>s.size}                  #compare a.size with s.size and AND the result with t. Return value. 


p f["...Q....
......Q.
..Q.....
.......Q
.Q......
....Q...
Q.......
.....Q.."]

p f["...Q.
Q....
.Q...
....Q
..Q.."]

p f["Q.
Q."]

p f["..Q
...
.Q."]

p f["..Q.
Q...
...Q
.Q.."]

p f["Q"]

2

Pythonの3232 200 155バイト

d=1
f=input()
Q=[]
for i in f:d=[0,d][i.count('Q')==1];Q+=[(len(Q),i.index('Q'))]
print[0,d][sum(k[1]==i[1]or sum(k)==sum(i)for k in Q for i in Q)==len(Q)]

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

入力仕様の変更に気づいた@beakerのおかげで-32バイト。言語をPython 3から2に変更inputしたため、入力を文字列の配列または文字配列の配列として使用できるようになりました。

@Leaky Nunのおかげで-45バイト


入力要件は緩和されています(必要に応じて)。
ビーカー

@beakerわかりました、ありがとう。代わりに、文字列の配列として入力を受け取ります。それを指摘してくれてありがとう!
ハイパーニュートリノ


1

JavaScript(ES6)、115バイト

a=>!a.some((b,i)=>b.some((q,j)=>q&&h[i]|v[j]|d[i+j]|e[i-j]|!(h[i]=v[j]=d[i+j]=e[i-j]=1))|!h[i],h=[],v=[],d=[],e=[])

ゴルフをしていない:

function queens(arr) {
    horiz = [];
    vert = [];
    diag = [];
    anti = [];
    for (i = 0; i < arr.length; i++) {
        for (j = 0; j < arr.length; j++) {
            if (arr[i][j]) { // if there is a queen...
                if (horiz[i]) return false; // not already on the same row
                if (vert[j]) return false; // or column
                if (diag[i + j]) return false; // or diagonal
                if (anti[i - j]) return false; // or antidiagonal
                horiz[i] = vert[j] = diag[i + j] = anti[i - j] = true; // mark it
            }
        }
        if (!horiz[i]) return false; // fail if no queen in this row
    }
    return true;
}

0

ルビー、155バイト

->x{(y=x.map{|r|(i=r.index ?Q)==r.rindex(?Q)?i:p or-2}).zip(y.rotate).map.with_index{|n,i|n.max-n.min==1&&i<y.size-1?-2:n[0]}.inject(:+)*2==(s=x.size)*~-s}

これは読むのが恐ろしいので、以下のゴルフバージョンが少し少なくなっています

->x{
    (y=x.map{|r|(i=r.index ?Q)==r.rindex(?Q)?i:p or-2})
    .zip(y.rotate)
    .map.with_index{|n,i|n.max-n.min==1&&i<y.size-1?-2:n[0]}
    .inject(:+)*2==(s=x.size)*~-s
}

これは同じコードですが、何が起きているかを区別するための改行がいくつかあります。

コードtselfはx、形式の文字列()の配列を取る匿名ラムダ関数です["..Q", "Q..", ".Q."]

最初の行は、各文字列をその文字列のQ文字のインデックスにマッピングしています。Q文字がない場合、-2 1に置き換えられます。この新しいインデックスの配列は、変数に割り当てられますy

次の行は、このインデックスの配列を、それ自体が1回転(回転)させて圧縮します。これにより、連続したインデックスのペアの配列が生成されます。

次の行は特に複雑です。インデックスの各ペアを通過し、大きい方から小さい方を引きます。これが1の場合(そして最後のペアではない 2に)、同じ対角線上に2つのクイーンがあり、値-2が挿入されます。そうでない場合は、ストリング内のクイーンの元のインデックスが挿入されます。

最後の行は、それぞれのすべてのインデックスを合計し、それがn-1の三角形の番号であるかどうかを確認します。nは正方形の幅(または高さ)です。

1:-1が私の目標でしたが、0以外は1なので、対角線のチェックが混乱します。それの否定性は、最終的な合計を間違えることが重要です。9のような大きな数字(1桁の数字)を考えましたが、それが間違った検証につながらないことを確信できません。
2:rubyのrotate配列関数はボードをラップしませんが、最後のペアが1つずつ異なる場合は関係ありません-それは対角線ではありません。


0

PHP、137 143バイト

ニールのソリューションに触発

for($n=1+strlen($s=$argv[1])**.5|0;($c=$s[$p])&&!(Q==$c&&$v[$x=$p%$n]++|$h[$x=$p/$n]++|$d[$y-$x]++|$a[$y+$x]++);$p++);echo$n-1==count($a)&&!$c;

最初のコマンドライン引数から入力を受け取ります。で実行し-rます。シングルバイトの改行が必要です。
実際には0、改行以外の任意の文字を使用できます。
true(1)またはfalse(空の文字列)を出力します。

壊す

for($n=1+strlen($s=$argv[1])**.5|0; // copy input to $s, $n=size+1 (for the linebreak)
    ($c=$s[$p])&&!(                 // loop through characters
        Q==$c&&                         // if queen: test and increment lines
            $v[$x=$p%$n]++|$h[$x=$p/$n]++|$d[$y-$x]++|$a[$y+$x]++
    );                                  // break if a line had been marked before
    $p++);
echo$n-1==count($a)             // print result: true for $n-1(=size) marks
    &&!$c;                      // and loop has finished

0

Pythonの3185の 176 175 172 171バイト

lambda x,c=lambda x:x.count("Q")==1:all([*map(c,x+[[l[i]for l in x]for i in range(len(x[0]))])])*~any(map(lambda s:"Q%sQ"%(s*".")in"".join(x),[len(x[0]),len(x[0])-2]))==-1

入力として文字列のリストを取る匿名関数。

Python 2、175バイト

lambda x:all([a.count("Q")==1for a in x]+[[l[i]for l in x].count("Q")==1for i in range(len(x[0]))]+[all(map(lambda s:"Q%sQ"%(s*".")not in"".join(x),[len(x[0]),len(x[0])-2]))])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.