พิจารณาว่ามีการเคลื่อนไหวในเกม Bejeweled / match 3 หรือไม่


20

พื้นหลัง

ในเกม Bejeweled และคล้ายกันผู้เล่นจะต้องสลับอัญมณีสองอันที่อยู่ติดกัน (ไม่มีเส้นทแยงมุม) ในตารางอัญมณี 8x8 เพื่อให้ตรงกับสามสีเดียวกันในแถว อัญมณีสามารถจับคู่ในแนวนอนหรือแนวตั้ง การเล่นเกมจะดำเนินต่อไปจนกว่าจะไม่มีการเคลื่อนไหวใด ๆ ที่สามารถทำให้เกิดเป็นสามแถวติดต่อกันซึ่งเป็นจุดสิ้นสุดของเกม

งาน

เป้าหมายคือการเขียนโปรแกรมที่กำหนดว่าเกมของ Bejeweled นั้นยังไม่จบ กล่าวอีกนัยหนึ่งมันต้องตรวจสอบเพื่อดูว่ามีการเคลื่อนไหวที่เป็นไปได้ที่ทำให้อย่างน้อยสามในแถว อาจมีมากกว่าสามอัญมณีในแถวและยังคงเป็นการย้ายที่ถูกต้อง

อินพุต

โปรแกรมของคุณจะต้องยอมรับผ่านอินพุตมาตรฐานแสดง 8x8 ของตาราง Bejeweled แต่ละอัญมณีเจ็ดสีจะแสดงเป็นตัวเลขจาก 1 ถึง 7 แต่ละบรรทัดจะมีหนึ่งแถวและ 8 บรรทัดแต่ละบรรทัดประกอบด้วย 8 หลักจะถูกป้อนข้อมูล ดูตัวอย่าง คุณสามารถสันนิษฐานได้ว่าการป้อนข้อมูลจะเป็นไปตามรูปแบบนี้เสมอและจะไม่มีสามในแถวอยู่แล้ว

เอาท์พุต

จากนั้นโปรแกรมจะต้องส่งออก (ไปยังเอาต์พุตมาตรฐาน) yesหรือnoขึ้นอยู่กับว่ามีการย้ายที่ถูกต้องอย่างน้อยหนึ่งครั้งหรือไม่ซึ่งจะส่งผลให้เกิดอัญมณีสามแถวขึ้นไปในแถว โปรแกรมของคุณจะต้องไม่ส่งออกสิ่งอื่นที่ไม่ใช่เช่นเดียวของทั้งสองหรือyesno

กฎระเบียบ

โปรแกรมของคุณต้องไม่ใช้ไฟล์หรือทรัพยากรภายนอกอาร์กิวเมนต์บรรทัดคำสั่งหรือต้องการชื่อไฟล์ที่แน่นอน โปรแกรมที่มีจำนวนไบต์น้อยที่สุดในซอร์สโค้ดจะเป็นผู้ชนะ

ตัวอย่าง

การป้อนข้อมูล:

12314131
13224145
54762673
61716653
61341144
23453774
27645426
75575656

เอาท์พุท: yes

การป้อนข้อมูล:

35261546
76421754
15743271
62135642
35617653
64565476
54427254
15635465

เอาท์พุท: no

ดูคำตอบของ MT0 ด้านล่างสำหรับกรณีทดสอบเพิ่มเติม


มันเป็นแค่แถวหรือคอลัมน์ด้วย
TheDoctor

@TheDoctor Columns ด้วย เมื่อฉันใช้วลี "สามในแถว" ฉันหมายความว่าพวกเขาจะต้องเรียงกันในแนวนอนหรือแนวตั้ง
bdr9

@ bdr9 คุณอาจต้องการแก้ไขใน
John Dvorak

@JanDvorak เรียบร้อยแล้ว
bdr9

นอกจากนี้อาจต้องการแก้ไขหากอนุญาตให้มี 4+ แถว
Justin

คำตอบ:


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=>ไปยังจุดเริ่มต้นของโค้ดหรือมิฉะนั้นเพื่อรับอินพุตจากพรอมต์จากนั้นแทนที่sด้วยprompt())

ผลลัพธ์คือคอนโซล

3 rdแก้ไข: 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 thเหมือนกับอักขระ (i + 2) thและอักขระ (i + 3) th (เทียบเท่ากับนิพจน์ทั่วไป(.).\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'

สร้างการแสดงออกปกติหลายรายการ (ดูรายละเอียดเพิ่มเติมด้านล่าง) โดยใช้คู่ของค่าที่นำมาจากสตริง Base-18 10907160789879h8และORทำการทดสอบทั้งหมด หากต้องการลดให้มากขึ้นคุณสามารถทราบว่านิพจน์ทั่วไปมาเป็นคู่โดยที่หนึ่งคือ "ย้อนกลับ" ของอีกรายการหนึ่ง (ละเว้นนิพจน์ปกติสำหรับ 3-in-row ในแนวนอนและแนวตั้งเนื่องจากสถานะ OP จะไม่มีการนำเสนอ - หากคุณต้องการเพิ่มการทดสอบเหล่านั้นกลับมาในผนวก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
];

( หมายเหตุ: regexs สำหรับ 3-in-a-row ในแนวนอน (0 th ) และแนวตั้ง (ส่วนหนึ่งของ 9 th ) ไม่เกี่ยวข้องเนื่องจาก 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 ) และเพิ่มในเอาต์พุตใช่ / ไม่ใช่

แก้ไข 3

  • เพิ่มโซลูชัน ECMAScript 6 เพื่อสร้างนิพจน์ปกติแต่ละรายการจากสตริง Base-18
  • ลบการทดสอบสำหรับ 3-in-a-row ในแนวนอน (ตามที่m-buettner แนะนำ )

แก้ไข 4

เพิ่มโซลูชันอื่น (สั้นกว่า) และอีกสองกรณีทดสอบที่ไม่ตรงกัน

แก้ไข 5

  • โซลูชันดั้งเดิมแบบย่อโดยแทนที่บรรทัดใหม่ด้วยอักขระที่ไม่ใช่ตัวเลข (ตามที่แนะนำโดยVadimR )

แก้ไข 6

  • โซลูชันดั้งเดิมที่สั้นลงโดยรวมบิตของนิพจน์ทั่วไป (ตามที่แนะนำโดยVadimR )

1
ทางออกที่ดี! ฉันไม่คิดว่า regex สามารถทำงานได้ โปรดรวมการ?'yes':'no'นับจำนวนตัวละครของคุณไว้เพื่อความเป็นธรรมเพราะอยู่ในข้อกำหนดและทุกคนใช้งาน
bdr9

ขอบคุณสำหรับกรณีทดสอบเพิ่มเติมฉันเพิ่มลิงก์ไปยังคำตอบของคุณเพื่อให้คนอื่นเห็นได้
bdr9

โว้ว. +1 สำหรับ regex
DankMemes

H-mm ไม่มีตัวดัดแปลงใน JS สำหรับ.จับคู่อักขระใด ๆ รวมถึงการขึ้นบรรทัดใหม่ ด้วย Perl, regexp ที่รวมกันเป็นสตริง 129 ไบต์ (ซึ่งขี้เกียจ, ฉันคอมไพล์ด้วยRegexp :: Assemble ), ดังนั้นโปรแกรม Perl ทั้งหมดประมาณ 150 ไบต์
2846289

1
@VadimR ขอบคุณ แต่คุณสามารถไปแทนที่.{8}|.{9}ด้วย.{8,9}และต่อไปได้.{7}|.{8}ด้วย.{7,8}
MT0

3

Python 383

เพียงไพ ธ อนบรรทัดเดียว!

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
โหวตขึ้นสำหรับ comprehensions ที่เข้าใจไม่ได้ :)
alexander-brett

2

Node.js - โซลูชันไร้เดียงสา - 905 ไบต์

ยังไม่มีคำตอบดังนั้นฉันจะโพสต์โซลูชั่นที่ไร้เดียงสาจริงๆใน Node.js

มันจะผ่านทุกการเคลื่อนไหวที่เป็นไปได้แล้วทดสอบกระดานผลลัพธ์เพื่อดูว่ามี 3 ในแถว

Golfed (พร้อมคอมไพเลอร์ปิดของ Google) (มีบางสิ่งที่แฮ็กอยู่ในนั้น! 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

สิ่งนี้รวมโซลูชัน regex แนวนอนทิศทางเดียวเข้ากับการหมุน

คำอธิบาย:

ในโซลูชันนี้ฉันจะหมุนซ้ำ ๆ และทำแบบทดสอบ 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, 5 บนบรรทัด 6 และ 8s บนบรรทัด 9 เพื่อจัดการกับอินพุตขนาดใหญ่โดยพลการ ยังไม่สนใจว่าแต่ละค่าคืออะไรดังนั้นคุณสามารถป้อนได้:

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

ฉันคิดว่านี่จะไม่ดีเท่างูหลาม แต่ตอนนี้: - / ฉันไม่ได้เข้าใช้อินเทอร์เน็ตวันนี้ฉันเลยยุ่งกับการแก้ปัญหานี้ด้วยสติ :) ต้องมีการเรียกด้วยแฟล็ก -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. อ่านตารางลงในบรรทัดเดียวของอักขระที่คั่นด้วยช่องว่าง
  2. ใช้ motherload regex เพื่อค้นหาว่ามีการจับคู่ในคอลัมน์แรก * - ถ้าใช่ให้สลับทั้งบรรทัดเป็น 'ใช่' (สิ้นสุดโปรแกรม)
  3. ตัดอักขระตัวแรกจากแต่ละคอลัมน์และข้ามไป 2 ถ้าเราทำ
  4. หากเราไม่ทำ (บรรทัดว่าง) ให้แทนที่ทั้งบรรทัดด้วย 'ไม่'

1

ทับทิม, 201 ไบต์

ฉันรู้สึกผิดหวังที่ไม่เห็นวิธีแก้ปัญหาสำหรับความท้าทายที่ยิ่งใหญ่นี้ซึ่งไม่ได้ใช้แรง regex หรือกำลังดุร้าย (ถึงแม้ว่ามันจะยอดเยี่ยม) ดังนั้นฉันจึงเขียนมัน มันใช้เวลาอินพุตบน STDIN

อัลกอริธึมทางคณิตศาสตร์ bitwise ที่สำคัญมาจากคำตอบที่ยอดเยี่ยมนี้ใน Game Exchange Stack Exchangeโดย @leander

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

Ungolfed & คำอธิบาย

->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. ​​" การวนซ้ำแต่ละครั้งมีสองขั้นตอนแบบไม่ต่อเนื่อง:

ขั้นตอนแรกคือการแปลงบอร์ดซึ่งคุณสามารถเห็นได้ในs.scan(n)บล็อกในโค้ดที่ไม่ได้รับการดัดแปลง มันจะแปลงบอร์ดให้เป็นอาร์เรย์ของจำนวนเต็ม 8 จำนวนหนึ่งสำหรับแต่ละแถวโดยถือว่าตัวเลขที่ตรงกันเป็น 1s และอื่น ๆ ทั้งหมดเป็น 0 ในสตริงไบนารี 12231123ตัวอย่างเช่นใช้แถว ในการทำซ้ำครั้งแรกสิ่งนี้จะกลายเป็นสตริงไบนารี่10001100(ทั้งหมด 1 วินาทีกลายเป็น - เอ้อ, พัก - 1 วินาทีและตัวเลขอื่น ๆ ทั้งหมดกลายเป็น 0) ซึ่งเป็นเลขทศนิยม 140 ในการทำซ้ำครั้งที่สองแถวเดียวกันจะ01100010กลายเป็น ตัวเลขอื่นทั้งหมดกลายเป็น 0s) หรือ 98 ทศนิยม

มันทำการเปลี่ยนแปลงครั้งที่สองพร้อมกันซึ่งเป็นแบบแรกและแบบหมุน 90 องศา สิ่งนี้ทำให้เราใช้ตรรกะเดียวกันในการสร้างการจับคู่แนวนอนเป็นแนวตั้ง เพื่อความเรียบง่ายมันเชื่อมสองบอร์ดเข้ากับกระดานยาวเดียวโดยมีศูนย์ที่จุดเริ่มต้นตรงกลาง (เพื่อแยกกระดานทั้งสอง) และสิ้นสุดสำหรับช่องว่างภายใน

ขั้นตอนที่สองคือการค้นหาการจับคู่ที่เป็นไปได้ซึ่งคุณสามารถเห็นในeach_cons(3).any?บล็อก แถวที่ถูกแปลง (ซึ่งตอนนี้เป็นจำนวนเต็ม 8 บิต) จะถูกตรวจสอบในกลุ่ม (ทับซ้อนกัน) ของสามแถว ( x , y , z ) โดยใช้เลขคณิตแบบบิต แต่ละกลุ่มจะมีการตรวจสอบเพื่อดูว่าการแข่งขันสามารถทำในแถวYอย่างใดอย่างหนึ่งโดยขยับชิ้นในแถวYหรือโดยการขยับชิ้นลงในปีจากxหรือZ เนื่องจากมีศูนย์ "แถว" ก่อนและหลังทั้งแถวเดิมและแถวของกระดานหมุนเวียนเราไม่ต้องตรวจสอบว่าเราอยู่ในแถวแรกหรือแถวสุดท้ายของบอร์ด

หากไม่พบไม้ขีดไฟมันจะดำเนินต่อไปในรอบถัดไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.