Зробіть рух на дошці Go


13

Вам надається позиція на дошці для гри «Go» та руху для гри. Вам потрібно вивести, чи закон є чи законним, чи нову позицію ради, якщо вона законна.

Коротке пояснення рухів Go: гра складається з альтернативного розміщення чорно-білих шматочків («каміння») в порожніх місцях на квадратній дошці. Набори шматочків одного кольору, які з'єднані один з одним (чотиристоронніми), називаються групами. Порожні місця на дошці, які примикають до групи (також 4-х сторонні), вважаються "свободами" цієї групи. Група з 0 свободами захоплюється (видаляється з дошки). Хід, який спричинив би захоплення власної групи ("самогубство"), є незаконним, якщо тільки він не захопить одну чи кілька груп опонента (здобуття волі в процесі, щоб вона фактично не була захоплена).

Для тих, кого це не стосується, вам не потрібно мати справу з ko (і superko), тобто ви можете вважати, що захоплення ko є законним. Якщо ви не знаєте, що це означає, просто дотримуйтесь наведених вище правил, і це буде добре.

Введення: число n між 2 і 19 (включно), що представляє розмір плати, а потім n рядків з n чисел між 0 і 2 (включно), що представляють позицію дошки, а потім 3 числа, розділені пробілом, що представляють собою рух, який потрібно зробити. У положенні дошки 0 означає порожнє місце, 1 означає чорний камінь і 2 означає білий камінь. Цей хід дає стовпчик, рядок і колір (1 або 2) каменю для розміщення. Стовпець і рядок засновані на 0, починаючи від 0 до n-1 (включно) і рахуються в тому ж порядку, що і вхід дошки.

Можна припустити, що дана позиція правління є законною (всі групи мають принаймні одну свободу).

Вихід: рядок, що містить 1 або 0 (або правда / хибність, якщо ви віддаєте перевагу), якщо переміщення є законним чи ні, з наступним (лише у випадку легального переходу) новим положенням дошки у тому ж форматі, що і вхідне.

Оцінка: краща кількість байтів повного вихідного коду, менша. 20% додаткового штрафу за використання символів, що не належать ascii, і 20% додаткового штрафу, якщо ваш код не можна перевірити в Linux за допомогою вільно доступного програмного забезпечення.

Правила: Немає мережевих підключень і немає сторонніх бібліотек. Ваша програма повинна використовувати стандартні потоки введення та виведення або стандартний еквівалент для вашої мови програмування.

Приклади:

1) Input:

2
10
01
1 0 2

Output:

0

2) Input:

2
10
11
1 0 2

Output:

1
02
00

3) Input:

5
22122
22021
11211
02120
00120
2 1 1

Output:

1
00100
00101
11011
02120
00120

4) Input:

6
000000
011221
121121
122221
011110
000000
4 0 1

Output:

1
000010
011221
121121
122221
011110
000000

Відповіді:


2

Python 3 (557 504 488)

import sys
s=sys.stdin
M=int(next(s))+1
j=Z=M*M-M
S=s.read(Z)
P=0
b=[0]*3
while j>0:j-=1+(j%M<1);b[int(S[j])]|=1<<j;P|=1<<j
N=lambda x:(x<<1|x>>1|x<<M|x>>M)&P&~x
def h(a,b):t=a|N(a)&b;return h(t,b)if t!=a else a
c,r,m=map(int,next(s).split())
o=m%2+1
p=1<<M*r+c
b[m]|=p
for n in(p<<1,p>>1,p<<M,p>>M):
 e=h(n&P,b[o])
 if~b[m]&N(e)<1<=n&b[o]:b[o]&=~e
_,B,W=b
g=~b[o]&N(h(p,b[m]))>=1>~_&p
print(+g)
q=''
while j<Z:
 r=1<<j
 if g*j%M>M-2:print(q);q=''
 else:q+='012E'[(r&B>0)+(r&W>0)*2]
 j+=1

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

Негольована версія з великою кількістю коментарів: https://gist.github.com/airfrog/8429006


У вас є БАГАТО прогалин в кінці кожного рядка, файл , як ви вивісили він має дві тисячі сімсот тридцять дві байт.
aditsu кинути, тому що SE є EVIL

@aditsu Це слід виправити зараз
airfrog

Розмір досі невірний, зараз має бути 555 :) Також мені цікаво, чи можна ще зберегти кілька байтів, скориставшись крапкою з комою.
aditsu кинути, тому що SE - EVIL

Помилка? Вхід: 6 000000 011221 121121 122221 011110 000000 4 0 1Вихід: 0. Додано зараз як приклад 4.
aditsu quit тому, що SE - EVIL

Ця помилка виправлена, я також виявив і виправив ще одну помилку під час гольфу, яку ви можете додати як приклад. Вхід: 5 22100 20211 12211 12120 01120 1 1 2вихід повинен бути 0.
повітряна жаба

2

Пітон ( 912 1004)

def o():
 n=int(raw_input(''))
 i=[raw_input('') for r in range(n+1)]
 b=[map(int,list(r)) for r in i[:n]]
 u,v,w=map(int,i[n].split(' '))
 if b[v][u]!=0:return 0
 b[v][u]=w
 if w==1:q=2
 elif w==2:q=1
 else:return 0
 f=[[],[],[]]
 h=[[],[],[]]
 g=[range(z*n,(z+1)*n) for z in range(n)]
 d=[(1,0),(-1,0),(0,1),(0,-1)]
 m=lambda z:max(0,min(n-1,z))
 t=[0,1,2,0,1]
 for j,s in enumerate(t):
  for r in range(n):
   for c in range(n):
    for y,x in map(lambda p:(m(r+p[0]),m(c+p[1])),d):
     if s==0:
      if b[y][x]==b[r][c]:
       if g[y][x]!=min(g[y][x],g[r][c]):
        t.insert(j+1,0)
       g[y][x]=g[r][c]=min(g[y][x],g[r][c])
     elif s==1:
      if g[r][c] not in h[b[r][c]]:
       h[b[r][c]].append(g[r][c])
      if b[y][x]==0 and g[r][c] not in f[b[r][c]]:
       f[b[r][c]].append(g[r][c])
    if s==2:
     if b[r][c]==q and g[r][c] not in f[b[r][c]]:
      b[r][c]=0
 h[w].sort()
 f[w].sort()
 if h[w]!=f[w]:return 0
 return "1\n"+'\n'.join([''.join(map(str,r)) for r in b])
print o()

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

Це, ймовірно, може бути значно скорочено ...

Інтерактивний приклад працює:

2
10
01
1 0 2
0

2
10
11
1 0 2
1
02
00

5
22122
22021
11211
02120
00120
2 1 1
1
00100
00101
11011
02120
00120

6
000000
011221
121121
122221
011110
000000
4 0 1
1
000010
011221
121121
122221
011110
000000

1
Ваша програма нічого не робить, вона лише визначає функцію.
aditsu кинути, тому що SE - EVIL

Запустіть його в інтерактивному режимі і викликати його з печаткою про () , як показано в прикладі бігу ...
юр

Ні. Це повинна бути окрема програма, яку ви запускаєте з командного рядка. Крім того, це також зробить її коротшою.
aditsu кинути, тому що SE - EVIL

Виправлено, додавши друку про () в останньому рядку
юр

Чому б просто не використовувати функціональне тіло (перекреслене)? І я думаю, що ви також провалили нещодавно доданий приклад 4.
aditsu киньте, тому що SE
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.