Codegolf — Могу Ли Я Раздвинуть Головоломку?

  • Автор темы Biboran
  • Обновлено
  • 22, Oct 2024
  • #1

Напишите программу или функцию, которая принимает прямоугольную сетку текста, где каждая ячейка является либо

 
 
 
 
 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
 
or a 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 . Все B cells will form a односвязный формы, т.е. все они будут ортогональны подключен без отверстий (соседние по диагонали буквы не считаются связанными). Аналогично, все A cells will form another simply-connected shape. The grid will always contain at least one B и хотя бы один A .

Представьте, что сетка на самом деле представляет собой два куска тонкого пластика в форме блоков, представленных AAAA ABBA ABAA and AAA A BB AAA порции. Если бы его положили на стол, можно ли было бы раздвинуть две части, сохраняя при этом обе полностью лежащими на столе?

Распечатайте или верните правдивый значение, если два A and BB фигуры можно разделить таким образом, просто раздвинув их. Если нет, распечатайте или верните ложный ценить.

Например, ввод

AAA ABB AAA

правдиво, потому что B section can be slid to the right, separating it from the A х:

B

Однако ввод

A

является ложным, потому что нет возможности сдвинуть B and A части друг от друга, не перекрывая их.

Выигрывает самый короткий код в байтах. При желании вы можете использовать любые два печатный ASCII символы вместо B and A .

Правдивые примеры (разделенные пустыми строками)

B

Ложные примеры

A

#код-гольф #геометрия #сетка

Biboran


Рег
13 Apr, 2014

Тем
82

Постов
228

Баллов
708
  • 26, Oct 2024
  • #2

CJam, 33 32 20 19 17 байт

Пересмотренная версия с массовой поддержкой @Sp3000 и @MartinBüttner:

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 <textarea id=O cols="20" rows="8">AAAAAABBBBBBBBB
AABBBBBBBBBBBBB
AAAAAAAAAABBBBB
AABBBBBBBBBBBBB
AAAAAAAAAAAAAAB</textarea>
<button id=P>Test</button>
<p id=Q>Result: </p> 

Попробуйте онлайн

Взносы

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

Алгоритм и доказательство

Ниже объясняются критерии раздвижения головоломки по горизонтали. Вертикальный регистр можно определить, просмотрев столбцы вместо строк или транспонировав матрицу символов и снова просмотрев строки.

Я буду использовать термин «растяжение» для обозначения максимальной последовательности одинаковых букв. Например, следующие строки имеют 1, 2 и 3 растяжения соответственно:

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)

Я также буду использовать термин «связанный» для обозначения ряда/головоломки, которая не может разъединиться.

Ключевое наблюдение состоит в том, что головоломка может развалиться тогда и только тогда, когда все строки имеют не более двух отрезков.. Или наоборот, это блокируется тогда и только тогда, когда есть строка, содержащая более двух отрезков.

Следующее, возможно, не квалифицируется как строгое математическое доказательство, но я считаю, что оно дает убедительное объяснение, почему это должно быть так.

Легко увидеть, что головоломка переплетена, если в ней есть ряды, состоящие более чем из двух отрезков. Глядя на ряд с 3 растяжками:

0

ясно, что это не дает головоломке развалиться, потому что 1 stretch is locked between the 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 или 2 участка. Начну с пары наблюдений:

  • Ряды только с одним растяжением не способствуют сцеплению головоломки, поскольку они могут скользить в любом направлении без каких-либо столкновений.
  • Если все строки с двумя растяжениями имеют одинаковый порядок x=>!(y=/AB+A|BA+B/).test(x)|(z=[],x.split` `.map(b=>b.split``.map((c,i)=>z[i]+=c)),!y.test(z)) and ⊂∘⍉,⊂ 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 cells are left of all f ← (∨/{∧/2>+/2≠/⍵}¨)⊂∘⍉,⊂ f 4 3 ⍴ 'AAAAABBBAAAB' ячеек или наоборот, и при раздвижении двух частей не возникает столкновений.

Единственный сложный случай — это головоломки, в которых есть строки с двумя участками разного порядка. Я собираюсь показать, что такие головоломки не существует по заданным характеристикам. Чтобы продемонстрировать это, давайте посмотрим на частичную головоломку, имеющую такую ​​конфигурацию, где AAAA ABBB AAAB are wildcards:

0

Теперь в спецификации говорится, что оба 1 and (∨/{∧/2>+/2≠/⍵}¨)⊂∘⍉,⊂ во всех действительных головоломках ячейки просто соединены между собой. Чтобы сделать {a,a,b,a,a,a,b,b,b,b,b,b,b,b} cells connected in the partial puzzle above, we have two options:

  1. Мы обходим один из участков {a,a,b,a,a} , for example:

    {a,a,b,b,b}

    Для этого мы неизбежно расширяем одну из строк, чтобы у нее было 3 отрезка, так что это никогда не даст нам корректную головоломку, в которой все строки имеют не более 2 отрезков.

  2. Соединяем их по прямой дорожке:

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

    <pre id=O></pre> cells are now simply connected, and there are still no rows with more than 2 stretches. However, the 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')) ячейки также должны быть просто соединены. Прямой путь теперь заблокирован подключенным 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 cells, and the only way to connect the <textarea id='S'>BAAAAABB BBAAABBB BBBABBBB BBBABBBB BBBABBBB BBBBBBBB BBBBBBBB</textarea> <p id='P'></p> ячеек заключается в циклическом обходе одного из участков 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); cells. This leads back to case 1, where we can't do that without creating rows of 3 stretches.

Для подсчета растяжек реализация использует оператор CJam RLE.

Объяснение кода

find ||answer||

Улитки, 14

T

Если головоломку можно раздвинуть, она печатает область ввода. В противном случае он печатает 0.

Для более крупных примеров это немного медленно, так как для этого требуется факториал времени в области сетки.

a ||answer||

JavaScript (ES6), 108 107 98 91 82 байта

g

Живая демонстрация. Протестировано в Firefox. Принимает входные данные в виде строки, разделенной символом новой строки.

Правки:

  • Сохранено 1 байт путем изменения A to a literal newline.
  • Сэкономлено 9 байт за счет выполнения теста RegExp непосредственно на многострочной строке вместо преобразования в массив.
  • Устранено еще 9 байтов за счет использования функции определения массива для разделения строки, перемещение ! в B function and calling RegExp directly on array instead of using /AB+A|BA+B/ .
  • Продолжил арифметическую последовательность, сохранив еще 9 байт. Выполнил модуль индекса вместо разделения массива на символы новой строки перед транспонированием.

Как это работает

Предыдущая версия:

g
  1. Примите вводные данные "undefinedAAABBA" and split it by newlines into an array of strings.
  2. Транспонировать T and store it in T . Использовать i to iterate over each element of i , разделите строку на массив символов и используйте map again to append the a -й символ в строке map th line of T . Поскольку каждый элемент a is uninitialized, it will end up looking something like a , но это не будет иметь значения.
  3. Создайте функцию тестирования на основе RegExp. 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) that matches the pattern find . Если оно совпадает, фигуры фиксируются в заданном направлении, потому что тогда существует набор g s sandwiched between two or more \n с или наоборот.
  4. Используйте функцию тестирования a=>!(T=[],R=/AB+A|BA+B/).test([...a].map((c,i)=>T[i%-~a.search` `]+=c))|!R.test(a) to test all elements of the block ,, 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' и его транспонировать o(t\B+~)+!(t\B for a match using 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. . Если оба совпадают, то части блокируются в обоих направлениях, поэтому выведите ложное значение, в противном случае — истинное.
 

Smith38


Рег
28 Oct, 2011

Тем
80

Постов
205

Баллов
625
  • 26, Oct 2024
  • #3

Javascript (ES6), 118

A B

Объяснение:

A ||answer||

JavaScript (ES6) 72 74

Редактировать Сэкономлено 2 байта, спасибо @NotthatCharles

У меня есть интуитивное понимание: если одна деталь может скользить хотя бы на долю шага, значит, она бесплатна. Текущие тестовые случаи подтверждают это.

Поэтому я проверяю только один шаг в каждом направлении.

Используемые символы: 1 и 0.
Еще 2 байта для использования любых двух печатных символов, таких как A и B.

Проверьте запуск приведенного ниже фрагмента в браузере, совместимом с EcmaScript 6 (с поддержкой оператора распространения — IE Firefox).

B A
 

Богдана 13


Рег
18 May, 2011

Тем
60

Постов
183

Баллов
483
  • 26, Oct 2024
  • #4

Математика 100 69 байт

Благодаря сохранению огромных 31 байта благодаря @Martin Buttner,

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

Форматирует ввод как матрицу символов; он также выполняет транспонирование матрицы. Если матрица или ее транспонирование имеет не более двух прогонов в строке, то головоломка может скользить.

..AAAAAA AAABBBBA .......A BBAAAAAA ........ has 2 runs of letters.

B has 3 runs of letters.

A has 4 runs of letters.

 

Vider


Рег
06 Jun, 2006

Тем
75

Постов
194

Баллов
619
  • 26, Oct 2024
  • #5

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

B

Попробуйте здесь. Это функция, которая принимает двумерный массив символов и возвращает A for sliding instances and ....... AAABBBB ....... BBAAAAA ....... для нескользящих.

.

Алгоритм аналогичен большинству других ответов: проверьте матрицу и ее транспонирование, чтобы ни одна строка не содержала более одной соседней пары разных букв.

B

Для входной матрицы 4x3 A .

функция может быть вызвана как

B ||answer||

что приводит к

A

Объяснение

B

JavaScript (ES6), 94 байта A for a truthy input and BBBAAB Альтернативный метод того же размера:

Это возвращает

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

за ложь. Я начал работу над этим до того, как были опубликованы какие-либо другие ответы. Я также изначально пытался использовать понимание массивов ES7, но в итоге это оказалось примерно на 10 символов длиннее, чем этот метод.

 

Gerasimenkoir


Рег
11 Apr, 2020

Тем
77

Постов
201

Баллов
636
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно