Bộ giải câu đố nhị phân


10

Giới thiệu

Quy tắc của câu đố:

Câu đố nhị phân (còn được gọi là Takuzu hoặc Subiku) rất đơn giản để hiểu và chỉ có một vài quy tắc:
Vì tên của trò chơi là nhị phân nên khá rõ ràng, nhưng bạn chỉ có thể điền vào số không và số không.

  1. Không quá hai chữ số giống nhau có thể nằm cạnh nhau theo chiều dọc hoặc chiều ngang với nhau
  2. Mỗi hàng và mỗi cột phải chứa một số không và số bằng nhau (điều này có nghĩa là mọi trò chơi nhị phân sẽ luôn có các số chẵn).
  3. Có thể không có hàng trùng lặp và không có cột trùng lặp (với thứ tự chính xác của số không và số không).

Bạn có thể chơi trò chơi tại www.binarypuheads.com nếu bạn muốn.

Chiến thuật:

Do quy tắc 1, chúng ta luôn có thể điền một chữ số nếu:
- Đã có hai chữ số giống nhau theo chiều dọc hoặc chiều ngang với nhau, trong trường hợp đó chúng ta có thể điền chữ số ngược lại ở cả hai bên. Tức là .11...0110...
- Có hai chữ số giống nhau theo chiều dọc hoặc chiều ngang chỉ có một khoảng cách ở giữa chúng. Tức là .1.1...101..

Do quy tắc 1, khi ba khoảng trống còn lại và chúng ta không thể có ba khoảng liền kề của cùng một chữ số, chúng ta có thể điền vào một trong các khoảng trống. Tức là .0.1.010.1.0(Chúng ta vẫn phải điền vào hai cái và chúng ta không thể có ba cái liền kề ở giữa, vì vậy khoảng cách đầu tiên phải là a 1.)

Do quy tắc 2, chúng ta luôn có thể điền vào các khoảng trống còn lại trong một hàng hoặc cột nếu một nửa trong số chúng đã được điền bằng chữ số ngược lại. Tức là .1.011010011

Do quy tắc 3, chúng ta luôn có thể điền các chữ số ngược nhau nếu chỉ còn hai chữ số để giải trên một dòng có thứ tự như nhau. Tức là 101100 & 1..100101100 & 110100

Do quy tắc 3, đôi khi chúng ta có thể điền vào một khoảng trống khi ba khoảng trống còn lại trên một dòng có thứ tự như nhau. Tức là 010011 & .1.01.010011 & .1.010(Ở đây chúng ta không thể điền vào 1cuối, bởi vì điều đó có nghĩa là chúng ta phải điền vào các số không ở hai khoảng trống khác, làm cho cả hai dòng bằng nhau theo thứ tự.)

Thí dụ:

Chúng tôi bắt đầu với lưới 6x6 sau đây với một số số và số không được điền vào (và các dấu chấm là những khoảng trống chúng tôi chưa điền vào):

.1....
.10.0.
1.11..
.1....
...1.0
......

Do quy tắc 1 & 2, chúng tôi có thể điền vào các chữ số này:

.1.01.
.1010.
101100
010011
.0.1.0
.010..

Do quy tắc 1, chúng tôi có thể điền vào 1 ở hàng 5, cột 1:

.1.01.
.1010.
101100
010011
10.1.0
.010..

Do quy tắc 3, chúng tôi có thể điền 0 vào hàng 1, cột 6 (khi nhìn vào hàng 4):

.1.010
.1010.
101100
010011
10.1.0
.010..

Bây giờ chúng ta có thể tiếp tục lấp đầy các khoảng trống bằng các chữ số do quy tắc 1 & 2:

.1.010
010101
101100
010011
10.1.0
.010.1

Bây giờ chúng ta có thể kết thúc hàng 5 do quy tắc 3 (khi nhìn vào hàng 3):

.1.010
010101
101100
010011
100110
.010.1

Và sau đó chúng ta có thể hoàn thành câu đố do quy tắc 1 & 2:

011010
010101
101100
010011
100110
101001

Thử thách:

Thách thức chỉ đơn giản là: đưa ra lưới bắt đầu, đưa ra câu đố đã giải.

LƯU Ý: Bạn không phải thực hiện các quy tắc trên. Tất nhiên là bạn có thể, và nó sẽ cho bạn gợi ý về cách thực hiện thử thách này, nhưng việc củng cố giải pháp với các quy tắc trong tâm trí là hoàn toàn tốt.
Làm thế nào bạn giải quyết nó là tùy thuộc vào bạn, nhưng thách thức là đưa ra câu đố đã giải.

Quy tắc thử thách:

  • Định dạng đầu vào và đầu ra cho lưới là linh hoạt, nhưng vui lòng cho biết những gì bạn sử dụng. (Tức là mảng byte 2D; Chuỗi có dòng mới; v.v.)
  • Điều này ở trên cũng áp dụng cho các ký tự được sử dụng. Trong ví dụ tôi đã sử dụng 01., nhưng nếu bạn muốn, bạn có thể sử dụng ABxthay thế. Vui lòng cho biết định dạng đầu vào / đầu ra và ký tự bạn đã sử dụng.
  • Bạn chỉ có thể giả sử các kích thước lưới sau sẽ được sử dụng : 6x6; 8x8; 10x10; 12x12; 14x14; 16x16.

Quy tắc chung:

  • Đây là , vì vậy câu trả lời ngắn nhất bằng byte thắng.
    Đừng để ngôn ngữ mã-golf ngăn cản bạn đăng câu trả lời với các ngôn ngữ không mã hóa. Cố gắng đưa ra một câu trả lời càng ngắn càng tốt cho ngôn ngữ lập trình 'bất kỳ'.
  • Các quy tắc chuẩn áp dụng cho câu trả lời của bạn, vì vậy bạn được phép sử dụng STDIN / STDOUT, các hàm / phương thức với các tham số thích hợp, các chương trình đầy đủ. Cuộc gọi của bạn.
  • Lỗ hổng mặc định bị cấm.
  • Nếu có thể, vui lòng thêm một liên kết với một bài kiểm tra cho mã của bạn.
  • Ngoài ra, xin vui lòng thêm một lời giải thích nếu cần thiết.

Các trường hợp thử nghiệm:

Các dấu chấm chỉ được thêm vào để dễ đọc, thay vào đó hãy sử dụng khoảng trắng hoặc bất cứ thứ gì bạn thích cho các khoảng trống. Cả định dạng trong và đầu ra đều linh hoạt.

Input:
1..0..
..00.1
.00..1
......
00.1..
.1..00

Output:
101010
010011
100101
011010
001101
110100

Input:
.1....
.10.0.
1.11..
.1....
...1.0
......

Output:
011010
010101
101100
010011
100110
101001

Input:
.......1..
.00..0..1.
.0..1..0.0
..1...1...
1.1......1
.......1..
.0..1...0.
....11...0
.0.0..1..0
0...0...1.

Output:
0110010101
1001100110
1001101010
0110011001
1010100101
0101010110
1001101001
0110110100
1010011010
0101001011


Câu trả lời:


4

Brachylog , 34 byte

{ℕ<2}ᵐ²&≜{d?ọᵐctᵐ=&{ḅlᵐ⌉<3}ᵐ}&\↰₂&

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

Điều này khá chậm, vì vậy trường hợp thử nghiệm trên TIO là 4 x 4. Tôi hiện đang chạy thử nghiệm 6x6 trên máy tính của mình để xem nó mất bao nhiêu thời gian.

Điều này có một danh sách các danh sách như là đầu vào. Các giá trị không xác định phải được chỉ định bằng các biến, đó là với các chuỗi chữ hoa (và tất cả chúng phải khác nhau, vì nếu không bạn sẽ chỉ ra rằng một số ô phải có cùng giá trị)

Giải trình

Chúng tôi giới hạn các giá trị được đặt vào {0,1}, sau đó chúng tôi thử khởi tạo các biến cho đến khi một giá trị tuân thủ cả 3 quy tắc. Đây là lý do tại sao điều này rất chậm (vì nó sẽ thử tất cả chúng cho đến khi tìm thấy một cái và vì trong trường hợp đó, Brachylog không được triển khai đủ tốt để có thể áp đặt các ràng buộc trước khi thử một ma trận có thể).

                                 &  Output = Input
{   }ᵐ²                             Map two levels on the Input (i.e. each cell):
 ℕ<2                                  The cell is either 0 or 1
       &≜                           Assign values to all cells
         {                  }       Define predicate 2:
          d?                          The Input with no duplicates is still the Input
                                        (i.e. all rows are different)
           ?ọᵐctᵐ=                    All occurences of 1s and 0s for each rows are equal
                  &{      }ᵐ          Map on rows:
                    ḅlᵐ                 Get the lengths of runs of equal values
                       ⌉<3              The largest one is strictly less than 3
                             &\↰₂   Apply predicate 2 on the transpose of the Input
                                      (i.e. do the same checks but on columns)

Vì tò mò, làm thế nào để Brachylog chỉ ra các biến ngoài bảng chữ cái viết hoa? Vì vậy, giả sử giải pháp của bạn sẽ hoạt động nhanh hơn, nó sẽ không thể điền vào tất cả các khoảng trống trên lưới 14x14 với Athông qua Y(với Ztham số đầu ra). Liệu nó tiếp tục với AA, AB, vv?
Kevin Cruijssen

2
@KevinCruijssen Bất kỳ định danh chữ hoa nào cũng là một biến, vì vậy, có AAlà một biến và KEVINCRUIJSSENcũng là một biến.
Gây tử vong vào

3
Như tôi nghi ngờ, một thử thách dành cho Brachylog: D
Jonathan Allan

3

JavaScript (ES6), 274 270 byte

Đưa đầu vào dưới dạng mảng 2D, trong đó các ô trống được đánh dấu 2. In tất cả các giải pháp có thể vào bàn điều khiển.

f=(a,x=0,y=0,w=a.length,p,R=a[y])=>(M=z=>!a.some((r,y)=>/(0|1),\1,\1/.exec(s=r.map((v,x)=>(v=z?v:a[x][y],b-=v&1,c-=!v,m|=v&2,v),b=c=w/2))||b*c<0|o[b*c||s]&(o[s]=1),o={}))(m=0)&M(1)&&(m?R&&[0,1].map(n=>(p=R[x])==n|p>1&&(R[x]=n,f(a,z=(x+1)%w,y+!z),R[x]=p)):console.log(a))

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

Phần đầu tiên của mã sử dụng M()chức năng để kiểm tra tính hợp lệ của bảng hiện tại, cả theo chiều ngang và chiều dọc.

M = z =>
  !a.some((r, y) =>
    /(0|1),\1,\1/.exec(
      s = r.map((v, x) =>
        (
          v = z ? v : a[x][y],
          b -= v & 1,
          c -= !v,
          m |= v & 2,
          v
        ),
        b = c = w / 2
      )
    ) ||
    b * c < 0 |
    o[b * c || s] &
    (o[s] = 1),
    o = {}
  )

Nó ánh xạ một hàng hoặc cột đầy đủ đến chuỗi s . Đây thực sự là một mảng bị ép buộc thành một chuỗi, vì vậy nó trông như thế "1,2,2,0,2,2".

Nó sử dụng:

  • Biểu thức chính quy /(0|1),\1,\1/để phát hiện 3 hoặc nhiều chữ số giống nhau liên tiếp.
  • Các quầy bc để theo dõi số lượng ngườisố không . Cả hai quầy được khởi tạo w / 2 và giảm đi mỗi lần một hoặc một zero (tương ứng) bắt gặp. Điều này dẫn đến một trong hai:
    • b = c = 0 b * c = 0 → dòng là đầy đủ và chính xác (như nhiều số không như những người )
    • b> 0 VÀ c> 0 b * c> 0 → dòng chưa hoàn thành nhưng chính xác cho đến nay (chúng tôi không có nhiều hơn w / 2 số không hoặc nhiều hơn w / 2 số )
    • b <0 HOẶC c <0 b * c <0 → dòng không hợp lệ
  • Cờ m (cho 'mất tích') khác không nếu có ít nhất hai cái còn lại trên bảng.
  • Đối tượng o để theo dõi tất cả các mẫu đường gặp phải cho đến nay.

Nếu bảng không hợp lệ, chúng tôi dừng lại ngay lập tức. Nếu bảng hợp lệ và đầy đủ, chúng tôi in nó ra bàn điều khiển. Nếu không, phần thứ hai của những nỗ lực mã để thay thế mỗi 2 với hoặc là một zero hoặc một một với các cuộc gọi đệ quy:

[0, 1].map(n =>
  (p = a[y][x]) == n |
  p > 1 && (
    a[y][x] = n,
    f(a, z = (x + 1) % w, y + !z),
    a[y][x] = p
  )
)

Bản giới thiệu


Cảm ơn đã thêm lời giải thích. Và tôi thích cách bạn in tất cả các đầu ra có thể, thay vì chỉ một!
Kevin Cruijssen

1
@KevinCruijssen Điều này có lẽ không phải là tối ưu nhưng rất thú vị để viết. Thử thách tốt đẹp!
Arnauld

1

Thạch , 53 51 byte

ṡ€3ḄFf0,7L
SḤnLṀȯÇ
⁻QȯÇ
Fṣ©2L’0,1ṗż@€®F€s€LÇÐḟZÇ$Ðḟ

Mất một danh sách liệt kê đại diện cho lưới điện, có chứa 0, 12(không gian). Trả về một danh sách các danh sách các danh sách, mỗi danh sách các danh sách có cùng định dạng (mặc dù không có 2s) và thể hiện một giải pháp khả thi cho đầu vào.

Hãy thử trực tuyến! (điều này sẽ không chạy bất kỳ trường hợp kiểm tra nào của câu hỏi do giới hạn bộ nhớ - tất cả cáclưới2 nSpaces được tạo như một danh sách danh sách các số nguyên - nhưng tôi đã đặt một trường hợp tương đối nặng ở đó với một giải pháp duy nhất). Phần chân trang tách ra và định dạng các lưới.

Phương pháp vũ lực thuần túy - thực hiện các quy tắc và kiểm tra chúng cho từng lưới có thể được hình thành bằng cách thay thế bất kỳ 2s nào bằng 1s hoặc 0s.

ṡ€3ḄFf0,7L - Link 1, # of runs of 3 1s or 3 0s by row: list of lists
ṡ€3        - all contiguous slices of length 3 for €ach list
   Ḅ       - convert all results from binary
    F      - flatten into one list
     f     - filter keep values in:
      0,7  -   0 paired with 7: [0,7]
         L - length

SḤnLṀȯÇ - Link 2, unequal counts of 1s and 0s by column ...or link 1: list of lists
S       - sum (vectorises, hence "by column", counts 1s since only 1s or 0s appear)
 Ḥ      - double
   L    - length (number of rows - OK since square)
  n     - not equal? (vectorises)
    Ṁ   - maximum (1 if any not equal)
     ȯÇ - ... or last link (1) as a monad

⁻QȯÇ - Link 3, rows are unique ...or link 2: list of lists
 Q   - unique
⁻    - not equal?
  ȯÇ - ... or last link (2) as a monad

Fṣ©2L’0,1ṗż@€®F€s€LÇÐḟZÇ$Ðḟ - Main link: list of lists
F                           - flatten
 ṣ©2                        - split at 2s and copy the result to the register
    L                       - length (# of such slices)
     ’                      - decrement (# of 2s)
      0,1                   - 0 paired with 1
         ṗ                  - Cartesian power (all binary lists of length # of 2s)
             ®              - recall value from register (the flat version split at 2s)
          ż@€               - zip (reversed @rguments) for €ach (1s & 0s where 2s were)
              F€            - flatten €ach
                s€L         - split €ach into chunks of length length(input) (into rows)
                    Ðḟ      - filter discard if:
                   Ç        -   call last link(3) as a monad
                         Ðḟ - filter discard if:
                        $   -   last two links as a monad:
                      Z     -     transpose
                       Ç    -     call last link(3) as a monad
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.