Bejeweled / match 3ゲームに動きがあるかどうかを判断する


20

バックグラウンド

宝石をちりばめたようなゲームでは、プレイヤーは同じ色の3つを連続して一致させるために、8x8の宝石の隣接する2つの宝石を交換する必要があります。宝石は、水平または垂直に一致させることができます。ゲームプレイは動きがなくなるまで続けられ、その結果、3回連続でゲームが終了します。

仕事

目標は、宝石をちりばめたゲームがまだ終わっていないかどうかを判断するプログラムを書くことです。言い換えれば、少なくとも3つ連続して移動する可能性があるかどうかを確認する必要があります。連続して3つ以上の宝石が存在する可能性がありますが、それでも有効な動きです。

入力

プログラムは、標準入力を介してBejeweledグリッドの8x8表現を受け入れる必要があります。7つの宝石の色はそれぞれ、1〜7の数字で表されます。各行には1行が含まれ、それぞれ8桁で構成される8行が入力されます。例を参照してください。入力は常にこの形式に従い、3行連続して入力されることは決してないと想定できます。

出力

プログラムは、次いで、必要があります(標準出力に)出力yes又はno少なくとも一つの有効な動きは、その行に3つ以上の宝石をもたらす存在するか否かに応じ。プログラムは、yesまたはのいずれかの単一のインスタンス以外を出力してはなりませんno

ルール

プログラムは外部ファイルやリソース、コマンドライン引数を使用したり、特定のファイル名を要求したりしてはいけません。ソースコードのバイト数が最も少ないプログラムが優先されます。

入力:

12314131
13224145
54762673
61716653
61341144
23453774
27645426
75575656

出力: yes

入力:

35261546
76421754
15743271
62135642
35617653
64565476
54427254
15635465

出力: no

追加のテストケースについては、以下のMT0の回答を参照してください。


行だけですか、列でもありますか。
TheDoctor 14年

@TheDoctor列も。「3行で」というフレーズを使用する場合、水平方向または垂直方向に並べる必要があります。
bdr9 14年

@ bdr9あなたはそれを編集したいかもしれません
ジョン・ドヴォルザーク

@JanDvorak完了。
bdr9 14年

また、4行以上が許可されている場合に編集することもできます。
ジャスティン

回答:


12

元のソリューション:JavaScript- 261 255 228 227 179 153文字

/(\d)(\1(\d|.{6}|.{9})|(\d|.{6}|.{9})\1|.{7}\1(.|.{9})|(.|.{9})\1.{7}|(.{7,9}|.{17})\1.{8}|.{8}\1(.{7,9}|.{17}))\1/.test(s.replace(/\n/g,'A'))?'yes':'no'

テストに文字列が変数であると仮定するとs(それ機能させるためにf追加しf=s=>置き換え、その後プロンプトから入力を取るために、それ以外の場合は、コードの先頭にまたはsprompt())。

出力はコンソールへです。

3 番目のソリューション:JavaScript(ECMAScript 6)-178文字

p=x=>parseInt(x,36);for(t="2313ab1b8a2a78188h9haj9j8iaiir9r",i=v=0;s[i];i++)for(j=0;t[j];v|=s[i]==s[i+a]&s[i]==s[i+b]&i%9<8&(b>3|(i+b-a)%9<8))a=p(t[j++]),b=p(t[j++]);v?'yes':'no'

以下の2 番目の解決策(特定の構成で文字を確認するために正規表現を使用)を取り、正規表現を使用せずに同じ構成で同じ文字の文字列を確認するように修正しました。

Base-36文字列"2313ab1b8a2a78188h9haj9j8iaiir9r"は、チェックするオフセットのペアを提供します。つまり、ペア23は、i 番目の文字が(i + 2)番目の文字と(i + 3)番目の文字(正規表現と同等)(.).\1\1-同一でない文字が改行ではないことを確認するためのいくつかの追加チェック付き)。

2 番目のソリューション:JavaScript(ECMAScript 6)-204文字

p=x=>parseInt(x,18);g=a=>a?a>1?"(.|\\n){"+a+"}":".":"";f=(x,a,b)=>RegExp("(.)"+g(a)+"\\1"+g(b)+"\\1").test(x);for(t="10907160789879h8",i=v=0;t[i];v|=f(s,x,y)||f(s,y,x))x=p(t[i++]),y=p(t[i++]);v?'yes':'no'

ベース-18文字列から取られた値のペアを使用して(詳細は以下を参照)は、複数の正規表現を構築10907160789879h8し、かかるORすべてのテストで。それをさらに減らすために、一方が他方の「逆」である正規表現がペアになっていることに注意することができます(OPが存在しないことを示すため、水平および垂直3行の正規表現を無視します- 0088Base-18文字列への追加でそれらのテストを追加したい場合)。

説明

有効な動きのすべての可能な構成をカバーする16の正規表現から始めます。

REs=[
    /(\d)\1\1/,                 // 3-in-a-row horizontally
    /(\d).\1\1/,                // 3-in-a-row horizontally after left-most shifts right
    /(\d)\1.\1/,                // 3-in-a-row horizontally after right-most shifts left
    /(\d)(?:.|\n){9}\1\1/,  // 3-in-a-row horizontally after left-most shifts down
    /(\d)(?:.|\n){7}\1.\1/, // 3-in-a-row horizontally after middle shifts down
    /(\d)(?:.|\n){6}\1\1/,  // 3-in-a-row horizontally after right-most shifts down
    /(\d)\1(?:.|\n){6}\1/,  // 3-in-a-row horizontally after left-most shifts up
    /(\d).\1(?:.|\n){7}\1/, // 3-in-a-row horizontally after middle shifts up
    /(\d)\1(?:.|\n){9}\1/,  // 3-in-a-row horizontally after right-most shifts up
    /(\d)(?:.|\n){7,9}\1(?:.|\n){8}\1/, // 3-in-a-row vertically (with optional top shifting left or right)
    /(\d)(?:.|\n){7}\1(?:.|\n){9}\1/,   // 3-in-a-row vertically after middle shifts right
    /(\d)(?:.|\n){9}\1(?:.|\n){7}\1/,   // 3-in-a-row vertically after middle shifts left
    /(\d)(?:.|\n){8}\1(?:.|\n){7}\1/,   // 3-in-a-row vertically after bottom shifts right
    /(\d)(?:.|\n){8}\1(?:.|\n){9}\1/,   // 3-in-a-row vertically after bottom shifts left
    /(\d)(?:.|\n){17}\1(?:.|\n){8}\1/,  // 3-in-a-row vertically after top shifts down
    /(\d)(?:.|\n){8}\1(?:.|\n){17}\1/,  // 3-in-a-row vertically after bottom shifts up
];

注3イン行のためのregexsは、水平(0 番目)と垂直方向(9の一部)、これらを照合入力が存在することはありませんことOP状態として無関係です。

入力に対してこれらのそれぞれをテストすると、その構成の有効な移動が見つかるかどうかが決まります。

ただし、正規表現を組み合わせて、次の6つを提供できます。

/(\d)(?:.|(?:.|\n){9}|(?:.|\n){6})?\1\1/            // Tests 0,1,3,5
/(\d)\1(?:.|(?:.|\n){9}|(?:.|\n){6})?\1/            // Tests 0,2,6,8
/(\d)(?:.|\n){7}\1(?:.|(?:.|\n){9})\1/              // Tests 4,10
/(\d)(?:.|(?:.|\n){9})\1(?:.|\n){7}\1/              // Tests 7,11
/(\d)(?:(?:.|\n){7,9}|(?:.|\n){17})\1(?:.|\n){8}\1/ // Tests 9,14
/(\d)(?:.|\n){8}\1(?:(?:.|\n){7,9}|(?:.|\n){17})\1/ // Tests 9a,12,13,15

これらは、単一の正規表現に結合できます。

/(\d)(?:.|(?:.|\n){9}|(?:.|\n){6})?\1\1|(\d)\2(?:.|(?:.|\n){9}|(?:.|\n){6})?\2|(\d)(?:.|\n){7}\3(?:.|(?:.|\n){9})\3|(\d)(?:.|(?:.|\n){9})\4(?:.|\n){7}\4|(\d)(?:(?:.|\n){7,9}|(?:.|\n){17})\5(?:.|\n){8}\5|(\d)(?:.|\n){8}\6(?:(?:.|\n){7,9}|(?:.|\n){17})\6/

これは入力に対してテストする必要があるだけです。

テストケース

他の人が役に立つかもしれないいくつかのテストケース(数字1-7のみを使用する入力フォーマットに準拠していませんが、それは簡単に修正され、8x4グリッドです-それはすべての有効な入力のテストに最低限必要であるためです)。

入力文字列から上の16個の正規表現のどれに一致するかを示すマップの形式。

Tests={
    "12345678\n34567812\n56781234\n78123456": -1, // No Match
    "12345678\n34969912\n56781234\n78123456": 1,    // 3-in-a-row horizontally after left-most shifts right 
    "12345678\n34567812\n59989234\n78123456": 2,    // 3-in-a-row horizontally after right-most shifts left
    "12345978\n34567899\n56781234\n78123456": 3,    // 3-in-a-row horizontally after left-most shifts down
    "12345978\n34569892\n56781234\n78123456": 4,    // 3-in-a-row horizontally after middle shifts down
    "12345678\n34967812\n99781234\n78123456": 5,    // 3-in-a-row horizontally after right-most shifts down
    "12399678\n34967812\n56781234\n78123456": 6,    // 3-in-a-row horizontally after left-most shifts up
    "12345678\n34597912\n56789234\n78123456": 7,    // 3-in-a-row horizontally after middle shifts up
    "12345998\n34567819\n56781234\n78123456": 8,    // 3-in-a-row horizontally after right-most shifts up
    "12945678\n34597812\n56791234\n78123456": 9,    // 3-in-a-row vertically after top shifts right
    "12349678\n34597812\n56791234\n78123456": 9,    // 3-in-a-row vertically after top shifts left
    "12345978\n34569812\n56781934\n78123456": 10,   // 3-in-a-row vertically after middle shifts right
    "92345678\n39567812\n96781234\n78123456": 11,   // 3-in-a-row vertically after middle shifts left
    "12945678\n34967812\n59781234\n78123456": 12,   // 3-in-a-row vertically after bottom shifts right
    "12349678\n34569812\n56781934\n78123456": 13,   // 3-in-a-row vertically after bottom shifts left
    "12395678\n34567812\n56791234\n78193456": 14,   // 3-in-a-row vertically after top shifts down
    "12345698\n34567892\n56781234\n78123496": 15,   // 3-in-a-row vertically after bottom shifts up
    "12345678\n34567899\n96781234\n78123456": -1,   // No match - Matches (.)\1.\1 but not 3 in a row
    "12345679\n99567812\n56781234\n78123456": -1,   // No match - Matches (.).\1\1 but not 3 in a row
};

編集1

\dsを.-に置き換えると、6文字節約されます。

編集2

余分な非キャプチャグループを置き換え(?:.|\n)[\s\S]削除し、(m-buettnerが示唆するように後方参照を更新し、yes / no出力に追加しました。

編集3

  • Base-18文字列から個々の正規表現を構築するECMAScript 6ソリューションを追加しました。
  • m-buettnerが示唆するように 3行1列の水平方向のテストを削除しました。

編集4

別の(より短い)ソリューションと、さらに2つの不一致のテストケースを追加しました。

編集5

  • 改行を数字以外の文字に置き換えることにより、元のソリューションを短縮しました(VadimRにより提案)。

編集6

  • 正規表現のビットを組み合わせることにより、元のソリューションを短縮しました(VadimRによって提案されています)。

1
いい解決策!正規表現が機能するとは思わなかったでしょう。?'yes':'no'それが要件にあり、他のすべての人がそれを使用しているため、公平のためにあなたのキャラクター数に含めてください。
bdr9 14年

追加のテストケースのおかげで、他の人が見ることができるように回答へのリンクを追加しました。
bdr9 14年

おっ 正規表現の+1
DankMemes

H-mm、.改行を含む任意の文字に一致するためのJSの修飾子はありませんか?Perlでは、結合された正規表現は単なる129バイトの文字列であるため(怠being なので、Regexp :: Assembleでコンパイルしました)、Perlプログラム全体は約150バイトです。
user2846289 14年

1
おかげ@VadimRいますが、さらに交換に行くことができる.{8}|.{9}.{8,9}して.{7}|.{8}.{7,8}
MT0

3

Python 383

Pythonの1行だけです!

a=[list(l)for l in raw_input().split('\n')];z=any;e=enumerate;c=lambda b:z(all(p==b[y+v][x+u]for(u,v)in o)for y,r in e(b[:-2])for x,p in e(r[:-2])for o in [[(0,1),(0,2)],[(1,0),(2,0)]]);print z(c([[q if(i,j)==(m,n)else a[m][n]if(i,j)==(y+1,x+1)else p for j,p in e(r)]for i,r in e(a)])for y,t in e(a[1:-1])for x,q in e(t[1:-1])for n,m in((x+u,y+v)for u,v in[(1,0),(1,2),(0,1),(2,1)]))

*まあ、セミコロンで、しかしそれはまだPythonでは簡単ではありません(python one-linersは楽しいです!


3
理解できない理解に賛成:)
アレクサンダー・ブレット

2

Node.js-単純なソリューション-905バイト

まあ、まだ答えがありませんので、Node.jsに本当に素朴なソリューションを投稿します

考えられるすべての動きを経て、結果のボードをテストして、3が連続しているかどうかを確認します。

Golfed(Google Closure Compilerを使用)(そこには!0や!1のようなハックなものがあります。XORスワップで何をしたかさえわかりません)

Array.prototype.a=function(){for(var f=[],d=0;d<this.length;d++)f[d]=this[d].a?this[d].a():this[d];return f};for(var a=[],b=0;8>b;b++)a[b]=[];for(b=2;b<process.argv.length;b++)for(var c=process.argv[b].split(""),e=0;e<c.length;e++)a[b-2][e]=parseInt(c[e],10);function h(){for(var d=l,f=0;f<d.length-2;f++)for(var g=0;g<d[f].length-2;g++){var k=d[f][g];if(k==d[f+1][g]&&k==d[f+2][g]||k==d[f][g+1]&&k==d[f][g+2])return!0}return!1}function m(){console.log("yes");process.exit()}for(b=0;b<a.length;b++)for(e=0;e<a[b].length;e++){var l=a.a();0!=b&&(l[b-1][e]^=l[b][e],l[b][e]^=l[b-1][e],l[b-1][e]^=l[b][e],h()&&m(),l=a.a());b!=a.length-1&&(l[b+1][e]^=l[b][e],l[b][e]^=l[b+1][e],l[b+1][e]^=l[b][e],h()&&m(),l=a.a());0!=e&&(l[b][e-1]^=l[b][e],l[b][e]^=l[b][e-1],l[b][e-1]^=l[b][e],h()&&m(),l=a.a());e!=a[b].length-1&&(l[b][e+1]^=l[b][e],l[b][e]^=l[b][e+1],l[b][e+1]^=l[b][e],h()&&m(),l=a.a())}console.log("no");

私はこれをすべて自分の携帯電話で書いたので、それをテストする時間などないことに注意してください。バグを見つけたらコメントしてください。後で確認します。

ゴルフ前の人間が読めるバージョン

// set it up
Array.prototype.clone = function() {
    var arr = [];
    for( var i = 0; i < this.length; i++ ) {
        if( this[i].clone ) {
             arr[i] = this[i].clone();
        } else {
             arr[i] = this[i];
        }
    }
};
var board=[];
for(var i=0;i<8;i++)board[i]=[];
for(var i=2;i<process.argv.length;i++){
    var row=process.argv[i].split("");
    for(var j=0;j<row.length;j++)board[i-2][j]=parseInt(row[j], 10);
}
// function to test
function testBoard(arr){
    for(var i=0;i<arr.length-2;i++){
        for(var j=0;j<arr[i].length-2;j++){
            var val=arr[i][j];
            if(val==arr[i+1][j] && val==arr[i+2][j])return true;
            if(val==arr[i][j+1] && val==arr[i][j+2])return true;
        }
    }
    return false;
}
// functions to exit
function yay(){console.log("yes");process.exit();}
function nay(){console.log("no");}
// super slow naive solution time
for(var i=0;i<board.length;i++){
    for(var j=0;j<board[i].length;j++){
        var newboard=board.clone();
        if(i!=0){
            newboard[i-1][j]=newboard[i-1][j]^newboard[i][j];// whoa, it's a
            newboard[i][j]=newboard[i-1][j]^newboard[i][j];  // cool algorithm
            newboard[i-1][j]=newboard[i-1][j]^newboard[i][j];// at least this 
                                                             // isn't all naive
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
        if(i!=board.length-1){
            newboard[i+1][j]=newboard[i+1][j]^newboard[i][j];
            newboard[i][j]=newboard[i+1][j]^newboard[i][j];
            newboard[i+1][j]=newboard[i+1][j]^newboard[i][j];
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
        if(j!=0){
            newboard[i][j-1]=newboard[i][j-1]^newboard[i][j];
            newboard[i][j]=newboard[i][j-1]^newboard[i][j];
            newboard[i][j-1]=newboard[i][j-1]^newboard[i][j];
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
        if(j!=board[i].length-1){
            newboard[i][j+1]=newboard[i][j+1]^newboard[i][j];
            newboard[i][j]=newboard[i][j+1]^newboard[i][j];
            newboard[i][j+1]=newboard[i][j+1]^newboard[i][j];
            if(testBoard(newboard))yay();
            newboard=board.clone();
        }
    }
}
nay();

ああ、実際には最初の投稿を10分遅らせました。私ちょっとこのかかわらような...
DankMemes

ああ、私が使ったのとまったく同じ方法(素朴だが小さなコード!)私よりもはるかに説明的であるために+1
KSab

より効率的なアルゴリズムがあります場合、私は...不思議
DankMemes

2

Perl、114 96 95 93 92 87 86 85バイト

+を含む -a0p

STDINの入力で実行します。

bejeweled.pl
12314131
13224145
54762673
61716653
61341144
23453774
27645426
75575656
^D

bejeweled.pl

#!/usr/bin/perl -a0p
$i/s%.%chop$F[$i++&7]%eg>3|/(.)((.|\H{6}|\H{9})\1|\H{7}\1.)\1/||redo;$_=$1?yes:n.o

これは、単一方向の水平正規表現ソリューションと回転を組み合わせたものです

説明:

このソリューションでは、次の4つのテストを繰り返し実行します。

/(.).\1\1/,      // 3-in-a-row horizontally after left-most shifts right
/(.)\C{9}\1\1/,  // 3-in-a-row horizontally after left-most shifts down
/(.)\C{7}\1.\1/, // 3-in-a-row horizontally after middle shifts down
/(.)\C{6}\1\1/,  // 3-in-a-row horizontally after right-most shifts down

\C「任意の文字」はどこにありますか(.これには改行が含まれません)。\C非推奨であり、警告が表示されることを除いて、\H代わりに(非水平スペース)を使用します。これはすべての数字と改行をキャプチャするのに十分です。

4回転後、これは必要な16のテストすべてを完了します。

-p                            Read lines from STDIN, print $_ at the end
-0                            No line ending => slurp ALL of STDIN
-a                            Split $_ into @F. Since there are no spaces
                              on the rows this means each element of @F is
                              1 row

    s%.%chop$F[$i++&7]%eg     Replace each row by the removed last column
                              This is therefore a left rotation. Very short
                              but at the cost of using @F. To make sure that
                              @F gets refilled from $_ each time I won't be
                              able to use while, until, eval or do$0 for the
                              loops but have to use redo. That costs a few
                              bytes but less than having to do my own split
$i/                      >3   The previous regex replacement always
                              returns 64 and each time through the loop $i is
                              increased by 64. So if this division reaches
                              4 all rotations have been done

/(.)((.|\H{6}|\H{9})\1|\H{7}\1.)\1/ This is the 4 regexes mentioned above
  ||redo                      Stop the loop if the regex matches or we
                              rotated 4 times
$_=$1?yes:n.o                If the regex matched $1 will be one of the
                              color digits (which cannot be 0) and this will
                              assign "yes" to $_. If the regex didn't match
                              in 4 times $1 will get its value from the last
                              succesful regex in scope which will be the one
                              from the rotation, but that one doesn't have
                              any () so $1 will be unset. So in case there
                              is no move $_ will be set to "no" (which needs
                              to be constructed because "no" is a keyword)

1

Python3、314B

import itertools as T,copy
r=[]
K=range(8)
J=[list(input())for w in K]
P=T.product
f=lambda A:["yes"for b in[A[m][n:]for m,n in P(K,K[:6])]if b[0]==b[1]==b[2]]
for i,j,x in P(K,K,[0,1]):
 t=j+1-x
 if i+x<8and t<8:B=copy.deepcopy(J);B[i][j],B[i+x][t]=B[i+x][t],B[i][j];r+=f(B)+f(list(zip(*B)))
r+=["no"]
print(r[0])

任意の大きな入力サイズを処理するには、8、6行目の5、および9行目の8を変更します。また、各値が何であるかを気にしませんので、あなたはそれを供給することができます:

absdefgh
sdkljahs
lsdfjasd
fjdhsdas
dkjhfasd
sdfhaskd
sdkfhkas
weriuwqe

そして、それは戻りyesます。

注釈

import itertools as T,copy 
            # itertools.product is going to save us lots of for loops
r=[]        # result
K=range(8)  # we can use range(8) everywhere, so this saves more than the usual R=range
J=[list(input())for w in K] 
            # input handling: keep everything as a length-1 string to avoid map(int,input())
P=T.product
f=lambda A:["yes"for b in[A[m][n:]for m,n in P(K,K[:6])]if b[0]==b[1]==b[2]] 
            # check the condition horiontally only. K[:6] is the same as range(5)
            # A[m][n:n+3] would be neater, but not actually needed
for i,j,x in P(K,K,[0,1]): 
            # <3 itertools.product! 3 for-loops without it.
            # NB we're only going right and downwards
 t=j+1-x
 if i+x<8and t<8: 
            # don't want out-of-bounds errors at the edges
  B=copy.deepcopy(J) 
            # preserve the reference array
  B[i][j],B[i+x][t]=B[i+x][t],B[i][j] 
            # do the switch
  r+=f(B)+f(list(zip(*B))) 
            # do the test. you could end up with lots of 'yes's in r.
            # zip(*B) takes the transpose, so that f checks the columns too
r+=["no"]   # happens to ensure that r is nonempty
print(r[0]) # only prints no if r was empty before the last line

1

GNU sed 255 + 2 = 257B

これはpythonほど良くないだろうと思っていましたが、今はそうです:-/今日はインターネットにアクセスできなかったので、これをsedで解決することに専念しました:)。-rフラグで呼び出す必要があります。つまりsed -rf command.sed < input、スコアに2を追加しました。

:a
$!N
s/\n/ /g
ta
:b
/^((\w)(\w\2\2|\2\w\2|\w\2\w* \w\2|\2\w* \w\w\2|\w* (\2\w* \w* \2|\w* \2\w* \2|\w\2\2|\w\2\w* \2|\2\w* \w\2|\w\2\w* \w\2))|\w((\w)(\w* \6\w\6|\6\w* \6|\w* (\6\w \w\6|\w\6\w* \6|\6\w* \6))|\w(\w)\w* \9\9))/c\yes
s/\w(\w*)/\1/g
tb
c\no

使い方:

  1. グリッドをスペースで区切られた文字の1行に読み取ります
  2. motherload正規表現を使用して、最初の列に一致があるかどうかを確認します*-はいの場合、行全体を「yes」に置き換えます(プログラムを終了します)
  3. 各列の最初の文字を削除し、2に移動した場合
  4. しなかった場合(行が空の場合)行全体を 'no'に置き換えます

1

ルビー、201バイト

正規表現やブルートフォースを使用しない(これらは素晴らしいのですが)この大きな課題に対する解決策が見られないことに失望しました。STDINで入力を受け取ります。

コアのビット演算アルゴリズムは、@ leanderによるGame Development Stack Exchangeのこの素晴らしい回答から派生しています。

s=$<.read
$><<(?1..?9).any?{|n|a=[0]*19
s.scan(n){i=$`.size
a[i/9+1]+=2**(i%9)
a[i%9+10]+=2**(i/9)}
a.each_cons(3).any?{|x,y,z|q=y&y<<1
l=q<<1
q>>=2
y&(l<<1|q>>1)|(q|l|(y&y<<2)>>1)&(x|z)>0}}?"yes":"no"

Rubyラムダ、181バイト

ここでは、文字列を取り、trueまたはを返すラムダとしてfalseです:

->s{(?1..?9).any?{|n|a=[0]*19
s.scan(n){i=$`.size
a[i/9+1]+=2**(i%9)
a[i%9+10]+=2**(i/9)}
a.each_cons(3).any?{|x,y,z|q=y&y<<1
l=q<<1
q>>=2
y&(l<<1|q>>1)|(q|l|(y&y<<2)>>1)&(x|z)>0}}}

repl.itで参照してください:https ://repl.it/ColJ/2

アンゴルフド&説明

->s{
  (?1..?9).any? {|n|
    a = [0] * 19

    s.scan(n) {
      i = $`.size
      a[i/9+1] += 2**(i%9)
      a[i%9+10] += 2**(i/9)
    }

    a.each_cons(3).any? {|x,y,z|
      q = y & y << 1
      l = q << 1
      q >>= 2
      y & (l << 1 | q >> 1) |
        (q | l | (y & y << 2) >> 1) &
        (x | z) > 0
    }
  }
}

コードは、数字「1」から「9」まで反復します。各反復には、2つの個別のステップがあります。

最初のステップはボード変換s.scan(n)です。これは、変更されていないコードのブロックで確認できます。バイナリ文字列で、一致する数字を1として、その他すべてを0として処理することにより、ボードを各行に1つずつの8つの整数の配列に変換します。たとえば、行を取り12231123ます。最初の反復では、これは、バイナリ文字列となるであろう10001100同じ列となる第2の反復において進数140である(すべて1は、-ERなるステー1S、他のすべての桁が0になる)、01100010(2S全てが2Sになると他のすべての数字は0)、または10進数の98になります。

同時に2番目の変換を実行します。これは、最初の変換と同じですが、ボードが90度回転します。これにより、同じロジックを使用して、水平一致を垂直一致とすることができます。簡単にするために、2つのボードを連結して、先頭、中央(2つのボードを分離する)、およびパディング用の末尾にゼロを付けた1つの長いボードにします。

2番目のステップは、一致する可能性のあるものを検索することですeach_cons(3).any?。これは、ブロックで確認できます。変換された行(現在は8ビット整数)は、ビット演算を使用して3行(xyz)のグループで(重複して)チェックされます。各グループは、一致が行で行うことができるかどうかを確認するためにチェックされ、Y、いずれかの行にピースをシフトすることによって、Y又はへピースをシフトすることによって、YからX又はZ。元のボードと回転したボードの両方の行の前後にゼロの「行」があるため、ボードの最初の行か最後の行かを確認する必要はありません。

一致するものが見つからなかった場合、次の反復に進みます。

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