คุณสามารถเอาชนะหน่วยสืบราชการลับของอังกฤษได้หรือไม่ (ตัวแก้ Nonogram)


20

ถึงเวลาแล้วที่จะเริ่มภารกิจที่เต็มไปด้วยอันตรายเพื่อเอาชนะหน่วยสืบราชการลับของอังกฤษ จุดมุ่งหมายของการท้าทายนี้คือการเขียนรหัสที่สั้นที่สุดที่จะแก้ Nonogram

Nonogram คืออะไร

ปริศนา Nonogram

กฎนั้นง่าย คุณมีตารางกำลังสองซึ่งจะต้องเติมด้วยสีดำหรือว่างเปล่า ข้างแต่ละแถวของตารางจะแสดงความยาวของการวิ่งของสี่เหลี่ยมสีดำในแถวนั้น ด้านบนแต่ละคอลัมน์จะแสดงความยาวของการวิ่งของสี่เหลี่ยมสีดำในคอลัมน์นั้น www.games501.com ฟรีเป้าหมายของคุณคือค้นหาสี่เหลี่ยมสีดำทั้งหมด ในประเภทตัวต่อปริศนาตัวเลขนี้เป็นรูปแบบของการตรวจเอกซเรย์ที่ไม่ต่อเนื่องซึ่งวัดว่ามีการเติมเต็มของจำนวนสี่เหลี่ยมจัตุรัสในแถวหรือคอลัมน์ใด ๆ ตัวอย่างเช่นคำใบ้ของ "4 8 3" จะหมายถึงมีชุดของสี่, แปด, และสามช่องที่เติมเต็มตามลำดับโดยมีอย่างน้อยหนึ่งช่องว่างระหว่างกลุ่มที่ต่อเนื่องกัน [ 1 ] [ 2 ]

ดังนั้นการแก้ปัญหาของ Nonogram ข้างต้นจะเป็น:

แก้ไข nonogram

รายละเอียดการใช้งาน

คุณสามารถเลือกที่จะเป็นตัวแทนของ Nonogram ได้อย่างไรก็ตามคุณต้องการและนำมาเป็นข้อมูลในแบบที่คุณคิดว่าเหมาะสมกับภาษาของคุณ กันไปสำหรับการส่งออก เป้าหมายของความท้าทายนี้คือการทำงานให้สำเร็จ ถ้าคุณสามารถแก้ nonogram ด้วยสิ่งใดก็ตามที่โปรแกรมของคุณให้นั่นแสดงว่าถูกต้อง ข้อแม้หนึ่งคือคุณไม่สามารถใช้ตัวแก้ปัญหาออนไลน์ได้ :)

ปัญหานี้มีความท้าทายอย่างมากในขั้นตอนวิธี (np-complete) ซึ่งไม่มีวิธีแก้ปัญหาที่มีประสิทธิภาพอย่างสมบูรณ์ดังนั้นคุณจะไม่ถูกลงโทษเนื่องจากไม่สามารถแก้ปัญหาที่ใหญ่กว่าได้แม้ว่าคำตอบของคุณจะได้รับรางวัลอย่างหนักถ้าเป็น สามารถรับมือกับคดีใหญ่ (ดูโบนัส) ในฐานะที่เป็นมาตรฐานโซลูชันของฉันทำงานได้สูงถึง 25x25 โดยประมาณภายใน 5-10 วินาที เพื่อให้เกิดความยืดหยุ่นในภาษาต่างๆโซลูชันที่ใช้เวลาน้อยกว่า 5 นาทีสำหรับ nonogram 25x25 นั้นดีพอ

คุณอาจสมมติว่าตัวต่อเป็นรูปสี่เหลี่ยมจัตุรัส NxN เสมอ

คุณสามารถใช้เครื่องทำจิ๊กซอว์ nonogram ออนไลน์นี้เพื่อทดสอบวิธีแก้ปัญหาของคุณ

เกณฑ์การให้คะแนน

คุณมีอิสระที่จะใช้ภาษาใด ๆ ที่คุณต้องการและเนื่องจากเป็นรหัสกอล์ฟรายการจะถูกจัดเรียงตามลำดับ: accuracy -> length of code -> speed.อย่างไรก็ตามอย่าท้อใจกับภาษารหัสกอล์ฟคำตอบในทุกภาษาที่แสดงความพยายามในการเล่นกอล์ฟ ในวิธีที่น่าสนใจจะถูกยกระดับขึ้น!

โบนัส

ที่จริงผมได้เรียนรู้เกี่ยวกับ Nonograms จากการ์ดคริสมาสต์การเข้ารหัสลับที่ออกโดยหน่วยสืบราชการลับของอังกฤษที่นี่ ส่วนแรกนั้นเป็นแบบ Nonogram ขนาดใหญ่ 25x25 หากโซลูชันของคุณสามารถแก้ไขปัญหานี้ได้คุณจะได้รับความชื่นชม :)

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

7 3 1 1 7
1 1 2 2 1 1
1 3 1 3 1 1 3 1
1 3 1 1 6 1 3 1
1 3 1 5 2 1 3 1
1 1 2 1 1
7 1 1 1 1 1 7
3 3
1 2 3 1 1 3 1 1 2
1 1 3 2 1 1
4 1 4 2 1 2
1 1 1 1 1 4 1 3
2 1 1 1 2 5
3 2 2 6 3 1
1 9 1 1 2 1
2 1 2 2 3 1
3 1 1 1 1 5 1
1 2 2 5
7 1 2 1 1 1 3
1 1 2 1 2 2 1
1 3 1 4 5 1
1 3 1 3 10 2
1 3 1 1 6 6
1 1 2 1 1 2
7 2 1 2 5
-
7 2 1 1 7
1 1 2 2 1 1
1 3 1 3 1 3 1 3 1
1 3 1 1 5 1 3 1
1 3 1 1 4 1 3 1
1 1 1 2 1 1
7 1 1 1 1 1 7
1 1 3
2 1 2 1 8 2 1
2 2 1 2 1 1 1 2
1 7 3 2 1
1 2 3 1 1 1 1 1
4 1 1 2 6
3 3 1 1 1 3 1
1 2 5 2 2
2 2 1 1 1 1 1 2 1
1 3 3 2 1 8 1
6 2 1
7 1 4 1 1 3
1 1 1 1 4
1 3 1 3 7 1
1 3 1 1 1 2 1 1 4
1 3 1 4 3 3
1 1 2 2 2 6 1
7 1 3 2 1 1
#
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

และนี่คือรุ่นที่แตกต่างกันเล็กน้อยเพื่อความสะดวกของคุณ tuple ที่คั่นด้วยเครื่องหมายจุลภาค (row, col) ที่แต่ละองค์ประกอบเป็นรายการของรายการ

([[7, 3, 1, 1, 7],
  [1, 1, 2, 2, 1, 1],
  [1, 3, 1, 3, 1, 1, 3, 1],
  [1, 3, 1, 1, 6, 1, 3, 1],
  [1, 3, 1, 5, 2, 1, 3, 1],
  [1, 1, 2, 1, 1],
  [7, 1, 1, 1, 1, 1, 7],
  [3, 3],
  [1, 2, 3, 1, 1, 3, 1, 1, 2],
  [1, 1, 3, 2, 1, 1],
  [4, 1, 4, 2, 1, 2],
  [1, 1, 1, 1, 1, 4, 1, 3],
  [2, 1, 1, 1, 2, 5],
  [3, 2, 2, 6, 3, 1],
  [1, 9, 1, 1, 2, 1],
  [2, 1, 2, 2, 3, 1],
  [3, 1, 1, 1, 1, 5, 1],
  [1, 2, 2, 5],
  [7, 1, 2, 1, 1, 1, 3],
  [1, 1, 2, 1, 2, 2, 1],
  [1, 3, 1, 4, 5, 1],
  [1, 3, 1, 3, 10, 2],
  [1, 3, 1, 1, 6, 6],
  [1, 1, 2, 1, 1, 2],
  [7, 2, 1, 2, 5]],
 [[7, 2, 1, 1, 7],
  [1, 1, 2, 2, 1, 1],
  [1, 3, 1, 3, 1, 3, 1, 3, 1],
  [1, 3, 1, 1, 5, 1, 3, 1],
  [1, 3, 1, 1, 4, 1, 3, 1],
  [1, 1, 1, 2, 1, 1],
  [7, 1, 1, 1, 1, 1, 7],
  [1, 1, 3],
  [2, 1, 2, 1, 8, 2, 1],
  [2, 2, 1, 2, 1, 1, 1, 2],
  [1, 7, 3, 2, 1],
  [1, 2, 3, 1, 1, 1, 1, 1],
  [4, 1, 1, 2, 6],
  [3, 3, 1, 1, 1, 3, 1],
  [1, 2, 5, 2, 2],
  [2, 2, 1, 1, 1, 1, 1, 2, 1],
  [1, 3, 3, 2, 1, 8, 1],
  [6, 2, 1],
  [7, 1, 4, 1, 1, 3],
  [1, 1, 1, 1, 4],
  [1, 3, 1, 3, 7, 1],
  [1, 3, 1, 1, 1, 2, 1, 1, 4],
  [1, 3, 1, 4, 3, 3],
  [1, 1, 2, 2, 2, 6, 1],
  [7, 1, 3, 2, 1, 1]])

น่าเศร้าที่เว็บไซต์ของฉันหยุดทำงาน แต่เคยมีตัวแก้ Nonogram ที่รวดเร็วพอสมควร ฟังดูเกินไปประมาณ 5-10 นาที
Neil

1
codegolf.stackexchange.com/q/30081/21348ที่เกี่ยวข้อง
edc65

1
@dwana คุณไม่จำเป็นต้องกังวลเกี่ยวกับกรณีที่แก้ไม่ตก สำหรับคำตอบแบบสุ่มบน nonogram 25x25 คุณมีการกำหนดค่าที่เป็นไปได้ 2 ^ 625 ในบริบทนั้นมีมากกว่าสองเท่าของจำนวนอะตอมในเอกภพที่เป็นที่รู้จัก (เช่นถ้าคุณใช้แต่ละอะตอมในเอกภพเป็นบิตคุณยังคงมีพื้นที่ไม่พอที่จะเก็บความเป็นไปได้) ในแง่ของเวลาถ้าคุณใช้นาโนวินาที (เผื่อแผ่) เพื่อตรวจสอบความถูกต้องของการกำหนดค่าแต่ละครั้งมันจะใช้เวลา 7 ช่วงอายุของจักรวาลเพื่อให้โค้ดทำงานเสร็จ :)
gowrath

1
Ty สำหรับการชี้แจงกรณีที่ไม่สามารถแก้ไขได้ (+ ฉันมีพีซีที่มีเวทย์มนตร์ตรวจสอบคำตอบใน ~ 2.1546362E-186 วินาที)
dwana

1
CSV ของคุณไม่มีคำใบ้สแควร์ Here's JS บางอย่างที่จะสร้างพวกเขาs=[].fill([].fill(0,0,25),0,25);s[3][3]=s[3][4]=s3[3][12]=s3[3][13]=s3[3][21]=s[8][6]=s[8][7]=s[8][10]=s[8][14]=s[8][15]=s[8][18]=s[16][6]=s[16][11]=s[16][16]=s[16][20]=s[21][3]=s[21][4]=s[21][9]=s[21][10]=s[21][15]=s[21][20]=s[21][21]=1;
ติตัส

คำตอบ:


5

Brachylog , 70 69 ไบต์

[R:C]hlL~l:L:1f=.:3aR,.z:3aC,
tL,?he##ElL,E:2a
.<2,_1<
@b:4f:la
e.h1,

นี่ใช้รายการของสองรายการ (ตัวบ่งชี้แถวแรกจากนั้นตามด้วยรายการคอลัมน์) ตัวบ่งชี้แต่ละตัวคือรายการ (สำหรับไซต์ที่เหมือน[3,1]หนึ่งแถว)

รุ่นนี้ใช้เวลาประมาณ 3 นาทีในการแก้ตัวอย่างความท้าทาย 5 ต่อ 5

วิธีที่มีประสิทธิภาพมากขึ้นรุ่น 91 ไบต์

[R:C]hlL~l:L:1f:Cz:3az:Rz:3a=.:4aR,.z:4aC,
tL,?he##ElL,E:2a
.<2,_1<
:+a#=,?h
@b:5f:la
e.h1,

ลองออนไลน์!

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

สิ่งนี้ใช้เวลาประมาณ 0.05 วินาทีในตัวอย่างที่ท้าทาย 5 จาก 5 นี่เป็นวิธีที่ช้าเกินไปสำหรับกรณีโบนัสเนื่องจากฉันไม่รู้ว่าจะแสดงบล็อกของบล็อกที่คั่นด้วยศูนย์อย่างน้อยหนึ่งศูนย์ในแง่ของข้อ จำกัด ได้อย่างไร

คำอธิบาย

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

  • ภาคแสดงหลัก:

    [R:C]     Input = [R, C]
    hlL       The length of R is L
    ~l        Create a list of length L
    :L:1f     Each element of that list is a sublist of length L with cells 0 or 1 (Pred 1)
              %%% Part unique to the 93 bytes version
    :Cz       Zip the rows of the list of lists with C
    :3a       The sum of 1s in each row is equal to the sum of the indicators (Pred 3)
    z         Transpose
    :Rz       Zip the columns of the list of lists with R
    :3a       The sum of 1s in each column is equal to the sum of the indicators (Pred 3)
              %%%
    =.        Assign values to the cells of the list of lists which satisfy the constraints
    :4aR,     The blocks of 1s must match the indicators on rows
    .z        Transpose
    :4aC,     The blocks of 1s must match the indicators on columns
    
  • เพรดิเคต 1: บังคับให้แถวมีความยาวเฉพาะและแต่ละเซลล์คือ 0 หรือ 1

    tL,       L is the length given as second element of the input
    ?he       Take an element from the list
    ##ElL,    That element E is itself a list of length L
    E:2a      The elements of E are 0s and 1s (Pred 2)
    
  • เพรดิเคต 2: จำกัด ตัวแปรเป็น 0 หรือ 1

    .<2,      Input = Output < 2
    _1<       Output > -1
    
  • ภาคแสดง 3: ผลรวมของ 1s ในรายการจะต้องเท่ากับผลรวมของตัวบ่งชี้ (เช่นถ้าตัวบ่งชี้คือ [3: 1] รายการนั้นจะต้องมีผลรวม 4)

    :+a       Sum the elements of the list and sum the indicator
    #=,       Both sums must be equal
    ?h        Output is the list
    
  • ภาคที่ 4: ตรวจสอบว่าบล็อกของ 1s ตรงกับตัวบ่งชี้

    @b        Split the list in blocks of the same value
    :5f       Find all blocks of 1s (Pred 5)
    :la       The list of lengths of the blocks results in the indicator (given as output)
    
  • เพรดิเคตที่ 5: จริงสำหรับบล็อก 1 วินาทีไม่เช่นนั้นจะเป็นเท็จ

    e.        Output is an element of the input
      h1,     Its first value is 1
    

รู้สึกเหมือนเป็นเครื่องมือที่สมบูรณ์แบบสำหรับงาน คอยที่จะอธิบาย
Emigna

@ สรุปสิ่งนี้ยอดเยี่ยมมากฉันกำลังรอให้ใครบางคนใช้ภาษาโปรล็อกชันเพื่อทำสิ่งนี้ คุณลองกับเคส 25x25 หรือยัง ฉันป้อนข้อมูลสำหรับคุณเรียบร้อยแล้ว
gowrath

@gowrath ฉันจะเปิดสิ่งนี้ในคอมพิวเตอร์ของฉันในบ่ายวันนี้เราจะเห็นว่าเกิดอะไรขึ้น
ทำให้เสียชีวิต

@ ทำให้ดูเหมือนว่าจะหมดเวลา แต่ฉันอาจจะทำผิด ฉันจะไม่พึ่งพาทักษะการป้อนข้อมูลของฉันอย่างสมบูรณ์เช่น: D
gowrath

@gowrath หมดเวลากับ TIO แต่ฉันจะเรียกใช้มันบนล่ามออฟไลน์โดยตรงบนคอมพิวเตอร์ของฉัน
ลดขนาด

9

Haskell, 242 230 201 199 177 163 160 149 131 ไบต์

import Data.Lists
m=map
a#b=[x|x<-m(chunk$length b).mapM id$[0,1]<$(a>>b),g x==a,g(transpose x)==b]
g=m$list[0]id.m sum.wordsBy(<1)

ในที่สุดต่ำกว่า 200 ไบต์ให้เครดิตกับ @Bergi ต้องขอบคุณ @nimi อย่างมากที่ช่วยลดขนาดลงเกือบครึ่ง

ว้าว. เกือบครึ่งขนาดแล้วส่วนหนึ่งเป็นเพราะฉัน แต่ส่วนใหญ่เป็นเพราะ @nimi

(#)ฟังก์ชั่นวิเศษคือ พบการแก้ปัญหาทั้งหมดของ nonogram ที่กำหนด

นี้สามารถที่จะแก้ปัญหาทุกกรณี O(2^(len a * len b))แต่อาจจะช้าสุดเนื่องจากความซับซ้อนของมันเป็นเรื่องเกี่ยวกับ เกณฑ์มาตรฐานอย่างรวดเร็วเผยให้เห็น 86GB จัดสรรให้สำหรับ nonogram 5x5

ความจริงแล้วสนุก: มันใช้ได้กับทุก nonograms ไม่ใช่แค่รูปสี่เหลี่ยมจัตุรัส


มันทำงานอย่างไร:

  • a#b: รายการที่กำหนดของรายการจำนวนเต็มซึ่งแสดงถึงจำนวนของสี่เหลี่ยมสร้างกริดทั้งหมด ( map(chunk$length b).mapM id$a>>b>>[[0,1]]) และกรองผลลัพธ์เพื่อเก็บเฉพาะรายการที่ถูกต้อง
  • g: เมื่อพิจารณาจาก nonogram ที่เป็นไปได้มันจะรวมการวิ่งของ 1 ในแนวนอน

คุณหมายถึง O (2 ^ (len a * len b)) ไม่ใช่ O ((len a * len b) ^ 2)
Anders Kaseorg

@AndersKaseorg ถูกต้อง เก็บล้านที่ฉันบอกเป็นนัยไว้โดยบังเอิญ : D
ThreeFx

1
อีกสองสามไบต์: m(chunk$l b)และreplicate(l$a>>b)
Bergi

@ThreeFx 86GB: O ... Btw คุณสามารถอธิบายสั้น ๆ ว่าจะรวบรวมได้อย่างไร ฉันเพิ่งเริ่มเรียนรู้ฮาเซลและนี่คือการให้ข้อผิดพลาดกับ ghc ต้องการทดสอบ :)
gowrath

1
import Data.Listsก็พอเพราะมันอีกครั้งการส่งออกทั้งในและData.List Data.List.Split
nimi

4

Pyth, 91 72 71 ไบต์

D:GHdRq@@QdG.nCf.)TrH8V^,01^hQ2=TcNhQ=Y1VhQ=*Y*:H@TH1:H@CTH2)IYjbmjkdTb

โปรแกรมที่จะเข้าของรายการของรูปแบบ[size, [horizontal clues], [vertical clues]]ที่แต่ละเบาะแสเป็นรายการของจำนวนเต็ม (เบาะแสที่ว่างเปล่าเป็นรายการที่ว่างเปล่า[]) และพิมพ์วิธีการแก้ปัญหาทุกบรรทัดใหม่แยกออกจากกันในรูปแบบของตารางไบนารีที่1จะมีการแรเงาและ0เป็นไม่มีเงา .

O(2^n^2)นี่คือพลังของสัตว์เพื่อเป็นประมาณ มันเริ่มใช้เวลานานมากในการไขปริศนาที่มีขนาดใหญ่ขึ้น แต่จะแก้ปัญหาโดยไม่ จำกัด ขนาดใด ๆ ตามเวลาที่กำหนด

ลองออนไลน์

มันทำงานอย่างไร

โปรแกรมสร้างทุกรูปแบบที่เป็นไปได้โดยการใช้ผลิตภัณฑ์ Cartesian ซ้ำของที่มีความยาวเท่ากับ[0, 1] size^2สิ่งนี้จะถูกแยกออกเป็นชิ้น ๆ ให้รายการสำหรับแต่ละเส้นแนวนอน แต่ละบรรทัดมีความยาวของการเข้ารหัสซึ่งถูกกรองด้วยการมีอยู่ของ1และทำให้แบนโดยทิ้งร่องรอยไว้สำหรับบรรทัดนั้น สิ่งนี้จะถูกตรวจสอบกับอินพุต กระบวนการข้างต้นซ้ำสำหรับการขนย้ายชิ้นตรวจสอบเส้นแนวตั้ง หากมีการเข้าชมแต่ละชิ้นจะถูกต่อกันและชิ้นส่วนที่ต่อกันจะเข้าร่วมในการขึ้นบรรทัดใหม่และพิมพ์โดยนัยด้วยการขึ้นบรรทัดใหม่

D:GHdRq@@QdG.nCf.)TrH8V^,01^hQ2=TcNhQ=Y1VhQ=*Y*:H@TH1:H@CTH2)IYjbmjkdTb  Program. Input: Q
                            hQ                                           Q[0], size
                           ^  2                                          Square
                        ,01                                              [0, 1]
                       ^                                                 Cartesian product
                      V                                     )            For N in the Cartesian product:
                                 cNhQ                                    Split N into Q[0] chunks
                               =T                                        Assign that to T
                                     =Y1                                 Y=1
                                        VhQ                              For H in range [0, Q[0]-1]:
D:GHd                                                                     def :(G, H, d)
                   rH8                                                     Run-length-encode(H)
               f.)T                                                        Filter by presence of 1 in character part
            .nC                                                            Transpose and flatten, giving the clue
       @@QdG                                                               Q[d][G], the relevant input clue
     Rq                                                                    Return clue==input clue
                                               :H@TH1                     :(H, T, 1)
                                                     :H@CTH2              :(H, transpose(T), 2)
                                           =*Y*                           Y=Y*product of above two
                                                             IY           If Y:
                                                                 mjkdT     Conacatenate each element of T
                                                               jb          Join on newlines
                                                                      b    Add a newline and implicitly print

ขอบคุณ @ Pietu1998 สำหรับคำแนะนำ


นี่อาจเป็นโปรแกรม Pyth ที่ยาวที่สุดเท่าที่ฉันเคยเห็น
Business Cat

=ZhZเท่ากับ=hZและจะมีค่าเท่ากับFN V
PurkkaKoodari

@TheBikingViking คุณหมายถึงอะไรให้เวลาเพียงพอ? ฉันค่อนข้างแน่ใจว่าสิ่งนี้จะไม่แก้ 25x25 ตอนนี้ถ้าคุณเริ่มต้นจากความคิดของจักรวาล
gowrath

1
@gowrath ฉันค่อนข้างแน่ใจเช่นนั้น! ฉันยังใหม่กับ Pyth และหลังจากนั้นฉันก็ไม่อยากลองใช้อัลกอริธึมที่ดีกว่านี้อีก
TheBikingViking

2

Javascript (ES6), 401 386 333 ไบต์

นี่เป็นความพยายามครั้งแรก มันไม่ได้มีประสิทธิภาพมากนัก แต่ฉันอยากรู้วิธีทดสอบวิธีการแก้ปัญหาโดยใช้นิพจน์ทั่วไปในการแทนค่าไบนารี่ของแถวและคอลัมน์

ตัวอย่างเช่นมันจะแปลคำใบ้[3,1]เป็นนิพจน์ทั่วไปต่อไปนี้:

/^0*1{3}0+1{1}0*$/

ตอนนี้รุ่นนี้ไม่ได้คำนึงถึงร่องรอยสี่เหลี่ยมจัตุรัส ฉันอาจจะเพิ่มสิ่งนี้ในภายหลัง

รหัส

(c,r)=>{W=c.length;w=[];S=0;M=(n,p)=>eval(`/^0*${p.map(v=>`1{${v}}`).join`0+`}0*$/`).exec(n);R=(y,i=0)=>S||(w[y]=r[y][i],y+1<W?R(y+1):c.every((c,y)=>(n=0,w.map((_,x)=>n+=w[W-1-x][y]),M(n,c)))&&(S=w.join`
`),r[y][i+1]&&R(y,i+1));r=r.map(r=>[...Array(1<<W)].map((_,n)=>((1<<30)|n).toString(2).slice(-W)).filter(n=>M(n,r)));return R(0)}

เอาท์พุต

การแก้ปัญหาจะปรากฏในรูปแบบไบนารี เช่น:

00110
01110
11100
11101
00001

ทดสอบ

นี่คือการทดสอบอย่างง่ายในตารางตัวอย่าง

let f =
(c,r)=>{W=c.length;w=[];S=0;M=(n,p)=>eval(`/^0*${p.map(v=>`1{${v}}`).join`0+`}0*$/`).exec(n);R=(y,i=0)=>S||(w[y]=r[y][i],y+1<W?R(y+1):c.every((c,y)=>(n=0,w.map((_,x)=>n+=w[W-1-x][y]),M(n,c)))&&(S=w.join`
`),r[y][i+1]&&R(y,i+1));r=r.map(r=>[...Array(1<<W)].map((_,n)=>((1<<30)|n).toString(2).slice(-W)).filter(n=>M(n,r)));return R(0)}

console.log(f(
  [[2],[3],[4],[2],[2]],
  [[2],[3],[3],[3,1],[1]]
));


ความคิดดี. แม้ว่าเบราว์เซอร์ของฉันจะไขปริศนาคริสต์มาสแล้ว
ติตัส

2

Haskell, 109 ไบต์

คำเตือน: นี้ได้มาจาก@ คำตอบของ ฉันช่วยเขาลงคำตอบ แต่ดูเหมือนว่าเขาจะหมดความสนใจในการปรับปรุงครั้งล่าสุดของฉันดังนั้นฉันจึงโพสต์คำตอบเหล่านั้นเป็นคำตอบใหม่

import Data.List
n=mapM id
a#b=[x|x<-n$(n$" #"<$a)<$b,g x==a,g(transpose x)==b]
g=map$max[0].map length.words

ตัวอย่างการใช้งาน: ->[[2],[3],[3],[3,1],[1]] # [[2],[3],[4],[2],[2]][[" ## "," ### ","### ","### #"," #"]]

กำลังดุร้าย. ลองใช้การรวมกันของและ#แบ่งชิ้น int ของ#นับความยาวและเปรียบเทียบกับการป้อนข้อมูล


1

PHP, 751 833 (720) 753 724 726 710 691 680 682 ไบต์

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

$p=[];foreach($r as$y=>$h){for($d=[2-($n=count($h)+1)+$u=-array_sum($h)+$w=count($r)]+array_fill($i=0,$n,1),$d[$n-1]=0;$i<1;$d[0]+=$u-array_sum($d)){$o=$x=0;foreach($d as$i=>$v)for($x+=$v,$k=$h[$i];$k--;)$o+=1<<$x++;if(($s[$y]|$o)==$o){$p[$y][]=$o;$q[$y]++;}for($i=0;$i<$n-1&$d[$i]==($i?1:0);$i++);if(++$i<$n)for($d[$i]++;$i--;)$d[$i]=1;}}
function s($i,$m){global$c,$w,$p;for(;!$k&&$i[$m]--;$k=$k&$m<$w-1?s($i,$m+1):$k){for($k=1,$x=$w;$k&&$x--;){$h=$c[$x];for($v=$n=$z=$y=0;$k&&$y<=$m;$y++)$n=$n*($f=($p[$y][$i[$y]]>>$x&1)==$v)+$k=$f?:($v=!$v)||$n==$h[$z++];if($k&$v)$k=$n<=$h[$z];}}return$k?is_array($k)?$k:$i:0;}
foreach(s($q,0)as$y=>$o)echo strrev(sprintf("\n%0{$w}b",$p[$y][$o]));
  • คาดว่าคำแนะนำในอาร์เรย์$rสำหรับคำใบ้ของแถวสำหรับคำใบ้$cของคอลัมน์และ$sสำหรับคำใบ้แบบสี่เหลี่ยม
  • พ่นinvalid argument supplied for foreachหากไม่พบวิธีแก้ปัญหา
  • เพื่อให้ได้จำนวนไบต์ที่ถูกต้องให้ใช้ฟิสิคัล\nและลบการขึ้นบรรทัดใหม่อีกสองบรรทัด

ลักษณะ

1) จากคำใบ้แถว
สร้างแถวที่เป็นไปได้ที่เป็นไปตามคำแนะนำของสี่เหลี่ยมจัตุรัส
และจดจำการนับสำหรับดัชนีแต่ละแถว

2) ย้อนกลับข้ามชุดค่าผสมแถว:
หากชุดค่าผสมตรงตามคำแนะนำคอลัมน์ค้นหาลึกหรือกลับชุดค่าผสมที่ประสบความสำเร็จ
ลองอีกวิธีเป็นไปได้สำหรับแถวนี้

3) โซลูชั่นการพิมพ์


การเล่นกอล์ฟครั้งสุดท้ายมีผลกระทบอย่างรุนแรงต่อประสิทธิภาพ;
แต่ฉันลบการมอบหมายการทำโปรไฟล์สำหรับการวัดประสิทธิภาพขั้นสุดท้าย

แทนที่$n=$n*($f=($p[$y][$i[$y]]>>$x&1)==$v)+$k=$f?:($v=!$v)||$n==$h[$z++];
ด้วยif(($p[$y][$i[$y]]>>$x&1)-$v){$k=($v=!$v)||$n==$h[$z++];$n=1;}else$n++;
เพื่อเลิกทำขั้นตอนการเล่นกอล์ฟครั้งสุดท้าย

ตัวอย่าง

สำหรับตัวอย่างเล็ก ๆ ( 17 ถึง 21รอบ12 8 7 6.7 5.3 ms) ให้ใช้

$r=[[2],[3],[3],[3,1],[1]];$c=[[2],[3],[4],[2],[2]];$s=[0,0,0,0,0];

สำหรับปริศนาคริสต์มาส:

  • ฆ่าเซิร์ฟเวอร์บ้านเล็ก ๆ ของฉันด้วยโซลูชันเก่า
  • ฆ่าเบราว์เซอร์ด้วยเอาต์พุตทดสอบ
  • แก้ไขได้แล้วใน50 37.8 45.5ประมาณ 36 วินาที

ใส่ข้อมูลจากคำถามไปยังไฟล์christmas.nonogramและใช้รหัสนี้เพื่อนำเข้า:

$t=r;foreach(file('christmas.nonogram')as$h)if('-'==$h=trim($h))$t=c;elseif('#'==$h){$t=s;$f=count($h).b;}else
{$v=explode(' ',$h);if(s==$t)for($h=$v,$v=0,$b=1;count($h);$b*=2)$v+=$b*array_shift($h);${$t}[]=$v;}

ชำรุด

$p=[];  // must init $p to array or `$p[$y][]=$o;` will fail
foreach($r as$y=>$h)
{
    // walk $d through all combinations of $n=`hint count+1` numbers that sum up to $u=`width-hint sum`
    // (possible `0` hints for $h) - first and last number can be 0, all others are >0
    for(
        $d=[2-
            ($n=count($h)+1)+               // count(0 hint)=count(1 hint)+1
            $u=-array_sum($h)+$w=count($r)  // sum(0 hint) = width-sum(1 hint)
        ]                           // index 0 to max value $u-$n+2
        +array_fill($i=0,$n,1)      // other indexes to 1
        ,$d[$n-1]=0;                // last index to 0
                                    // --> first combination (little endian)
        $i<1;   // $i:0 before loop; -1 after increment; >=$n after the last combination
        $d[0]+=$u-array_sum($d) // (see below)
    )
    {
        // A: create row (binary value) from 1-hints $h and 0-hints $d
        $o=$x=0;
        foreach($d as$i=>$v)
            for($x+=$v,$k=$h[$i];$k--;)
                $o+=1<<$x++;
        // B: if $o satisfies the square hints
        if(($s[$y]|$o)==$o)
        {
            $p[$y][]=$o;    // add to possible combinations
            $q[$y]++;       // increase possibility counter
        }
        // C: increase $d
            // find lowest index with a value>min
                // this loop doesn´t need to go to the last index:
                // if all previous values are min, there is nothing left to increase
        for($i=0;$i<$n-1&$d[$i]==($i?1:0);$i++);
        if(++$i<$n)             // index one up; increase $d if possible
            for($d[$i]++        // increase this value
            ;$i--;)$d[$i]=1;    // reset everything below to 1
            // adjust $d[0] to have the correct sum (loop post condition)
    }
}

// search solution: with backtracking on the row combinations ...
function s($i,$m)
{
    global $c,$w,$p;
    for(;
        !$k // solution not yet found
        &&$i[$m]    // if $i[$m]==0, the previous iteration was the last one on this row: no solution
            --;     // decrease possibility index for row $m
        $k=$k&$m<$w-1? s($i,$m+1) : $k      // if ok, seek deeper while last row not reached ($m<$w-1)
    )
    {
        // test if the field so far satisfies the column hints: loop $x through columns
        for($k=1,$x=$w;$k&&$x--;)   // ok while $k is true
        {
            $h=$c[$x];
            // test column hints on the current combination: loop $y through rows up to $m
            for($v=$n=$z=   // $v=temporary value, $n=temporary hint, $z=hint index
                $y=0;$k&&$y<=$m;$y++)
                // if value has not changed, increase $n. if not, reset $n to 1
                // (or 0 for $k=false; in that case $n is irrelevant)
                $n=$n*  
                    // $f=false (int 0) when value has changed, true (1) if not
                    ($f=($p[$y][$i[$y]]>>$x&1)==$v)
                    +$k=$f?:    // ok if value has NOT changed, else
                        ($v=!$v)        // invert value. ok if value was 0
                        || $n==$h[$z    // value was 1: ok if temp hint equals current sub-hint
                        ++]             // next sub-hint
                ;
            // if there is a possibly incomplete hint ($v==1)
            // the incomplete hint ($n) must be <= the next sub-hint ($c[x][$z])
            // if $n was <$h[$z] in the last row, the previous column hints would not have matched
            if($k&$v)$k=$n<=$h[$z];
        }
        // ok: seek deeper (loop post condition)
        // not ok: try next possibility (loop pre condition)
    }
    return$k?is_array($k)?$k:$i:0;  // return solution if solved, 0 if not
}

// print solution
foreach(s($q,0)as$y=>$o)echo strrev(sprintf("\n%0{$w}b",$p[$y][$o]));

1
ตัวอย่างขนาดใหญ่ฆ่าเซิร์ฟเวอร์ภายในบ้านขนาดเล็กของฉัน (500 - ข้อผิดพลาดเซิร์ฟเวอร์ภายใน) การรวมจะพร้อมหลังจาก 15 วินาที แต่ผลิตภัณฑ์คาร์ทีเซียนมีสมาชิก 1.823E + 61 (แถวที่ 7 และแถวที่ 22 มีทางออกเดียว btw.) อัลกอริทึมต้องได้รับการปรับปรุง
ติตัส

ฉันคิดว่านี่น่าจะดีกว่าถ้าคุณใช้ backtracking ซ้ำ อย่างไรก็ตามมันเยี่ยมมาก!
gowrath

@gowrath: backtracking ให้บิตและประหยัด bytes ... จำนวนเต็มกับ bit arithmetics ให้ความเร็วประมาณ 50% แต่เพิ่มขนาด (ต้องหาว่ามันราคาเท่าไหร่) ... ฉันยังอยู่กับมัน
ติตัส

@gowrath: ฉันไล่ตามข้อบกพร่องของฉัน; มันอยู่ในการเพิ่มขึ้น (ที่อื่น?): $dจะต้องอยู่ในลำดับที่ถูกต้องสำหรับforeach
Titus
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.