Логічні фігури точок


12

Гра

Останнім часом більшу частину мого часу займає захоплююча гра на моєму телефоні під назвою Logic Dots, яка надихнула мене написати цей виклик. Простіше пояснити правила, якщо я покажу вам дисплей гри, тому ось скріншот невирішеної та вирішеної головоломки:

Зараз тут слід помітити три основні речі.

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

Мета гри - вписати потрібні фігури в сітку. Ви можете обертати фігури, але вони не можуть входити по діагоналі.

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

Ось більша та трохи складніша сітка:

Зауважте, що у невирішеній головоломці вже кілька квадратів заповнені. Сірі квадрати означають заблоковані квадрати, на яких НЕ МОЖЕТЕ розмістити крапку. Крапки з хвостами говорять вам про те, що крапка знаходиться в цьому місці, і вона посилається на щонайменше ще одну крапку в напрямку хвоста, але не в іншому напрямку (включаючи протилежний напрямок).

Позначення

У решті цієї публікації я буду звертатися до ради, використовуючи такі символи:

  • <,>, ^, v - Позначає заздалегідь розміщену крапку з хвостом, що простягається у напрямку точки
  • * - Позначає крапку. Якщо подано на невирішеній сітці (вхід), це індивідуальна форма. Якщо у виході, то він підключений до крапок навколо нього.
  • # - Позначає заблокований квадрат сітки (де ви не можете розмістити крапку)
  • -, | (дефіс і штрих) - Позначте крапку з правого та лівого хвоста та крапку відповідно вгору та вниз хвостом
  • ** (пробільний символ) - ** Позначає порожній пробіл

Використовуючи ці символи, останній приклад випадку (невирішений) можна представити наступним чином:

 <    



    # 
 ^ #

І рішення можна представити як:

*< * *
   *  
     *
 *   *
 * *#*
 ^ # *

Зауважте, що жодна дві форми не може торкатися горизонтально, вертикально або по діагоналі , тому такий випадок недійсний:

 *** 
**   
  ** 

Виклик

Ваше завдання - вирішити будь-яку логічну точку головоломки, від 4х4 до 9х9 включно. Ви отримаєте чотири рядки введення, потім ігрову дошку. Рядки будуть такими:

  • 1-й рядок, "Фігури" - фігури, які потрібно знайти, кожна з яких подається у формі sizexquantity(наприклад, 3x2для двох фігур довжиною три) і розділена пробілом. Приклад рядка:3x1 2x1 1x1
  • 2-й рядок, Стовпці - список, розділений пробілом, необхідного підрахунку крапок для кожного стовпця. Приклад рядка:1 1 2 2
  • 3-й рядок, рядки - пробіл, відокремлений пробілом, необхідного підрахунку крапок для кожного рядка. Приклад рядка:3 0 3 0
  • 4-й рядок, Розмір дошки - Одне ціле число, розмір плати, B

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

4x1 3x1 2x2 1x2
1 4 0 3 0 5
4 1 1 2 3 2
6
 <    



    # 
 ^ #  

Тоді ваша програма виведе вирішену дошку в тій же нотації. Відповідний вихід для вищевказаного входу такий:

** * *
   *  
     *
 *   *
 * *#*
 * # *

Зауважте, що ігрова дошка може мати декілька рішень. У цьому випадку просто виведіть одне дійсне рішення. Крім того, ваша програма повинна вивести правильне рішення протягом 10 секунд на розумному настільному комп’ютері для складної сітки 10х10.

Це код гольфу, тому виграє найменше байт.


Випробування

Введення 1

3x2 1x4
2 2 3 1 2
4 0 3 0 3
5


    #
  #  
    *

Вихід 1

*** *

 ***#
  #  
* * *

Введення 2

3x1 1x6
2 0 4 0 3
3 1 2 1 2
5
*    


   # 

Вихід 2

* * *
  *  
  * *
*  # 
  * *

Введення 3

5x1 4x1 2x1 1x2
1 2 3 3 2 2
0 5 0 4 0 4
6
#     
  -   


 #    
   <  

Вихід 3

#     
 *****

 **** 
 #    
* ** *

Так, це правильно @flawr
globby

@flawr t no two shapes can touch horizontally, vertically or diagonally(це має бути на початку, не втрачено майже в кінці, але все одно ...)
edc65

@globby Чи не кожен порожній простір буде замінений на #, я вважаю, що # - це коли ви натискаєте порожнє місце в грі. Коли ви закінчите рівень, він заповнює всі порожні комірки.
Теун Пронк

@TeunPronk № # - це пробіли, заздалегідь визначені, що ви не можете розмістити крапку на рівні, як сірі квадрати у другому прикладі.
глобі

2
Краще, ніж пропонуйте винагороду, вам слід додати цікавіші тестові випадки та виправити помилки у своєму питанні. Наприклад, останній вихід до поточних тестових випадків все ще містить <і ^
edc65

Відповіді:


3

Пітон 2: 766 739 696 663 633 байт

def f(B,S,o=0):
 if[]==S:print'\n'.join(B);exit()
 s=S[0]
 for i in r:
  for j in R(Z-s+1):
   if(B[i][j]in' '+'>v'[o])*(B[i][j+s-1]in' '+'<^'[o])*({' ','-|'[o]}>=set(B[i][j+1:j+s-1]))*all(B[x][y]in'# 'for x,y in [(x,y)for y in R(j-1,j+s+1)for x in i-1,i+1]+[(i,j-1),(i,j+s)]if 0<=x<Z>y>=0):q=B[:];q[i]=q[i][:j]+'*'*s+q[i][j+s:];q=(q,t(q))[o];any((t(q)+q)[k].count('*')>m[k]for k in R(Z+Z))or f(q,S[1:])
 o or f(t(B),S,1)
y=raw_input;S=[];s=str.split
for i in s(y()):u,v=map(int,s(i,'x'));S+=[u]*v
m=map(int,s(y())+s(y()));Z=input();R=range;r=R(Z);B=[y()for _ in r];J=''.join;t=lambda x:map(J,zip(*x))
f(B,S[:len(S)-J(B).count('*')])

Дивіться, як це працює в Інтернеті: Ideone.com (Інтернет-версія може бути надто повільною для великих та складних мереж, в автономному режимі це має бути нормально)

Введення здійснюється через stdin, просто скопіюйте та пройдіть рядки з ОП (але будьте обережні, зміна stackexchange іноді видаляє пробіли чи рядки).

Деякі основні ідеї цього коду: він використовує рекурсивну функцію f. fнамагається розмістити одну фігуру біля дошки. Для кожного можливого місця він називає себе модифікованою дошкою. У ньому 3 петлі. oвизначає орієнтацію (2 - горизонтальна, 3 - вертикальна). Він завжди буде розміщувати фігуру горизонтально, тому в кінці o=2перенесе плату з функцією t. i- це рядок і jє всі можливі початкові стовпці. Тоді відбувається чимало перевірок, якщо на кінцях фігури є дійсні символи, якщо в середині фігури є дійсні символи та якщо навколишнє порожнє.


Я намагався скоротити останні 6 байтів, коли побачив останню редакцію (-30) і відмовився ... У вас є мій голос за те, що це варто
edc65

3

JavaScript (ES6) 661 667 695 702 745 755 786 790 784 798

Незавершена робота може бути скорочена. Напевно, занадто повільно на складній сітці. Можливо, не.

Редагуйте трохи довше, набагато швидше.
Змініть 2 виправлення помилок, перевірку стовпців / рядків. До речі, зараз це швидше

Функція M є основною. Параметр w - це рядковий рядок з усім входом. Функція аналізує вхід і готує стартову дошку. Символи <>^v|-*на стартовій дошці замінюються на ,, кожен з ,яких повинен бути замінений *правильним рішенням.

Функція R намагається рекурсивно розмістити всі форми на дошці. Коли форма розміщена, вона називає себе, передаючи коротший список фігур і модифіковану дошку. Якщо розміщені всі фігури, рішення все ще може бути недійсним, якщо вони ,не замінені на *.

Перевірка функції P, якщо фігуру можна розмістити в заданому положенні та орієнтації. Він перевіряє всі обмеження (всередині дошки, без перекриття, без дотику, дійсного числа рядків і стовпців)

M=w=>(
  [x,c,r,z]=w=w[S='split'](n='\n'),
  (b=[...w.slice(4).join(n)])
  .map((c,p)=>~(k='*<>-*^v|'.indexOf(c))&&[(q=k>3?z:1,0),k&1&&-q,k&2&&q].map(o=>b[p+o]=0),
    c=c[S](e=' '),r=r[S](e),w=z++,f='*',s='',x[S](e).map(v=>s+=v[0].repeat(v[2]))),
  R=(s,b,x=0,y=0,n=s[0],V=i=>b[i]>'#',
    P=(p,o,q,t,g,l,d=[...b])=>{
        if(l<z-n&!V(p+o*l-o)&!V(p+o*l+o*n))
        {
          for(i=-1;v=d[p],++i<w;p+=o,t-=v==f)
            if(i>=l&i-n<l)
              for(v!=e&v!=0|[q,w,~z].some(w=>V(p+w)|V(p-w))?t=0:d[p]=f,j=o*i,u=k=0;
                  ++k<z;(u+=d[j]==f)>g[i]?t=0:j+=q);
          return t>=n&&d.join('')
        }
    })=>{
    if(b){
      if(!n)return~b.search(0)?0:b;
      for(s=s.slice(1);y<w||(y=0,++x<w);++y)
        if(h=R(s,P(y*z,1,z,r[y],c,x))||n>1&&R(s,P(x,z,1,c[x],r,y)))return h
    }
  })(s,b)

Тест в консолі FireFox / FireBug

;['3x2 1x4\n2 2 3 1 2\n4 0 3 0 3\n5\n     \n     \n    #\n  #  \n    *\n'
,'3x1 1x6\n2 0 4 0 3\n3 1 2 1 2\n5\n*    \n     \n     \n   # \n     \n'
,'5x1 4x1 2x1 1x2\n1 2 3 3 2 2\n0 5 0 4 0 4\n6\n#     \n  -   \n      \n      \n #    \n   <  \n'
,'4x1 3x1 2x2 1x2\n1 4 0 3 0 5\n4 1 1 2 3 2\n6\n <    \n      \n      \n      \n    # \n ^ #  \n']
.forEach(x=>console.log(x,M(x).replace(/ /g,'`'))) // space replaced with ` for clarity

Вихід (загальний час виконання <1сек)

3x2 1x4
2 2 3 1 2
4 0 3 0 3
5


    #
  #  
    *

***`*
`````
`***#
``#``
*`*`*

3x1 1x6
2 0 4 0 3
3 1 2 1 2
5
*    


   # 


*`*`*
``*``
``*`*
*``#`
``*`*

5x1 4x1 2x1 1x2
1 2 3 3 2 2
0 5 0 4 0 4
6
#     
  -   


 #    
   <  

#`````
`*****
``````
`****`
`#````
*`**`*

4x1 3x1 2x2 1x2
1 4 0 3 0 5
4 1 1 2 3 2
6
 <    



    # 
 ^ #  

**`*`*
```*``
`````*
`*```*
`*`*#*
`*`#`*

Схоже, @globby забув про цю щедрість. У будь-якому випадку, у цій гонці було дуже весело.
Якубе
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.