Tôi có thể trượt ngoài câu đố không?


38

Viết chương trình hoặc hàm lấy trong một lưới văn bản hình chữ nhật trong đó mỗi ô là một Ahoặc a B. Tất cả các Aô sẽ tạo thành một hình dạng được kết nối đơn giản , tức là tất cả chúng sẽ được kết nối trực giao không có lỗ (các chữ cái lân cận theo đường chéo không được tính là được kết nối). Tương tự như vậy, tất cả các Bô sẽ tạo thành một hình dạng được kết nối đơn giản khác. Lưới sẽ luôn chứa ít nhất một Avà ít nhất một B.

Hãy tưởng tượng lưới thực sự là hai mảnh nhựa mỏng hình khối, được biểu thị bằng ABcác phần. Nếu nó được đặt phẳng trên bàn, hai mảnh có thể trượt ra ngoài trong khi giữ cả hai mặt phẳng hoàn toàn trên bàn không?

In hoặc trả lại một truthy giá trị nếu hai ABhình dạng có thể được tách ra như thế này bằng cách đơn giản kéo chúng ra xa nhau. Nếu không, hãy in hoặc trả lại một falsy giá trị.

Ví dụ: đầu vào

AAA
ABB
AAA

là sự thật bởi vì BBphần có thể được trượt sang bên phải, tách nó ra khỏi A:

AAA
A    BB
AAA

Tuy nhiên, đầu vào

AAAA
ABBA
ABAA

là sai lầm vì không có cách nào để trượt ABcác phần tách rời nhau mà không có chúng chồng lên nhau.

Mã ngắn nhất tính bằng byte thắng. Nếu muốn, bạn có thể sử dụng bất kỳ hai ký tự ASCII có thể in được thay thế AB.

Ví dụ thật (cách nhau bởi các dòng trống)

BBB
BAA
BBB

BA

A
B

AB
AB

AAA
BBB

AAAAB
ABBBB

ABBA
ABBA
AAAA

AAAAAABBBBBBBBB
AABBBBBBBBBBBBB
AAAAAAAAAABBBBB
AABBBBBBBBBBBBB
AAAAAAAAAAAAAAB

AAAAAAAAAAAA
ABABABABABAB
BBBBBBBBBBBB

BAAAAABB
BBAAABBB
BBBABBBB
BBBABBBB
BBBABBBB
BBBBBBBB
BBBBBBBB

AAA
BAA
AAA

Ví dụ giả

BBBB
BAAB
BABB

BBBB
BAAB
AABB

BBBBBBB
BBBBBAB
AAAAAAB
BBBBBBB

BAAA
BABA
BBBA
AABA
AAAA

AAAAAAA
ABBBBBA
AAAAABA
BBBBBBA

BAAAAABB
BBAAABBB
BBBABBBB
BBBABBBB
BBBAABBB
BBBBBBBB
BBBBBBBB

AAA
ABA
BBA
ABA
AAA

Câu trả lời:


9

Ốc, 14

o(t\B+~)+!(t\B

Nếu câu đố có thể được trượt ra, nó sẽ in ra khu vực đầu vào. Nếu không, nó in 0.

Nó hơi chậm đối với các ví dụ lớn hơn, vì nó cần thời gian trong khu vực của lưới điện.

         ,, the program will print the number of starting cells matching this pattern
o        ,, pick a cardinal direction
(
    t    ,, teleport to any cell on the grid
    \B+  ,, match "B" 1 or more times, moving in the direction set by 'o'.
         ,, when a cell is matched, it gets slimed and can't be matched again.
    ~    ,, match an out-of-bounds cell
)+       ,, do parenthesized instructions 1 or more times
!(       ,, the following must not match:
    t\B  ,, teleport to some cell and match 'B'

4
"Hơi chậm một chút .." . Không chắc chắn những gì bạn mong đợi từ một ngôn ngữ có tên là Ốc sên ...
Bassdrop Cumberwubwubwub

4
@Bas Bây giờ, không có lý do để xát muối vào vết thương.
Trasiva

21

CJam, 33 32 20 19 17 byte

Phiên bản sửa đổi, với sự hỗ trợ lớn từ @ Sp3000 và @ MartinBüttner:

qN/_z]{:e`z,3<}/|

Dùng thử trực tuyến

Đóng góp

  • @ Sp3000 đề xuất đơn giản hóa quan trọng cho thuật toán ban đầu của tôi.
  • @ MartinBüttner đã áp dụng các kỹ năng chơi golf điên rồ của mình vào cách tiếp cận sửa đổi, điều này gần như chắc chắn dẫn đến mã ngắn hơn tôi sẽ nghĩ ra ngay cả sau khi xem xét đơn giản hóa.

Thuật toán và bằng chứng

Sau đây giải thích các tiêu chí cho câu đố trượt theo chiều ngang. Trường hợp dọc có thể được xác định bằng cách nhìn vào các cột thay vì các hàng hoặc hoán vị ma trận ký tự và nhìn lại các hàng.

Tôi sẽ sử dụng thuật ngữ "kéo dài" cho một chuỗi tối đa của cùng một chữ cái. Ví dụ: các hàng sau có lần lượt 1, 2 và 3:

AAAAAAAA
BBBAAAAA
AABBBAAA

Tôi cũng sẽ sử dụng thuật ngữ "lồng vào nhau" cho một hàng / câu đố không thể trượt ra.

Quan sát chính là câu đố có thể trượt ra khi và chỉ khi tất cả các hàng có tối đa 2 lần kéo dài . Hoặc đảo ngược, nó được lồng vào nhau khi và chỉ khi có bất kỳ hàng nào có nhiều hơn 2 đoạn .

Những điều sau đây có thể không đủ điều kiện là một bằng chứng toán học nghiêm ngặt, nhưng tôi tin rằng nó đưa ra một lời giải thích thuyết phục tại sao điều này phải là trường hợp.

Dễ dàng thấy rằng câu đố được lồng vào nhau nếu nó có các hàng dài hơn 2 đoạn. Nhìn vào một hàng với 3 trải dài:

BBBAAB

rõ ràng là nó ngăn chặn câu đố trượt ra ngoài vì sự Akéo dài bị khóa giữa các Bđoạn. Điều này có nghĩa là hàng được lồng vào nhau, từ đó làm cho toàn bộ câu đố được lồng vào nhau.

Hướng ngược lại của bằng chứng không hoàn toàn rõ ràng. Chúng ta cần chỉ ra rằng không có câu đố lồng vào nhau mà tất cả các hàng chỉ có 1 hoặc 2 đoạn. Bắt đầu với một vài quan sát:

  • Các hàng chỉ có 1 độ căng không góp phần làm cho câu đố được lồng vào nhau, vì chúng có thể trượt theo hai hướng mà không có bất kỳ va chạm nào.
  • Nếu tất cả các hàng có 2 đoạn có cùng thứ tự AB, câu đố rõ ràng không được lồng vào nhau. Trong trường hợp này, tất cả các Aô còn lại của tất cả các Bô hoặc ngược lại và không có va chạm khi trượt hai mảnh cách nhau.

Trường hợp khó khăn duy nhất sẽ là các câu đố trong đó chúng ta có các hàng với 2 đoạn theo thứ tự khác nhau. Tôi sẽ chỉ ra rằng những câu đố như vậy không tồn tại theo các thông số kỹ thuật nhất định. Để hiển thị điều này, chúng ta hãy nhìn vào một câu đố một phần có cấu hình này, trong đó .có các ký tự đại diện:

.......
AAABBBB
.......
BBAAAAA
.......

Bây giờ, đặc tả nói rằng cả hai ABcác ô được kết nối đơn giản trong tất cả các câu đố hợp lệ. Để làm cho các Aô được kết nối trong câu đố một phần ở trên, chúng tôi có hai tùy chọn:

  1. Chúng tôi vòng quanh một trong những đoạn của B, ví dụ:

    ..AAAAAA
    AAABBBBA
    .......A
    BBAAAAAA
    ........
    

    Để làm điều này, chúng tôi không thể tránh khỏi việc mở rộng một trong các hàng để có 3 lần kéo dài, vì vậy điều này sẽ không bao giờ cho chúng ta một câu đố hợp lệ trong đó tất cả các hàng có tối đa 2 lần.

  2. Chúng tôi kết nối chúng trên một con đường trực tiếp:

    .......
    AAABBBB
    ..A....
    BBAAAAA
    .......
    

    Các Aô hiện được kết nối đơn giản và vẫn không có hàng nào có nhiều hơn 2 đoạn. Tuy nhiên, các Btế bào cũng cần được kết nối đơn giản. Đường dẫn trực tiếp hiện bị chặn bởi các Aô được kết nối và cách duy nhất để kết nối các Bô là vòng quanh một trong các Aô của các ô. Điều này dẫn trở lại trường hợp 1, trong đó chúng ta không thể làm điều đó mà không tạo ra các hàng gồm 3 đoạn.

Để đếm các đoạn đường, việc triển khai sử dụng toán tử CJam RLE.

Giải thích về Mã

qN/     Get input and split at newlines.
_z      Make a transposed copy.
]       Wrap the original and transposed puzzle in an array so that we can
        loop over the two.
{       Start of loop over original and transposed puzzle.
  :e`     Apply RLE to all rows.
  z,      Transpose the matrix with the RLE rows, and take the element count of the
          result. Or in other words, take the column count. This will be the length
          of the longest row after RLE.
  3<      Check the length for less than 3.
}/      End of loop over original and transposed puzzle.
|       Or the results of the two.

9

JavaScript (ES6), 108 107 98 91 82 byte

a=>!(T=[],R=/AB+A|BA+B/).test([...a].map((c,i)=>T[i%-~a.search`
`]+=c))|!R.test(a)

Bản demo trực tiếp . Đã thử nghiệm trên Firefox. Đưa đầu vào dưới dạng một chuỗi phân cách dòng mới.

Chỉnh sửa:

  • Đã lưu 1 byte bằng cách thay đổi \nthành một dòng mới.
  • Đã lưu 9 byte bằng cách thực hiện kiểm tra RegExp trực tiếp trên chuỗi nhiều dòng thay vì chuyển đổi thành một mảng.
  • Loại bỏ 9 byte khác bằng cách sử dụng mảng hiểu để phân tách chuỗi, di chuyển! vào ghàm và gọi RegExp trực tiếp trên mảng thay vì sử dụng find.
  • Tiếp tục chuỗi số học bằng cách lưu thêm 9 byte. Đã thực hiện một mô-đun trên chỉ mục thay vì chia mảng theo dòng mới trước khi thực hiện chuyển đổi.

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

Phiên bản trước:

a=>(T=[],a.split`
`.map(s=>s.split``.map((c,i)=>T[i]+=c)),!T.find(g=s=>/AB+A|BA+B/.test(s)))|!g(a)
  1. Lấy đầu vào avà chia nó theo dòng mới thành một chuỗi các chuỗi.
  2. Chuyển avà lưu trữ nó trong T. Sử dụng mapđể lặp lại qua từng phần tử của a, chia chuỗi thành một mảng ký tự và sử dụng maplại để nối thêm iký tự thứ trong dòng vào idòng thứ của T. Vì mỗi yếu tố của Tchưa được khởi tạo, cuối cùng nó sẽ trông giống như vậy "undefinedAAABBA", nhưng điều này sẽ không thành vấn đề.
  3. Tạo chức năng kiểm tra dựa trên RegExp gphù hợp với mẫu /AB+A|BA+B/. Nếu khớp, các mảnh được khóa theo hướng đã cho bởi vì sau đó có một bộ Bs được kẹp giữa hai hoặc nhiều As hoặc ngược lại.
  4. Sử dụng chức năng gkiểm tra để kiểm tra tất cả các yếu tố của khối avà chuyển vị của nó Tcho một trận đấu bằng cách sử dụng find. Nếu cả hai khớp nhau, thì các mảnh được khóa theo cả hai hướng, do đó, tạo ra một giá trị giả, nếu không thì là một giá trị trung thực.

5

Javascript (ES6), 118

slidey=
// code
a=>!a.match(R=/AB+A|BA+B/)||!(a=a.split`
`.map(b=>b.split``))[0].map((_,c)=>a.map(d=>d[c])).some(e=>e.join``.match(R))

// IO
var S =document.getElementById('S');
S.onkeyup = _=> document.getElementById('P').innerText = slidey(S.value);

document.getElementById('P').innerText = slidey(S.value);
<textarea id='S'>BAAAAABB
BBAAABBB
BBBABBBB
BBBABBBB
BBBABBBB
BBBBBBBB
BBBBBBBB</textarea>
<p id='P'></p>

Giải trình:

a=> !/* check string horizontally */ || !/* check string vertically by transposing it and
                                            running the same horizontal check */

a=> !a.match(R=/AB+A|BA+B/) || !/* ... */
// check for lines containing something like BAAAAAB or ABBBBBBBA
// this is the only way something can get blocked horizontally
// eg AAAAAAA
//    AAABAAA <<< note the B in the middle of As here
//    AAABBBB <<< blocked from being pulled out horizontally
//    AAAAAAA

a=> /* ... */ ||!( a = a.split('\n').map(b=> b.split('')) ) // split a into 2D array
    [0].map((_,c)=>a.map(d=>d[c])) // transpose it
    .some(e=>e.join``.match(R)) // run the check again using `some` to go line by line
                                // which is shorter than .join().match() outside

a=> !/* returns null if no horizontal obstacles and an array if there are */
    || !/* same thing */
// negate both to cast to a boolean (false if obstacles, true if not)
// an input can only be unslidable if both directions are blocked
// so (no obstacles vertically? || no obstacles horizontally?) gives the answer

Chuột! Đánh tôi với nó
intrepidcoder

5

JavaScript (ES6) 72 74

Chỉnh sửa 2 byte đã lưu thx @NotthatCharles

Tôi có một sự hiểu biết trực quan rằng nếu một mảnh có thể trượt chỉ một phần của bước, thì nó miễn phí. Các trường hợp thử nghiệm hiện tại xác nhận điều này.

Vì vậy, tôi kiểm tra chỉ một bước trong mỗi hướng.

Các ký tự được sử dụng: 1 và 0
2 byte nữa để sử dụng bất kỳ 2 ký tự có thể in như A và B

Kiểm tra chạy đoạn mã dưới đây trong trình duyệt tuân thủ EcmaScript 6 (hỗ trợ toán tử trải rộng - IE Firefox)

f=s=>[w=~s.search`
`,-w,-1,1].some(o=>![...s].some((x,p)=>x+s[p+o]==10))

// 4 bytes more- for any symbol, not just 1 and 0 (for instance A and B):
g=s=>[w=~s.search`
`,-w,-1,1].some(o=>![...s].some((x,p)=>x+s[p+o]=='AB'))

//TEST
console.log=x=>O.innerHTML+=x+'\n'

testOk = [
 '111\n100\n111',
 '10',
 '0\n1',
 '01\n01',
 '000\n111',
 '00001\n01111',
 '0110\n0110\n0000',
 '000000111111111\n001111111111111\n000000000011111\n001111111111111\n000000000000001',
 '000000000000\n010101010101\n111111111111',
 '10000011\n11000111\n11101111\n11101111\n11101111\n11111111\n11111111',
 '000\n100\n000'
]

testKo = [
 '1111\n1001\n1011',
 '1111\n1001\n0011',
 '1111111\n1111101\n0000001\n1111111',
 '1000\n1010\n1110\n0010\n0000',
 '0000000\n0111110\n0000010\n1111110',
 '10000011\n11000111\n11101111\n11101111\n11100111\n11111111\n11111111',
 '000\n010\n110\n010\n000'
]

console.log('Expecting true')
testOk.forEach(t=>console.log(t+'\n'+f(t)+'\n'))
console.log('Expecting false')
testKo.forEach(t=>console.log(t+'\n'+f(t)+'\n'))
<pre id=O></pre>


Chà, đó chỉ là thiên tài. Đánh bại một lần nữa bởi một pro. :-)
Sản phẩm ETH

s[p+o]=='0'có vẻ hơi dài Nó có thể được thay thế bằng 1-s[p+o], hoặc ít nhất s[p+o]==0?
Sản xuất ETH

@ETHproductions vâng, nó dài, đáng để suy nghĩ thêm. Nó phải cung cấp sai cho '\ n' (viền dọc, chuyển thành 0) và không xác định (viền trên và dưới, chuyển đổi thành NaN)
edc65

=='A'có thể được thay thế bởi <'B'. Tương tự cho=='B'
Không phải Charles

Ngoài ra, bạn không thể làm gì x+s[p+o]=='AB'?
Không phải Charles

3

Toán học 100 69 byte

Với 31 byte khổng lồ được lưu, nhờ @Martin Buttner,

g=Max[Length/@Split/@#]<3&;g[c=Characters@StringSplit@#]||g@Thread@c&

Định dạng đầu vào dưới dạng ma trận các ký tự; nó cũng tạo ra một chuyển vị của ma trận. Nếu ma trận hoặc chuyển vị của nó không có nhiều hơn 2 lần chạy mỗi hàng thì câu đố có thể trượt.

{a,a,b,b,b} có 2 lượt chữ.

{a,a,b,a,a} có 3 dòng chữ.

{a,a,b,a,a,a,b,b,b,b,b,b,b,b} có 4 chữ cái.


2

APL Dyalog, 22 byte

(∨/{∧/2>+/2≠/⍵}¨)⊂∘⍉,⊂

Hãy thử nó ở đây. Đây là một hàm lấy một mảng các ký tự 2D và trả về 1cho các trường hợp trượt và 0cho các trường hợp không trượt. Thuật toán tương tự như hầu hết các câu trả lời khác: kiểm tra ma trận và chuyển vị của nó rằng không có hàng nào chứa nhiều hơn một cặp chữ cái khác nhau liền kề. Đối với ma trận đầu vào 4x3

AAAA
ABBB
AAAB

chức năng có thể được gọi là

f ← (∨/{∧/2>+/2≠/⍵}¨)⊂∘⍉,⊂
f 4 3 ⍴ 'AAAAABBBAAAB'

mà kết quả trong 1.

Giải trình

⊂∘⍉,⊂   The matrix and its transpose.
{...}¨   For each of them:
  2≠/⍵   On each row, replace each adjacent pair with 1 if they differ, with 0 otherwise
  2>+/    Take the sum on each row and check that it's less than 2
  ∧/     AND over all rows
∨/      OR over the resulting two values

1

JavaScript (ES6), 94 byte

x=>!(y=/AB+A|BA+B/).test(x)|(z=[],x.split`
`.map(b=>b.split``.map((c,i)=>z[i]+=c)),!y.test(z))

Phương pháp thay thế cùng kích thước:

x=>(t=s=>!/AB+A|BA+B/.test(s),z=[],x.split`
`.map(b=>b.split``.map((c,i)=>z[i]+=c)),t(x)|t(z))

Điều này trả về 1cho một đầu vào trung thực và giả mạo 0. Tôi bắt đầu làm việc này trước khi bất kỳ câu trả lời nào khác được đăng. Ban đầu tôi cũng đã thử sử dụng khả năng hiểu mảng của ES7, nhưng kết quả đó dài hơn khoảng 10 ký tự so với phương pháp này.

Dùng thử:

a=x=>!(y=/AB+A|BA+B/).test(x)|(z=[],x.split`
`.map(b=>b.split``.map((c,i)=>z[i]+=c)),!y.test(z))

P.onclick=_=>Q.innerHTML='Result: '+a(O.value)
<textarea id=O cols="20" rows="8">AAAAAABBBBBBBBB
AABBBBBBBBBBBBB
AAAAAAAAAABBBBB
AABBBBBBBBBBBBB
AAAAAAAAAAAAAAB</textarea>
<button id=P>Test</button>
<p id=Q>Result: </p>

Gợi ý chào mừng!


Sử dụng [... b] thay vì b.split`` tiết kiệm 3 byte, nhưng chỉ hoạt động trong một số trình duyệt.
intrepidcoder
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.