Bạn có thể đánh bại tình báo Anh? (Bộ giải Nonogram)


20

Đã đến lúc bắt tay vào một nhiệm vụ nguy hiểm để đánh bại Tình báo Anh. Mục đích của thử thách này là viết mã ngắn nhất sẽ giải được một Nonogram.

Nonogram là gì?

Câu đố Nonogram

Các quy tắc rất đơn giản. Bạn có một lưới các ô vuông, phải được điền vào màu đen hoặc để trống. Bên cạnh mỗi hàng của lưới được liệt kê độ dài của các ô vuông màu đen trên hàng đó. Trên mỗi cột được liệt kê độ dài của các hình vuông màu đen trong cột đó. Mục đích của bạn là tìm tất cả các hình vuông màu đen. Trong loại câu đố này, các con số là một dạng chụp cắt lớp rời rạc để đo xem có bao nhiêu dòng hình vuông điền vào có trong bất kỳ hàng hoặc cột nào. Ví dụ, một đầu mối của "4 8 3" có nghĩa là có các bộ bốn, tám và ba hình vuông đầy, theo thứ tự đó, với ít nhất một hình vuông trống giữa các nhóm liên tiếp. [ 1 ] [ 2 ]

Vì vậy, giải pháp cho Nonogram ở trên sẽ là:

Không giải

Chi tiết thực hiện

Bạn có thể chọn đại diện cho Nonogram theo cách bạn muốn và lấy nó làm đầu vào theo bất kỳ cách nào bạn thấy phù hợp với ngôn ngữ của mình. Đầu ra cũng vậy. Mục đích của thử thách này là hoàn thành công việc theo nghĩa đen; nếu bạn có thể giải quyết biểu đồ không với bất kỳ đầu ra nào mà chương trình của bạn đưa ra, điều đó là hợp lệ. Một lưu ý là bạn không thể sử dụng bộ giải trực tuyến :)

Vấn đề này rất khó khăn về mặt thuật toán (np-perfect) ở chỗ không có giải pháp hoàn toàn hiệu quả cho nó và do đó, bạn sẽ không bị phạt vì không thể giải quyết những vấn đề lớn hơn, mặc dù câu trả lời của bạn sẽ được đền đáp rất nhiều nếu đó là có khả năng xử lý các vụ án lớn (xem phần thưởng). Là một điểm chuẩn, giải pháp của tôi hoạt động lên tới khoảng 25x25 trong vòng 5-10 giây. Để cho phép linh hoạt giữa các ngôn ngữ khác nhau, các giải pháp mất ít hơn 5 phút cho một biểu đồ không có kích thước 25x25 là đủ tốt.

Bạn có thể giả sử một câu đố luôn luôn là một phi hình vuông NxN.

Bạn có thể sử dụng nhà sản xuất câu đố phi hình trực tuyến này để kiểm tra các giải pháp của bạn.

Chấm điểm

Tất nhiên, bạn được tự do sử dụng bất kỳ ngôn ngữ nào bạn muốn và vì đây là môn đánh gôn, các mục sẽ được sắp xếp theo thứ tự: accuracy -> length of code -> speed.Tuy nhiên, đừng nản lòng với các ngôn ngữ chơi gôn, câu trả lời trong tất cả các ngôn ngữ thể hiện nỗ lực chơi gôn một cách thú vị sẽ được nâng cao!

Tiền thưởng

Tôi thực sự đã học về Nonograms từ một tấm thiệp Giáng sinh bằng mật mã do Tình báo Anh phát hành tại đây . Phần đầu tiên về cơ bản là một Nonogram 25x25 đồ sộ. Nếu giải pháp của bạn có thể giải quyết điều này, bạn sẽ nhận được danh tiếng :)

Để làm cho cuộc sống của bạn dễ dàng hơn về mặt nhập dữ liệu, tôi đã cung cấp cách tôi thể hiện dữ liệu cho câu đố cụ thể này để bạn sử dụng miễn phí. 25 dòng đầu tiên là các đầu mối hàng, theo sau là một dòng phân cách '-', theo sau là 25 dòng của các đầu mối col, theo sau là một dòng phân cách '#', và sau đó là một đại diện của lưới với các đầu mối vuông được điền vào.

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

Và đây là một phiên bản hơi khác nhau để thuận tiện cho bạn; một tuple được phân tách bằng dấu phẩy (hàng, col) trong đó mỗi phần tử là danh sách các danh sách.

([[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]])

Đáng buồn là trang web của tôi bị sập nhưng nó đã từng có một trình giải Nonogram khá nhanh; 5-10 phút nghe có vẻ quá mức.
Neil


1
@dwana Bạn không cần phải lo lắng về những trường hợp không thể giải quyết. Đối với câu trả lời ngẫu nhiên, trên một phi hình 25x25, bạn có 2 ^ 625 cấu hình có thể. Trong bối cảnh, số lượng nguyên tử trong vũ trụ đã biết nhiều hơn gấp đôi (tức là nếu bạn sử dụng mỗi nguyên tử trong vũ trụ một chút, bạn vẫn sẽ không có đủ không gian để lưu trữ các khả năng). Về mặt thời gian, nếu bạn mất một giây nano (hào phóng) để kiểm tra tính hợp lệ của từng cấu hình, sẽ mất 7 vòng đời của vũ trụ để mã hoàn thành chạy :)
gowrath

1
Ty để làm rõ các trường hợp không thể giải quyết. (+ tôi có một PC ma thuật xác nhận câu trả lời trong ~ 2.1546362E-186 giây)
dwana

1
CSV của bạn không có gợi ý vuông. Tại đây, một số JS để tạo ra chúng: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;
Titus

Câu trả lời:


5

Brachylog , 70 69 byte

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

Cái này lấy một danh sách gồm hai danh sách (đầu tiên là các chỉ số hàng, sau đó là các cột). Mỗi chỉ báo là một danh sách (đối với các lần ngồi như [3,1]trên một hàng).

Phiên bản này mất khoảng 3 phút để giải quyết 5 trên 5 ví dụ về thử thách.

Phiên bản hiệu quả hơn, 91 byte

[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,

Hãy thử trực tuyến!

Cái này không phải là lực lượng hoàn chỉnh: sự khác biệt duy nhất là cái này áp đặt các ràng buộc đối với các giá trị của các ô sao cho số 1 trong mỗi hàng và cột khớp với các số được đưa ra làm chỉ số trong đầu vào. Phần vũ lực duy nhất sau đó là trong việc tìm kiếm một lưới với các ràng buộc mà "các khối" của 1 khớp với những gì được đưa ra như là dấu hiệu.

Điều này mất khoảng 0,05 giây trên 5 đến 5 ví dụ về thử thách. Điều này vẫn còn quá chậm đối với trường hợp tiền thưởng, vì tôi không biết làm thế nào để thể hiện các khối của các khối được phân tách bằng một hoặc nhiều số 0 theo các ràng buộc.

Giải trình

Tôi sẽ giải thích bên dưới phiên bản 93 byte. Sự khác biệt duy nhất giữa hai là lệnh gọi vị ngữ 3 không tồn tại trong phiên bản 70 byte và đánh số các vị từ (vì có ít hơn một).

  • Vị ngữ chính:

    [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
    
  • Vị ngữ 1: Buộc các hàng có độ dài cụ thể và mỗi ô là 0 hoặc 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)
    
  • Vị ngữ 2: Ràng buộc một biến là 0 hoặc 1

    .<2,      Input = Output < 2
    _1<       Output > -1
    
  • Dự đoán 3: Tổng số 1 trong danh sách phải bằng tổng chỉ số (ví dụ: nếu chỉ số là [3: 1] thì danh sách phải có tổng 4)

    :+a       Sum the elements of the list and sum the indicator
    #=,       Both sums must be equal
    ?h        Output is the list
    
  • Vị ngữ 4: Kiểm tra xem các khối 1 có khớp với chỉ báo không

    @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)
    
  • Vị ngữ 5: Đúng cho các khối 1s, sai khác

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

Cảm thấy như công cụ hoàn hảo cho công việc. Mong được giải thích.
Emigna

@Firthize Điều này thật tuyệt vời, tôi đã chờ đợi ai đó sử dụng ngôn ngữ prolog-esque để làm điều này. Bạn đã thử nó với trường hợp 25x25? Tôi đã nhập dữ liệu cho bạn rồi
gowrath

@gowrath Tôi sẽ chạy cái này trên máy tính của tôi chiều nay, chúng ta sẽ xem điều gì sẽ xảy ra.
Gây tử vong

@Firthize Có vẻ đã hết thời gian nhưng tôi có thể đang làm sai. Tôi cũng sẽ không hoàn toàn dựa vào các kỹ năng nhập dữ liệu của mình: D
gowrath

@gowrath Nó hết thời gian trên TIO, nhưng tôi sẽ chạy nó trên trình thông dịch ngoại tuyến trực tiếp trên máy tính của tôi.
Gây tử vong

9

Haskell, 242 230 201 199 177 163 160 149 131 byte

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)

Cuối cùng dưới 200 byte, ghi có vào @Bergi. Rất cảm ơn @nimi vì đã giúp giảm gần một nửa kích thước.

Ồ Bây giờ gần như một nửa kích thước, một phần là do tôi nhưng chủ yếu là vì @nimi.

Chức năng kỳ diệu là (#). Nó tìm thấy tất cả các giải pháp của một nonogram nhất định.

Điều này có thể giải quyết tất cả các trường hợp, nhưng có thể siêu chậm, vì nó phức tạp O(2^(len a * len b)). Một điểm chuẩn nhanh cho thấy 86GB được phân bổ cho một nonogram 5x5.

Sự thật thú vị: Nó hoạt động cho tất cả các hình không, không chỉ hình vuông.


Làm thế nào nó hoạt động:

  • a#b: Đưa ra danh sách các danh sách số nguyên biểu thị số lượng hình vuông, tạo tất cả các lưới ( map(chunk$length b).mapM id$a>>b>>[[0,1]]) và lọc kết quả để chỉ giữ lại các số nguyên hợp lệ.
  • g: Đưa ra một biểu đồ không tiềm năng, nó tính tổng số lần chạy của 1 theo chiều ngang.

Ý bạn là O (2 ^ (len a * len b)), không phải O ((len a * len b) ^ 2).
Anders Kaseorg

@AndersKaseorg Phải. Giữ một triệu tôi vô tình ngụ ý ở đó. : D
ThreeFx

1
Một vài byte khác: m(chunk$l b)replicate(l$a>>b)
Bergi

@ThreeFx 86GB: O ... Btw bạn có thể giải thích ngắn gọn cách biên dịch cái này không? Tôi chỉ mới bắt đầu học haskell và điều này đang gây ra lỗi với ghc. Muốn thử nghiệm :)
gowrath

1
import Data.Listslà đủ, bởi vì nó tái xuất cả hai Data.ListData.List.Split.
nimi

4

Pyth, 91 72 71 byte

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

Một chương trình lấy đầu vào của danh sách biểu mẫu [size, [horizontal clues], [vertical clues]]trong đó mỗi đầu mối là danh sách các số nguyên (đầu mối trống là danh sách trống []) và in mọi giải pháp, dòng mới được phân tách, dưới dạng lưới nhị phân 1được tô bóng và không 0bị mờ .

Đây là một lực lượng vũ phu, đại khái là như vậy O(2^n^2). Nó bắt đầu mất một thời gian rất dài cho các câu đố lớn hơn, nhưng sẽ giải quyết bất kỳ kích thước nào được cung cấp đủ thời gian.

Dùng thử trực tuyến

Làm thế nào nó hoạt động

Chương trình tạo ra mọi bố cục có thể bằng cách lấy sản phẩm Cartesian lặp đi lặp lại [0, 1]với độ dài bằng size^2. Điều này sau đó được chia thành các khối, đưa ra một danh sách cho mỗi đường ngang. Mỗi dòng được mã hóa theo chiều dài chạy, được lọc bởi sự hiện diện 1và làm phẳng, để lại đầu mối cho dòng đó. Điều này sau đó được kiểm tra đối với đầu vào. Quá trình trên được lặp lại cho chuyển vị của các khối, kiểm tra các đường thẳng đứng. Nếu có một hit, mỗi đoạn được nối và các đoạn được nối được nối trên dòng mới và được in ngầm, với một dòng mới.

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

Cảm ơn @ Pietu1998 cho một số mẹo


Đây có thể là chương trình Pyth dài nhất tôi từng thấy
Business Cat

=ZhZbằng =hZ, và FNbằng V.
PurkkaKoodari

@TheBikingViking Chính xác thì ý bạn là gì khi có đủ thời gian? Tôi khá chắc chắn rằng điều này sẽ không giải quyết được 25x25 nếu bạn đã bắt đầu nó từ quan niệm về vũ trụ.
gowrath

1
@gowrath Tôi cũng khá chắc chắn về điều đó! Tôi chưa quen với Pyth và sau khoảng thời gian này, tôi thậm chí không muốn xem xét việc thực hiện một thuật toán tốt hơn
TheBikingViking

2

Javascript (ES6), 401 386 333 byte

Đây là một nỗ lực sớm. Nó không hiệu quả lắm nhưng tôi tò mò thử nghiệm một giải pháp bằng cách sử dụng các biểu thức chính quy trên biểu diễn nhị phân của các hàng và cột.

Ví dụ, nó sẽ dịch đầu mối [3,1]thành biểu thức chính quy sau:

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

Ngay bây giờ, phiên bản này không tính đến manh mối vuông. Tôi có thể sẽ thêm điều này sau.

(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)}

Đầu ra

Giải pháp được hiển thị ở định dạng nhị phân. Nhu la:

00110
01110
11100
11101
00001

Kiểm tra

Đây là một thử nghiệm đơn giản trên lưới ví dụ.

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]]
));


ý kiến ​​hay. Tuy nhiên, giết chết trình duyệt của tôi trên câu đố Giáng sinh.
Tít

2

Haskell, 109 byte

Tuyên bố miễn trừ trách nhiệm: điều này được bắt nguồn từ câu trả lời của @ ThreeFx . Tôi đã giúp anh ấy đánh golf xuống câu trả lời của anh ấy nhưng anh ấy dường như đã mất hứng thú để đưa vào những cải tiến đáng kể cuối cùng của tôi, vì vậy tôi đăng chúng dưới dạng câu trả lời mới.

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

Ví dụ sử dụng: [[2],[3],[3],[3,1],[1]] # [[2],[3],[4],[2],[2]]-> [[" ## "," ### ","### ","### #"," #"]].

Lực lượng vũ phu. Hãy thử tất cả các kết hợp #, chia int chunk của #, đếm độ dài và so sánh với đầu vào.


1

PHP, 751 833 (720) 753 724 726 710 691 680 682 byte

Tôi đã háo hức xây dựng một trình tự tăng dần chuyên biệt và thử trình tạo cartesian của tôi một lần nữa;
nhưng bỏ rơi cartesian ủng hộ quay lui để giải câu đố lớn nhanh hơn.

$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]));
  • mong đợi gợi ý trong mảng $rcho gợi ý hàng, $ccho gợi ý cột và $scho gợi ý vuông.
  • ném invalid argument supplied for foreachnếu nó không tìm thấy giải pháp.
  • để có được số byte chính xác, hãy sử dụng vật lý \nvà loại bỏ hai ngắt dòng khác.

sự miêu tả

1) từ gợi ý hàng
tạo ra các hàng có thể thỏa mãn gợi ý vuông
và ghi nhớ số lượng của chúng cho mỗi chỉ số hàng.

2) quay lui qua các kết hợp hàng:
Nếu kết hợp thỏa mãn các gợi ý cột, tìm kiếm sâu hơn hoặc trả lại kết hợp thành công,
hãy thử khả năng tiếp theo cho hàng này

3) giải pháp in


Lần đánh golf cuối cùng đã ảnh hưởng nghiêm trọng đến hiệu suất;
nhưng tôi đã loại bỏ các bài tập hồ sơ cho các điểm chuẩn cuối cùng.

Thay thế $n=$n*($f=($p[$y][$i[$y]]>>$x&1)==$v)+$k=$f?:($v=!$v)||$n==$h[$z++];
bằng if(($p[$y][$i[$y]]>>$x&1)-$v){$k=($v=!$v)||$n==$h[$z++];$n=1;}else$n++;
để hoàn tác bước đánh gôn cuối cùng.

ví dụ

Đối với ví dụ nhỏ ( 17 đến 21 khoảng 12 8 7 6,7 5,3 ms), hãy sử dụng

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

cho câu đố giáng sinh:

  • giết máy chủ nhỏ của tôi với giải pháp cũ
  • giết trình duyệt với kết quả kiểm tra
  • hiện đã giải quyết trong 50 37,8 45,5 khoảng 36 giây

đưa dữ liệu từ câu hỏi vào một tệp christmas.nonogramvà sử dụng mã này để nhập:

$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;}

phá 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
Ví dụ lớn giết chết máy chủ gia đình nhỏ của tôi (500 - Lỗi máy chủ nội bộ). Các kết hợp đã sẵn sàng sau 15 giây, nhưng sản phẩm cartesian có 1.823E + 61 thành viên. (Hàng thứ 7 và 22 chỉ có một giải pháp btw.) Thuật toán phải được cải thiện.
Tít

Tôi nghĩ rằng điều này có thể được tăng tốc nếu bạn sử dụng quay lui đệ quy. Tuy nhiên, công việc tuyệt vời!
gowrath

@gowrath: quay lui cung cấp một chút và thậm chí tiết kiệm byte ... số nguyên với bit arithologists cho tốc độ khoảng 50% nhưng tăng kích thước (phải tìm hiểu xem chi phí chính xác là bao nhiêu) ... Tôi vẫn còn trên đó.
Tít

@gowrath: Tôi đuổi con bọ của tôi xuống; nó đã tăng dần (ở đâu khác?): $dphải theo đúng thứ tự choforeach
Tít
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.