ตรวจสอบบอร์ด Minesweeper


33

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

ตามปกติคุณควรให้ฟังก์ชันหรือโปรแกรมและโค้ดที่สั้นที่สุดเป็นไบต์ชนะ

ดูเพิ่มเติมความท้าทายที่ผ่านมาในการสร้าง , การแก้ปัญหาและอย่างเต็มที่ใช้เรือกวาดทุ่นระเบิด

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

สตริงเดียวเช่นนี้: 02X2 13X2 X211.

  • แถวของคณะกรรมการเรือกวาดทุ่นระเบิดจะถูกแยกออกด้วยช่องว่าง ดังนั้นข้างต้นหมายถึงบอร์ด 3x4:

    02X2
    13X2
    X211

  • แต่ละเซลล์เป็นตัวละคร: Xสำหรับเหมืองหรือจำนวนผ่าน08

  • แถวทั้งหมดมีความยาวเท่ากัน

  • มีอย่างน้อย 3 แถวและ 3 คอลัมน์

  • อินพุตไม่ได้ขึ้นต้นหรือลงท้ายด้วยเว้นวรรค แต่คุณอาจรวมบรรทัดใหม่ในตอนท้ายหากต้องการ

เอาท์พุท:

Truthy ที่สอดคล้องกันบนกระดานที่ถูกต้องและค่าFalsey ที่สอดคล้องกันบนกระดานที่ไม่ถูกต้อง ความสอดคล้องกันหมายความว่าเอาต์พุต Truthy ทั้งหมดเหมือนกันและเอาต์พุต Falsey ทั้งหมดเหมือนกัน

กรณีทดสอบ

แต่ละบรรทัดเป็นกรณีทดสอบแยกกัน

True:

02X2 13X2 X211
XXXX XXXX XXXX XXXX
XX4X2 5X6X4 XX6XX 4XX54 2X4XX

False:

02X2 13X2 X212
XXXX XXXX X7XX XXXX
XX5X2 5X6X4 XX6XX 4XX54 2X5XX

คุณควรระบุผลลัพธ์ที่ผิดพลาดที่สอดคล้องกันจะต้องแตกต่างจากผลลัพธ์ที่เป็นจริงที่สอดคล้องกัน ;-)
John Dvorak

@JanDvorak นั่นควรจะบอกเป็นนัยว่าพวกเขาเป็น Truthy และ Falsey ตามลำดับ
xnor

ไม่ได้จริงๆ "ความจริง" และ "เท็จ" เป็นเพียงสองป้ายกำกับที่คุณให้เรากำหนด ฉันไม่เห็นข้อ จำกัด ใด ๆ ที่พวกเขาเป็นจริงหรือเท็จตามลำดับในภาษาที่เราใช้ คำเดียวที่อาจทำให้พวกเขาต้องมีความแตกต่างคือ "ระบุ" คำกริยา ฉันไม่แน่ใจว่ามันจะนับว่าเป็นข้อมูลจำเพาะ (แต่ก็ยังเป็นสิ่งต้องห้ามเป็นช่องโหว่มาตรฐาน)
John Dvorak

4
@JanDvorak 'ความจริง' และ 'เท็จ' เป็นคำศัพท์ที่ใช้กันโดยทั่วไปถ้าฉันไม่ผิดใช้โดยทั่วไปในการอธิบายสิ่งต่าง ๆ (ไม่จำเป็นต้องเป็นคนโง่) ที่ประเมินว่าจริงหรือเท็จเมื่อพิมพ์ไปที่คนโง่ ตัวอย่างเช่น 0 นั้นเป็นเท็จและ 1 โดยทั่วไปจะเป็นความจริง
KSab

1
@JanDvorak Nope, Truthy / Falsey ต้องตรงกับถูกต้อง / ไม่ถูกต้อง
xnor

คำตอบ:


11

Python 2, 132 129 128

def f(s):w=s.find(' ');E=dict(enumerate(s));return all(E[i]in' X'+`sum(E.get(i+d/3*~w+d%3+w,5)>'O'for d in range(9))`for i in E)

ฉันเคยenumerateเล่นกอล์ฟ ... และยังเคยใช้rangeที่อื่นในโปรแกรมเดียวกัน เห็นได้ชัดว่ามีบางอย่างผิดปกติ

แก้ไข: ทำซ้ำdict(enumerate(s))มากกว่าenumerate(s)ดังนั้นenumerateไม่จำเป็นต้องถูกเรียกสองครั้ง


ช่างฉลาดใช้~อะไรดี! และพจนานุกรมที่จะทำให้การจัดทำดัชนีนอกขอบเขตทำได้ถูกต้อง
xnor

@xnor ความคิดเห็นของคุณเกี่ยวกับ~ผู้ประกอบการทำให้ฉันสังเกตเห็นว่าฉันใช้มันสองครั้งโดยไม่มีเหตุผลเลยซึ่งการใช้เพียงครั้งเดียวจะเห็นได้ชัดว่าทำสิ่งเดียวกัน ฉันคิดว่าส่วนพจนานุกรมนั้นสนุกดีขอบคุณ
feersum

9

Pyth, 43

Jhxzd!f-@zT+" X"`sm/:+*JNztd+d2\Xm+T*kJU3Uz

ลองมันนี่

คำอธิบาย:

  • Jhxzd: นี่คือตำแหน่งของช่องว่างแรกในอินพุต + 1 ( zในอินพุตdคือช่องว่าง) มันคือการแยกในอินพุตระหว่างเซลล์ที่ติดกันตามแนวตั้งบนบอร์ด
  • !f: นี่คือตรรกะไม่ใช่ ( !) ของตัวกรอง ( f) ซึ่งจะเป็นTrueถ้าหากว่านิพจน์นั้นเป็นเท็จสำหรับทุกองค์ประกอบของลำดับ
  • -@zT: นำตัวละครไปที่ที่ตั้งT(ตัวแปรแลมบ์ดา) จากอินพุตและลบลักษณะที่ปรากฏของ: (นี่จะเป็นจริงถ้าตัวละครไม่ได้ถูกลบออกและเป็นเท็จถ้าเป็น
  • +" X": ลบ Space, X และ
  • `: พิมพ์ซ้ำจาก
  • sm: ผลรวมของแผนที่ถึง
  • / \X: นับ "X" ใน
  • :+*JNz: ส่วนของอินพุตนำหน้าด้วยJอักขระตัวเต็ม
  • td+d2: จาก d-1 ถึง d + 2
  • m+T*kJU3: สำหรับ d ใน [T, T + J, T + 2 * J]
  • Uzrange(len(input))สำหรับเสื้อใน

7
Downvoters: ทำไมต้อง downvotes
isaacg

7

APL (NARS2000) (74)

{~0∊(G>9)∨G=(⍴G)↑{+/∊9<⍵∘⌷¨G∘.⊖(G←2-⍳3)∘.⌽⊂Z}¨⍳⍴Z←G↑⍨2+⍴G←¯1+⎕D⍳⊃⍵⊂⍨⍵≠' '}

นอกจากนี้ยังทำงานใน Dyalog APL ถ้ามีการตั้งค่า⎕ML3

คำอธิบาย:

  • ⊃⍵⊂⍨⍵≠' ': แบ่งช่องว่างและใช้รายการเพื่อสร้างเมทริกซ์
  • G←¯1+⎕D⍳: พบว่าดัชนีใน⎕Dแต่ละค่าลบ 1 Gและเก็บใน ( ⎕Dมีตัวเลขซึ่งไม่ใช่ตัวเลขใด ๆ จะกลายเป็น10)
  • Z←G↑⍨2+⍴G: เพิ่มสองบรรทัดและคอลัมน์ของศูนย์ที่ขอบของเมทริกซ์เพื่อจัดการกับวิจิตร
  • {... }¨⍳⍴Z: สำหรับแต่ละตำแหน่งZค้นหาจำนวนระเบิดในย่าน Moore ของตำแหน่งนั้น:
    • G∘.⊖(G←2-⍳3)∘.⌽⊂Z: หมุนZซ้าย, ขวา, ขึ้น, ลง, ซ้าย - ขวา, ขึ้น - ลง, ซ้าย - ขวาและขึ้น - ลง
    • ⍵∘⌷¨: สำหรับแต่ละสิ่งเหล่านี้ค้นหาองค์ประกอบที่ในเมทริกซ์ที่หมุนเหล่านี้
    • +/∊9<: นับจำนวนองค์ประกอบที่สูงกว่า 9 (นี่คือจำนวนระเบิด)
  • (⍴G)↑: ลบบรรทัดที่เพิ่มของศูนย์อีกครั้ง
  • G=: ตรวจสอบว่าแต่ละองค์ประกอบในGนั้นเท่ากับปริมาณของระเบิดที่ล้อมรอบตำแหน่งนั้นหรือไม่
  • (G>9)∨: และตรวจสอบว่าองค์ประกอบในGนั้นสูงกว่า9(นี่คือระเบิดหรือไม่)
  • ~0∊: return 1ถ้า matrix ที่ได้นั้นไม่มีเลขศูนย์ (= กำลังสองทั้งหมดเป็นลูกระเบิดหรือหมายเลขที่ถูกต้อง) และ0ถ้าเป็นเช่นนั้น

คุณนับจำนวนไบต์หรือตัวอักษรหรือไม่? คุณควรนับจำนวนไบต์
Tim S.

5
@TimS: มีการเข้ารหัส APL จำนวน 1 ไบต์นี่คือหนึ่งรายการ
marinus

5

C #, 321 320 305

bool s(string B){var L=B.Split(' ').Select(s=>' '+s+' ').ToList();var b=new string(' ',L[0].Length);L.Insert(0,b);L.Add(b);Func<int,int,IEnumerable<int>>E=Enumerable.Range;return E(1,b.Length-2).All(x=>E(1,L.Count-2).All(y=>L[y][x]=='X'||L[y][x]-'0'==E(x-1,3).Sum(X=>E(y-1,3).Sum(Y=>L[Y][X]=='X'?1:0))));}

ก่อนอื่นลองเล่นกอล์ฟและฉันรู้ว่า C # ไม่ใช่ภาษาในอุดมคติ

ผมหวังว่าการเขียนวิธีการเช่นที่ได้รับอนุญาตมิฉะนั้นเพิ่มอีก 7 staticตัวอักษร

เว้นระยะ:

bool s(string B) {
    var L = B.Split(' ').Select(s => ' ' + s + ' ').ToList();
    var b = new string(' ', L[0].Length);
    L.Insert(0, b);
    L.Add(b);
    Func<int, int, IEnumerable<int>> E = Enumerable.Range;
    return E(1, b.Length - 2).All(x =>
        E(1, L.Count - 2).All(y =>
            L[y][x] == 'X' ||
            L[y][x] - '0' == E(x - 1, 3).Sum(X =>
                E(y - 1, 3).Sum(Y =>
                  L[Y][X] == 'X' ? 1 : 0))));
}

การใช้ Linq ช่วยประหยัดพื้นที่บางส่วนเมื่อเทียบกับลูป แต่ก็ยากที่จะทำการดีบัก

ผมได้เรียนรู้เล็ก ๆ น้อย ๆ เช่นการแปลงโดยการลบchar => int'0'

ดูเหมือนง่ายกว่าที่จะวางกระดานด้วยช่องว่างดังนั้นการวนซ้ำมันจะง่ายขึ้น


1
คุณไม่สามารถเพียงแค่เปลี่ยนด้วย-'0' -48ใช้งานได้สำหรับฉันและบันทึกไม่กี่ไบต์สำหรับ 'X' และ '' ที่หลากหลาย
Roman Gräf

5

Python 2, 121

def f(B):n=B.find(' ')+1;R=range(len(B));print all(B[I]in' X'+`sum(2>I%n-i%n>-2<I/n-i/n<2<B[i]>'W'for i in R)`for I in R)

นี้เป็นแรงบันดาลใจอย่างมากจากคำตอบของ feersum ลำดับของวันนั้นมากเกินไป: แทนที่จะตรวจสอบเหมืองใน 9 เพื่อนบ้านของเซลล์ตรวจสอบทุก ๆ เซลล์เพื่อดูว่าเป็นของฉันหรือไม่

เราตรวจสอบว่าเซลล์สองเซลล์เป็นเพื่อนบ้านกับ2>r>-2<c<2ที่ไหนrและcมีความแตกต่างของแถวและคอลัมน์ของเซลล์เทียบเท่า{r,c}<{-1,0,1}หรือไม่ พิกัดเหล่านี้จะถูกคำนวณจากดัชนีเซลล์Iและiเป็นและc=I%n-i%n r=I/n-i/nการทำดัชนีลงในสตริงโดยตรงและมีประสิทธิภาพยิ่งกว่าการแยกแถวและคอลัมน์มากกว่าที่จะแปลงเป็นวัตถุ 2D เช่นรายการของรายการ การตรวจสอบเหมืองเป็นเทียบเท่าที่นี่เพื่อB[i]>'W'B[i]=='X'

การใช้enumerateจะมีการบันทึกอักขระสองตัวไว้บน ugly range(len(B))ยกเว้นว่าจะส่งคืนวัตถุตัววนซ้ำซึ่งไม่สนับสนุนการวนซ้ำสองลูปผ่านมัน


ฉันคิดว่าโมดูลัสเชิงลบควรใช้ได้กับ n; ~B.findแล้วคุณสามารถใช้
feersum

@feersum แต่น่าเสียดายที่มันเลอะ/เพราะมันปัดเศษเชิงลบลงด้วย
xnor

4

Python 2, 140

s=input();w=s.index(' ')+1
print all(c in'X 'or(int(c)==sum(s[max(0,a-1):max(0,a+2)].count('X')for a in[i-w,i,i+w]))for i,c in enumerate(s))

4

JavaScript (ES6), 135 133 125 122

f=s=>s.split(" ")[e="every"]((l,i,a)=>[...l][e]((c,j)=>!(-[-1,0,k=1][e]((y,m,q)=>q[e](x=>k+=(a[i+y]||0)[j+x]=="X"))-c+k)))

จัดเตรียมอินพุตให้กับฟังก์ชันเป็นสตริง:

f("XX4X2 5X6X4 XX6XX 4XX54 2X4XX");

สำหรับคำอธิบายให้ดูที่เวอร์ชันเก่าด้านล่าง รุ่นใหม่มาแทนที่forลูปที่มีeveryการโทรและการใช้ตัวแปรe="every"ที่จะทำแทนsomeArray[e](...)someArray.every(...)

นอกจากนี้ตัวนับkถูกจัดทำดัชนีไว้1เพื่อให้k+=...นิพจน์นั้นเป็นจริงเสมอเพื่อให้everyลูปทำงาน เรากำจัดพิเศษที่1โดยการลบtrueผล (ซึ่งตัวเลข coerces ไป1) ส่งกลับโดยการดำเนินการevery[-1,0,k=1][e](...)


เวอร์ชั่นเก่า:

f=s=>s.split(" ").every((l,i,a)=>[...l].every((c,j)=>{q=[-1,k=0,1];for(y of q)for(x of q)k+=(a[i+y]||0)[j+x]=="X";return c=="X"||k==c}))

รหัสที่มีช่องว่างและความคิดเห็น:

f=s=>s.split(" ")                 // split on spaces
      .every((l,i,a)=>             // for every line
                                   //     l: line string, i: line number, a: whole array
          [...l].every((c,j)=>{    // for every character
                                   //     c: character, j: index in string
              q=[-1,k=0,1];        // define counter k=0 and q=[-1,0,1]
              for(y of q)          // use q to loop adjacent spaces
                  for(x of q)

                      k+=              // add the following boolean to k:

                          (a[i+y]      //   from line number i+y...
                                 ||0)  //   (or a dummy zero, to prevent lookups on undefined)
                          [j+x]        //   ...get index j+x from the above value...
                                =="X"; //   ...and compare it to "X"

              return !(k-c)     // after the loop, this character passed if
                                // the char equals the number of counted X's (so k-c is 0)
                                // or it is an X itself (so `k-c` is NaN)
          })
      )

everyวิธีการอาร์เรย์JavaScript ใช้การเรียกกลับและใช้การเรียกกลับไปยังองค์ประกอบทุกส่วนของอาร์เรย์ หากโทรกลับใด ๆ ที่ส่งกลับค่า falsey ที่ผลตอบแทนการโทรeveryfalse

บูลีนใน JS ถูกบังคับให้ 1 หรือ 0 เมื่อส่วนหนึ่งของการเพิ่ม สำหรับพื้นที่โดยรอบในแต่ละเรา "เพิ่ม" ผลบูลของการเปรียบเทียบความคุ้มค่าที่จะXแล้วเพิ่มค่าที่เคาน์เตอร์ในการแสดงออกk k += (... == "X")ดังนั้นkมีการนับจำนวนของรอบXs เพราะtrueนับเป็น1และนับเป็นfalse0


แทนที่จะc=="X"ลองใช้!c/1ซึ่งจะช่วยให้คุณประหยัดจำนวนคู่ของไบต์มาก! !!c/1ถ้ามันล้มเหลวลอง เหตุผลก็คือ'X'/1 => NaNและNaNเป็นเท็จ คุณตรวจสอบว่าc=='X'ทำไมไม่ลองตรวจสอบว่ามันไม่ได้falseหรือไม่
Ismael Miguel

@IsmaelMiguel ที่ประเมินเช่นเดียวกับ(!c)/1ที่ไม่ได้ช่วย แต่น่าเสียดายที่ ฉันจำเป็นต้องมีวงเล็บ!(c/1)ซึ่งค่าใช้จ่าย 2. นอกจากนี้ยัง0/1เป็น falsey เพื่อให้การป้อนข้อมูลที่ไม่ถูกต้อง " 0X" trueจะมีผลที่ไม่ถูกต้อง สิ่งที่ดีที่สุดที่ฉันสามารถทำได้ในขณะที่ยังคงเคารพศูนย์คือการรวมสองเงื่อนไขเข้าด้วยกันกับวลีที่ถูกทำให้เป็นโมฆะเช่น!(+c+1&&k-c)นั้น แต่นั่นก็มีความยาวเท่ากันกับที่ฉันมีอยู่แล้ว
apsillers

@ IsmaelMiguel ขอบคุณที่ให้ฉันคิดเกี่ยวกับมันแม้ว่า - ฉันได้ตระหนักว่า!(k-1-c)การทดสอบทั้งสองเงื่อนไขเพราะถ้าการkแข่งขันc(ลบด้วย 1 ชดเชย) แล้วการปฏิเสธทำให้เป็น0จริงและถ้าcไม่ใช่ตัวเลขเราจะได้รับNaNและการปฏิเสธ trueนอกจากนี้ยังมี
apsillers

คุณหิวจริงๆ! คุณกิน 10 ไบต์ตั้งแต่รหัสเริ่มต้น! ฉันชอบโซลูชันที่คุณคิดขึ้นมา +1 สำหรับทางออกของคุณ!
Ismael Miguel

3

CJam, 70 65 63 ไบต์

1l_S#):L)S*+:Q{Ii33/2%[0~1LL)L(L~)L~_))]W):Wf+Qf='X/,(scI==&}fI

นี้สามารถเล่นกอล์ฟได้มาก

ให้1สำหรับบอร์ดที่ถูกต้องและ0สำหรับบอร์ดที่ไม่ถูกต้อง

กรณีทดสอบ

{-1:W;
1l_S#):L)S*+:Q{Ii33/2%[0~1LL)L(L~)L~_))]W):Wf+Qf='X/,(scI==&}fI
}6*]N*

อินพุต

02X2 13X2 X211
XXXX XXXX XXXX XXXX
XX4X2 5X6X4 XX6XX 4XX54 2X4XX
02X2 13X2 X212
XXXX XXXX X7XX XXXX
XX5X2 5X6X4 XX6XX 4XX54 2X5XX

เอาท์พุต

1
1
1
0
0
0

ลองออนไลน์ได้ที่นี่


3

JavaScript (ES6) 98

การใช้ฟังก์ชันบางตัวเพื่อใช้ฟังก์ชันกับอักขระแต่ละตัวของสตริง
ฟังก์ชันจะส่งคืน

  • false ถ้าว่าง
  • NaN ถ้า 'X' (ลบค่าซ้ำ ๆ จากอักขระที่ไม่ใช่ตัวเลขเช่น 'X' ให้ NaN)
  • ค่าตัวเลข 0 หากมีจำนวน adiacent 'X' ที่เหมาะสมไม่ใช่ 0
    การตรวจสอบภายในใช้แผนที่เพียงเพราะสั้นกว่าforEach

ผลตอบแทนบางส่วนเป็นจริงที่ค่าความจริงแรก (ในกรณีนี้ไม่ใช่ศูนย์) หมายถึงการตรวจสอบล้มเหลว ผลลัพธ์จะถูกทำให้ไร้ผลเพื่อให้เป็นจริง / เท็จที่เป็นที่รู้จักมากขึ้น

F=v=>![...v].some(
  (x,p)=>x!=' '&&[1,-1,l=v.search(' '),-l,++l,-l,++l,-l].map(q=>x-=v[p+q]=='X')|x
)

ทดสอบในคอนโซล FireFox / FireBug

;["02X2 13X2 X212","XXXX XXXX X7XX XXXX","XX5X2 5X6X4 XX6XX 4XX54 2X5XX"
,"02X2 13X2 X211","XXXX XXXX XXXX XXXX","XX4X2 5X6X4 XX6XX 4XX54 2X4XX","111 1X1 111"]
.forEach(t => console.log(t, F(t)))

เอาท์พุต

02X2 13X2 X212 false
XXXX XXXX X7XX XXXX false
XX5X2 5X6X4 XX6XX 4XX54 2X5XX false
02X2 13X2 X211 true
XXXX XXXX XXXX XXXX true
XX4X2 5X6X4 XX6XX 4XX54 2X4XX true
111 1X1 111 true

1

R, 156 ตัวอักษร

a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])

ด้วยการเยื้องช่องว่างและการขึ้นบรรทัดใหม่เพื่อความชัดเจน:

a = b = do.call(rbind,strsplit(scan(,""),"")) #Reads stdin and turn into a matrix
for(i in 1:nrow(a)) #Ugly, ugly loop
    for(j in 1:ncol(a))
        b[i,j] = sum(a[abs(i-row(a))<2 & abs(j-col(a))<2]=="X")
v = a!="X"
all(b[v]==a[v])

ตัวอย่าง:

> a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])
1: XX4X2 5X6X4 XX6XX 4XX54 2X4XX
6: 
Read 5 items
[1] TRUE
> a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])
1: XXXX XXXX XXXX XXXX
5: 
Read 4 items
[1] TRUE
> a=b=do.call(rbind,strsplit(scan(,""),""));for(i in 1:nrow(a))for(j in 1:ncol(a))b[i,j]=sum(a[abs(i-row(a))<2&abs(j-col(a))<2]=="X");v=a!="X";all(b[v]==a[v])
1: XX5X2 5X6X4 XX6XX 4XX54 2X5XX
6: 
Read 5 items
[1] FALSE
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.