Чи можу я розсунути головоломку?


38

Напишіть програму або функцію, яка містить прямокутну сітку тексту, де кожна комірка є Aабо a B. Усі Aкомірки утворюватимуть просто сполучену форму, тобто всі вони будуть ортогонально з'єднані без отворів (по діагоналі сусідні букви не вважаються сполученими). Так само всі Bклітини формуватимуть іншу просто з'єднану форму. Сітка завжди буде містити хоча б одну Aі хоча б одну B.

Уявіть, що сітка - це насправді два шматочки блокової форми з тонкого пластику, представлені частинами Aта B. Якби його було розміщено плоско на столі, чи могли б два шматки розсунутись, зберігаючи обидва повністю плоскі на столі?

Роздрукуйте або поверніть значення " truthy", якщо дві форми Aі Bформи можна було б розділити так, просто відтягнувши їх. Якщо ні, надрукуйте або поверніть фальшиве значення.

Наприклад, вхід

AAA
ABB
AAA

є правдоподібною, оскільки BBрозділ можна ковзати праворуч, відокремлюючи його від As:

AAA
A    BB
AAA

Однак вхід

AAAA
ABBA
ABAA

є хибною, тому що немає способу розсунути частини Aта їх Bчастини, не перекриваючи їх.

Виграє найкоротший код у байтах. За бажанням ви можете використовувати будь-які два символи ASCII для друку, що роздруковуються, замість Aта B.

Приклади правди (розділені порожніми рядками)

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

Приклади фальшивості

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

Відповіді:


9

Равлики, 14

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

Якщо головоломку можна розсунути, вона друкує область введення. В іншому випадку він друкує 0.

Для більших прикладів це трохи повільно, оскільки це потребує часу в районі сітки.

         ,, 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
"Це трохи повільно .." . Не впевнений, чого ви очікували від мови під назвою Равлики ...
Bassdrop Cumberwubwwwwub

4
@Bas Тепер тепер немає причин для втирання солі в рани.
Трасіва

21

CJam, 33 32 20 19 17 байт

Переглянута версія з масовою підтримкою від @ Sp3000 та @ MartinBüttner:

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

Спробуйте в Інтернеті

Внески

  • @ Sp3000 запропонував критичне спрощення мого оригінального алгоритму.
  • @ MartinBüttner застосував свої шалені навички гольфу до переглянутого підходу, що майже напевно призвів до більш короткого коду, ніж я б придумав навіть після розгляду спрощення.

Алгоритм і доказ

Далі пояснюються критерії розгадування головоломки горизонтально. Вертикальний випадок можна визначити, переглянувши стовпці замість рядків, або перенісши матрицю символів і знову переглянувши рядки.

Я буду використовувати термін "розтягнути" для максимальної послідовності одних і тих же букв. Наприклад, наступні рядки мають відповідно 1, 2 та 3 розтяжки:

AAAAAAAA
BBBAAAAA
AABBBAAA

Я також буду використовувати термін "замкнений" для рядка / пазла, який не може розсуватися.

Ключове зауваження полягає в тому, що головоломка може розсуватися, якщо і лише тоді, коли всі ряди мають не більше 2 розтяжок . Або зворотно, він замикається, якщо і лише за наявності будь-якого ряду з більш ніж 2 розтягненнями .

Наведене нижче може не кваліфікуватися як суворий математичний доказ, але я вважаю, що це дає переконливе пояснення, чому це повинно бути так.

Неважко помітити, що головоломка замикається, якщо вона має рядки більше 2 розтяжок. Дивлячись на ряд з 3-ма розтяжками:

BBBAAB

зрозуміло, що це заважає головоломці розсуватися, оскільки Aнатяжка заблокована між Bрозтягненнями. Це означає, що рядок перемикається, що в свою чергу робить всю головоломку замкненою.

Протилежний напрямок доказування не настільки очевидний. Нам потрібно показати, що немає замкнених пазлів, де всі ряди мають лише 1 або 2 розтяжки. Починаючи з пари спостережень:

  • Рядки з лише 1 розтяжкою не сприяють зведенню головоломки, оскільки вони можуть ковзати в будь-яку сторону без зіткнень.
  • Якщо всі рядки з двома розтяжками мають однаковий порядок Aі B, головоломка явно не переплітається. У цьому випадку всі Aосередки залишаються від усіх Bкомірок, або навпаки, і при розсуванні цих двох частин немає зіткнень.

Єдиний складний випадок - це пазли, де у нас є рядки з 2-ма розтяжками різного порядку. Я збираюся показати, що таких задачок не існує за даними специфікаціями. Щоб показати це, давайте подивимось на часткову головоломку, яка має таку конфігурацію, де .знаки підстановки:

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

Тепер у специфікації сказано, що Aі Bклітинки, і клітини просто з'єднані у всіх дійсних головоломок. Щоб зробити Aклітинки з’єднаними в частковій загадці вище, у нас є два варіанти:

  1. Накручуємо навколо однієї з ділянок B, наприклад:

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

    Для цього ми неминуче подовжуємо один з рядів на 3 розтяжки, тому це ніколи не дасть нам дійсної головоломки, де всі ряди мають не більше 2 розтяжок.

  2. Ми з'єднуємо їх прямим шляхом:

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

    Ці Aклітини тепер просто з'єднані, і до сих пір немає рядка з більш ніж 2 -х ділянок. Однак Bклітини також потрібно просто з'єднати. Зараз прямий шлях блокується підключеними Aклітинками, і єдиний спосіб з'єднання Bкомірок - це петля навколо однієї з ділянок Aкомірок. Це повертається до випадку 1, де ми не можемо цього зробити, не створивши рядків з 3 розтяжок.

Для підрахунку розтяжок реалізація використовує оператор CJam RLE.

Пояснення Кодексу

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 байт

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

Демонстраційна демонстрація . Випробуваний у Firefox. Вводиться в якості рядка з обмеженим рядком.

Зміни:

  • Збережено 1 байт, змінивши \nбуквальний новий рядок.
  • Збережено 9 байтів, виконавши тест RegExp безпосередньо у багаторядковому рядку замість перетворення на масив.
  • Вилучили ще 9 байт, використовуючи розуміння масиву, щоб розділити рядок, рухаючись! у gфункцію та виклик RegExp безпосередньо на масив, а не використовувати find.
  • Продовжив артметичну послідовність, зберігаючи ще 9 байт. Зробив модуль на індекс замість того, щоб розділити масив на нові рядки перед тим, як приймати транспонінг.

Як це працює

Попередня версія:

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. Візьміть вхід aі розділіть його новими рядками на масив рядків.
  2. Перекладіть aі зберігайте його T. Використовуйте mapдля ітерації над кожним елементом a, розділіть рядок на символьний масив і mapзнову використовуйте для додавання iсимволу в рядку до iпершого рядка T. Оскільки кожен елемент Tнеініціалізований, він буде виглядати щось подібне "undefinedAAABBA", але це не має значення.
  3. Створіть на основі RegExp функцію тестування, gяка відповідає шаблону /AB+A|BA+B/. Якщо вона збігається, шматки фіксуються в заданому напрямку, тому що тоді існує набір Bs, прошитий між двома або більше As або навпаки.
  4. Використовуйте функцію тестування gдля тестування всіх елементів блоку aта його транспонування Tна відповідність find. Якщо обидва збігаються, то шматки фіксуються в обох напрямках, тож виведіть помилкове значення, інакше просте.

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>

Пояснення:

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

Щури! Бий мене до цього.
intrepidcoder

5

JavaScript (ES6) 72 74

Відредагуйте 2 байти, збережені thx @NotthatCharles

Я інтуїтивно розумію, що якщо одна деталь може просунути лише частину кроку, то це безкоштовно. Поточні тестові випадки це підтверджують.

Тож я перевіряю лише один крок у кожному напрямку.

Використовувані символи: 1 і 0
2 байти більше, щоб використовувати будь-які 2 символи для друку, такі як A і B

Випробуйте запуск фрагмента нижче в браузері, сумісному з EcmaScript 6 (підтримуючи оператор розповсюдження - 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>


Ну, це просто геній. Знов побили професіонала. :-)
ETHproductions

s[p+o]=='0'здається трохи довгим. Чи можна його замінити 1-s[p+o], або принаймні s[p+o]==0?
ETHproductions

@ETHproductions так, це довго, варто ще подумати. Він повинен містити значення false для '\ n' (вертикальна межа, перетворюється на 0) та для невизначеної (верхня та нижня межа, перетворюється на NaN)
edc65

=='A'можна замінити на <'B'. Те саме для=='B'
Не те, щоб Чарльз

Крім того, ви не можете просто зробити це x+s[p+o]=='AB'?
Не те, що Чарльз

3

Mathematica 100 69 байт

Завдяки масивному збереженому 31 байту завдяки @Martin Buttner,

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

Форматує вхід у вигляді матриці символів; це також робить транспозицію матриці. Якщо або матриця, або її транспонінг мають не більше 2 прогонів у рядку, то головоломка може ковзати.

{a,a,b,b,b} має 2 тиражі листів.

{a,a,b,a,a} має 3 тиражі листів.

{a,a,b,a,a,a,b,b,b,b,b,b,b,b} має 4 тиражі листів.


2

Діалог APL, 22 байти

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

Спробуйте тут. Це функція, яка займає 2D-масив символів і повертається 1для розсувних екземплярів та 0для нековзних. Алгоритм схожий на більшість інших відповідей: перевірити наявність матриці та її перенесення, що жоден рядок не містить більше однієї сусідньої пари різних літер. Для вхідної матриці 4x3

AAAA
ABBB
AAAB

функцію можна викликати як

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

що призводить до 1.

Пояснення

⊂∘⍉,⊂   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 байти

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

Альтернативний метод однакового розміру:

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

Це повертається 1за правдивий внесок і 0за хибність. Я почав працювати над цим ще до того, як були опубліковані інші відповіді. Я також спочатку намагався використовувати розуміння масивів ES7, але це виявилося приблизно на 10 символів довше, ніж цей метод.

Спробуй:

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>

Пропозиції Ласкаво просимо!


Використання [... b] замість b.split`` зберігає 3 байти, але працює лише в деяких браузерах.
intrepidcoder
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.