元のソリューション: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=>
置き換え、その後プロンプトから入力を取るために、それ以外の場合は、コードの先頭にまたはs
でprompt()
)。
出力はコンソールへです。
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行の正規表現を無視します- 0088
Base-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
\d
sを.
-に置き換えると、6文字節約されます。
編集2
余分な非キャプチャグループを置き換え(?:.|\n)
て[\s\S]
削除し、(m-buettnerが示唆するように)後方参照を更新し、yes / no出力に追加しました。
編集3
- Base-18文字列から個々の正規表現を構築するECMAScript 6ソリューションを追加しました。
- (m-buettnerが示唆するように) 3行1列の水平方向のテストを削除しました。
編集4
別の(より短い)ソリューションと、さらに2つの不一致のテストケースを追加しました。
編集5
- 改行を数字以外の文字に置き換えることにより、元のソリューションを短縮しました(VadimRにより提案)。
編集6
- 正規表現のビットを組み合わせることにより、元のソリューションを短縮しました(VadimRによって提案されています)。