Бінарний головоломка


10

Вступ

Правила головоломки:

Головоломка Бінарний (також відомий як Takuzu або Subiku) зрозуміла дуже просто і має лише кілька правил:
Оскільки назва гри є бінарною, це досить очевидно, але ви можете заповнити лише нулі та одиниці.

  1. Не більше двох однакових цифр можуть розташовуватися вертикально або горизонтально один до одного
  2. Кожен рядок і кожен стовпець повинні містити рівну кількість нулів і одиниць (це неявно означає, що кожна бінарна гра завжди матиме рівні розміри).
  3. Не може бути жодних дублюваних рядків і не дублюються стовпці (з точно таким же порядком нулів і одиниць).

Ви можете пограти в гру на сайті www.binarypuzzle.com, якщо хочете.

Тактика:

Завдяки правилу 1, ми завжди можемо заповнити цифру, якщо:
- Вже є дві однакові цифри, вертикально або горизонтально прилеглі один до одного, і в цьому випадку ми можемо заповнити протилежну цифру в обидві сторони. Тобто .11...0110...
- Існують дві однакові цифри по вертикалі або по горизонталі з лише одним проміжком між ними. Тобто .1.1...101..

Зважаючи на правило 1, коли залишилось три проміжки, і ми не можемо мати три сусідні з однієї і тієї ж цифри, ми можемо заповнити один з пропусків. Тобто .0.1.010.1.0(Нам залишається заповнити два, і ми не можемо мати три сусідніх у середині, тому перший проміжок повинен бути а 1.)

Завдяки правилу 2, ми завжди можемо заповнити залишилися пробіли в рядку або стовпці, якщо половина з них вже заповнена протилежною цифрою. Тобто .1.011010011

Завдяки правилу 3, ми завжди можемо заповнити протилежні цифри, якщо залишиться лише дві для вирішення в однаковому порядку. Тобто 101100 & 1..100101100 & 110100

Завдяки правилу 3, ми можемо іноді заповнити проміжок, коли три пропуски залишені на рівній впорядкованій лінії. Тобто 010011 & .1.01.010011 & .1.010(Тут ми не можемо заповнити а 1наприкінці, тому що це означає, що нам потрібно заповнити нулі на двох інших проміжках, зробивши обидва рядки рівними за порядком.)

Приклад:

Почнемо з наступної сітки 6х6 із заповненими нулями та нулями (а крапки - це прогалини, які ми ще повинні заповнити):

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

Завдяки правилам 1 і 2 ми можемо заповнити ці цифри:

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

Завдяки правилу 1, ми можемо заповнити 1 у рядку 5, стовпець 1:

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

Завдяки правилу 3 ми можемо заповнити 0 у рядку 1, стовпець 6 (якщо дивитися на рядок 4):

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

Тепер ми можемо продовжувати заповнювати прогалини цифрами завдяки правилам 1 і 2:

.1.010
010101
101100
010011
10.1.0
.010.1

Тепер ми можемо закінчити рядок 5 завдяки правилу 3 (якщо дивитися на рядок 3):

.1.010
010101
101100
010011
100110
.010.1

І тоді ми можемо закінчити головоломку завдяки правилам 1 і 2:

011010
010101
101100
010011
100110
101001

Виклик:

Завдання проста: давши стартову сітку, виведіть розв’язану головоломку.

ПРИМІТКА. Не потрібно виконувати правила, наведені вище. Ви, звичайно, можете, і це повинно дати вам підказки, як реалізувати цей виклик, але грубе посилення рішення з урахуванням правил - це зовсім чудово.
Як ви вирішите це, вирішувати вам, але завдання полягає в тому, щоб вивести вирішену головоломку.

Правила виклику:

  • Формат введення та виведення для мережі є гнучким, але, будь ласка, вкажіть, що ви використовуєте. (Тобто 2D байтовий масив; рядок з новими рядками; тощо)
  • Це вище стосується також використаних символів. У прикладі, який я використав 01., але якщо ви хочете, можете скористатися ABxнатомість. Будь ласка, вкажіть, який формат вводу / виводу та символи ви використовували.
  • Можна припустити , буде використовуватися тільки такі розміри сітки: 6x6; 8x8; 10x10; 12x12; 14x14; 16x16.

Загальні правила:

  • Це , тому найкоротша відповідь у байтах виграє.
    Не дозволяйте мовам з кодовим гольфом відштовхувати вас від публікації відповідей з не кодовими гольф-мовами. Спробуйте придумати якомога коротшу відповідь на "будь-яку" мову програмування.
  • Для вашої відповіді застосовуються стандартні правила , тому вам дозволяється використовувати STDIN / STDOUT, функції / метод з відповідними параметрами, повноцінні програми. Твій дзвінок.
  • Лазівки за замовчуванням заборонені.
  • Якщо можливо, додайте посилання з тестом для вашого коду.
  • Також, будь ласка, додайте пояснення, якщо це необхідно.

Тестові приклади:

Точки додаються лише для читабельності, не соромтесь використовувати пробіли чи будь-що інше, що ви віддаєте перевагу замість прогалин. І в, і в вихідному форматі гнучкі.

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


Відповіді:


4

Брахілог , 34 байти

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

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

Це досить чортово повільно, тому тестовий випадок на TIO - 4х4. Зараз я на своєму комп'ютері запускаю тестовий корпус 6x6, щоб побачити, скільки часу потрібно.

Це бере список списків як вхідний. Невідомі значення слід вказувати змінними, тобто з великими рядками (і всі вони повинні бути різними, оскільки в іншому випадку ви вказували б на те, що деякі комірки повинні мати однакове значення)

Пояснення

Ми обмежуємо значення, які мають бути {0,1}, а потім намагаємось інстанції змінних, поки не буде дотримано всіх 3 правил. Ось чому це так повільно (тому що він буде намагатися всі вони, поки не знайде його; і тому, що в такому випадку Брахілог не реалізований досить добре, щоб обмеження могли бути накладені перед спробою можливої ​​матриці).

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

Як цікаво, як Brachylog вказує на змінні, що виходять за межі головного алфавіту? Отже, скажімо, що ваше рішення запрацювало швидше, воно не зможе заповнити всі порожні пробіли в сітці 14x14 з Aнаскрізним YZвихідним параметром). Чи продовжує він з AA, ABі так далі?
Кевін Круїссен

2
@KevinCruijssen Будь-який ідентифікатор великого регістру - це змінна, тому так AA- це змінна, а KEVINCRUIJSSENтакож змінна.
Фаталізувати

3
Як я підозрював,
Джонатан Аллан

3

JavaScript (ES6), 274 270 байт

Приймає вхід як двовимірний масив, де порожні комірки позначені 2. Друкує всі можливі рішення на консолі.

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

Як це працює

Перша частина коду використовує M()функцію для перевірки дійсності поточної плати як по горизонталі, так і по вертикалі.

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 = {}
  )

Він відображає повний рядок або стовпець у рядку s . Це насправді масив, примусовий до рядка, так це виглядає "1,2,2,0,2,2".

Він використовує:

  • Регулярний вираз /(0|1),\1,\1/для виявлення 3 або більше послідовних однакових цифр.
  • Лічильники b і c відстежують кількість одиниць і нулів . Обидва лічильника ініціалізуються на w / 2 і зменшуються щоразу, коли виникає один або нуль (відповідно). Це призводить до:
    • Ь = с = 0 B * C = 0 → лінія є повною і правильною (як багато нулів , як ті )
    • б> 0 і з> 0 B * C> 0 → лінія не завершенаалесих пір правильно (ми не маємо більшеніж ж / 2 нулів або більшеніж ж / 2 з них )
    • b <0 АБО c <0 b * c <0 → рядок недійсний
  • Прапор m (для 'відсутній'), який не дорівнює нулю, якщо на дошці є щонайменше один два .
  • Об'єкт o відслідковувати всі зустрічаються досі шаблони ліній.

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

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

Демо


Дякуємо, що додали пояснення. І мені подобається, як ви друкуєте всі можливі результати, а не лише один!
Кевін Круїссен

1
@KevinCruijssen Це, мабуть, далеко не оптимально, але писати було цікаво. Приємний виклик!
Арнольд

1

Желе , 53 51 байт

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

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

Спробуйте в Інтернеті! (це не буде запускати будь-який із тестових випадків запитання через обмеження пам’яті - всісітки2 nSpaces створюються у вигляді списку списків цілих чисел - але я поставив там відносно здоровий випадок із єдиним рішенням). Нижній колонтитул відокремлює і форматує сітки.

Метод чистої грубої сили - реалізує правила і перевіряє їх на кожну сітку, яка могла б бути сформована шляхом заміни будь-якого з 2s на 1s або 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.