진주 목걸이를 묶는


18

개요

진주 (또는 Masyu) 는 그리드에서 재생되는 논리 게임입니다. 격자에 검은 색과 흰색 진주가 있습니다. 목적은직선 세그먼트와 직각 만 사용하여 각 진주를 통과하는 단일 폐쇄 루프 를 형성하는것입니다.

루프가 진주와 상호 작용하는 방식을 결정하는 몇 가지 규칙이 있습니다.

  • 화이트 펄은 직선 으로 이동해야 하지만 루프는 경로 의 이전 및 / 또는 다음 셀에서 회전 해야합니다 .
  • 검은 진주가 켜져 있어야 하지만 고리는 경로에서 다음 이전 셀을 통해 직선으로 이동해야합니다 .
  • 루프가 교차하거나 교차 하지 않아야 합니다. 모든 셀에는 정확히 0 개 또는 2 개의 루프 항목이 있습니다.

Wikipedia (및 솔루션)의 예제 퍼즐 :

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

당신의 목표는 주어진 퍼즐을 해결하는 것입니다. 가능한 솔루션이 여러 개인 경우 어떤 솔루션을 제공하든 문제가되지 않습니다.

입력

입력이 해결되지 않은 정사각형 그리드가됩니다. 위에 표시된 예는 다음과 같습니다.

..w.w.....
....w...b.
..b.b.w...
...w..w...
b....w...w
..w....w..
..b...w...
w...b....w
......ww..
..b......b

w흰색 진주이고 b검은 진주이며 .빈 세포입니다.

입력이 유효하다고 가정하십시오. 이것은 그것이 잘 형성되어 있고 적어도 하나의 해결책이 가능하다는 것을 의미합니다. 유효한 모든 퍼즐은 3x3 이상이며 진주가 하나 이상 포함되어 있습니다.

산출

출력은 경로를 나타내는 좌표 문자열입니다. 그리드의 왼쪽 위 모서리는 0 0이고 오른쪽 위는입니다 n-1 0. 여기서 n 은 그리드의 너비입니다.

경로는 단순히 일련의 정렬 된 좌표입니다.

x1 y1 x2 y2 x3 y3 ...

경로는 닫혀 있다고 가정되므로 끝에서 첫 번째 좌표를 반복 할 필요 는 없지만 그렇게하는 데 대한 벌점은 없습니다.

출력 구성되어야 적어도 경로 곳곳. 회전이 없으면 경로의 모든 셀을 출력 할 필요는 없습니다. 예를 들어, 예제 출력은 다음과 같이 시작할 수 있습니다.

1 0 5 0 5 1 ...

또는

1 0 2 0 3 0 4 0 5 0 5 1 ...

경로에없는 셀 은 출력에 포함 되지 않아야 합니다. 경로의 모든 셀에서 시작할 수 있습니다.


단편

다음은 솔루션을 시각화하는 데 사용할 수있는 스 니펫입니다. 작업중인 그리드와 출력 경로에 붙여 넣기 만하면됩니다. 내 코드를 보는 것이 고통 스럽다는 것을 알고 있습니다.


테스트 사례

이 테스트 사례는 각 입력에 대해 하나의 가능한 출력을 보여줍니다 (마지막은 제외). 다른 유효한 경로가있을 수 있습니다. CW 또는 CCW로 이동하거나 다른 지점에서 시작할 수 있습니다. 솔루션은 테스트 케이스를 일 / 주 / 일이 아닌 초 / 분 / 시간으로 해결할 수 있어야합니다.

진주 -3

...
w..
..b

0 0 1 0 2 0 2 1 2 2 1 2 0 2 0 1

진주 -6

.wb..b
......
..b...
w.ww..
......
b....b

0 0 2 0 2 2 4 2 4 1 3 1 3 0 5 0 5 5 3 5 3 4 4 4 4 3 1 3 1 4 2 4 2 5 0 5 0 2 1 2 1 1 0 1

진주 -12

.....w.b.w..
ww..b...b...
.w.....b....
...wbww..b.b
....b.......
w.w.........
..w......b.b
.....bb.....
.....b.....w
w.ww..b.....
...w......w.
b..w.....b..

당신은 마지막 테스트 케이스에 대한 솔루션을 넣지 않았습니다 ...
mbomb007

2
@ mbomb007 맞습니다.
Geobits

그래서 해결책이 없습니까?
mbomb007

2
해결책이 있습니다. 나는 답변을 그들의 노력에 대해 보여줄 수 있도록 열어 두었습니다. 또한 규칙에 대한 느낌을 얻기 위해 퍼즐을 한두 손으로 해결하는 데 도움이 될 수 있으며 모든 예제가 사전 해결 된 경우 수행하기가 어렵습니다.
Geobits

진주가없는 그리드가 2x2 이상인 그리드가 유효한 것으로 간주됩니까 (두 번째 문장은 유효하지 않으며 입력에 대한 요점은 해결되지 않은 것입니다 (확장되지 않은 진주가 없으면 해결해야 함))? 그렇다면 진주가없는 고리가 필요합니까? 아니면 정확히 무엇입니까? 아마도 특정 색상이 없어도됩니까?
VisualMelon

답변:


7

C, 590640760880963 1018

무차별 대입 속도는 상당히 빠릅니다. 12x12 테스트는 10ms 미만에서 실행됩니다. 그것을 알면 골프에 더 적합한 언어를 선택할 수 있습니다.

큰 퍼즐이 정사각형이 아닌 경향이 있기 때문에 보드가 정사각형이라고 가정하지 않습니다.

W세트하는 기판 크기에 제한을 정의한다. W - 2경계 검사를 피하기 위해 테두리에 추가 행을 사용하므로 실제 한계는 더 작습니다 .

#define W 40
int Y,X,T,P,Q[W*W],D[]={-W,-1,1,W};char B[W*W],K[W*W],I[W];
t(x,d,s){for(P=0;B[x];x*=x!=*Q)s-=K[Q[P++]=x]-1,
d=(54202126527627840ll>>2*(d*7+B[x+=D[d]]%8))&3;return x?0:s;}
m(x){int c=K[x],u=B[x-W],U=u&7,l=B[x-1],L=l&7,r=0,
i=U!=3&U!=4&L!=2&L!=4,o=(39>>U)&1?57:70;o&=(52>>L)&1?42:85;
if(x/W>Y+1){for(;P--;)printf("%d %d ",Q[P]%W-1,Q[P]/W-1);exit(0);}
if(u>7)o&=U>4?~64:~6;if(l>7)o&=L>4?~32:~10;
for(o&=c?c>1?c>2?(r=8*i,96):(r=8,i*30):~0:1;o;r++,o/=2)
if(o&1)if(B[x]=r,r%8!=1||!t(x,0,T))m(x+1);B[x]=0;}
main(){for(;gets(I);Y++)for(X=0;I[X];X++)
T+=(K[X+1+Y*W+W]=I[X]/36)-1;m(W);}

나를 테스트 하십시오 .

보다 어려운 테스트 사례는 다음과 같습니다.

.b.....b.b.......b..
.....w.....b.w....w.
....w.........w.....
..bb.....w.w.b....b.
.w.....b..b......w..
.....b..............
.b..........b.b..bw.
....w....w....b...w.
.......bb...b...w...
..b.......w.........
....b.w.....w.b...b.
w...b...w..b.w.w....
b.w....w............
...b.w......b..b...b
w......w.b.ww.......
.b....b..........b..
....b....w.bb.w...w.
w..b......w...b.....
b.....w.........w...
...b....w..w..b...w.
...................b
.b..w..bb.b..b..w...
........w......b....
b....w......b..b.b..
...b..bb.w.w........
...b.......w......w.
w...w.b.w.....b....b
............w..ww...
..b.b..b....b.......
....b.........w...b.
.ww.......b.w.w.....
b.....w..w.w...b....
....ww..b.b.w....w.w
.............bb..w..
.b....w.b.b........w
....bw..........b...

코드가 실행 초기에 솔루션을 매우 일찍 발견 한 것은 운이 좋았지 만 (<5 분) 전체 검색에 훨씬 더 오래 걸립니다 (67 분).

20x36


s /
Bruute

9

파이썬-1669

여전히 꽤 길지만 컴퓨터에서 1 초 안에 마지막 예제를 실행할만큼 빠릅니다. 속도를 줄이면 더 짧아 질 수는 있지만 지금은 ungolfed 코드와 거의 같습니다.

마지막 테스트 사례에 대한 예제 출력 :

0 11 1 11 2 11 3 11 4 11 4 10 3 10 2 10 1 10 1 9 2 9 3 9 4 9 4 8 3 8 3 7 4 7 5 7 5 6 5 5 6 5 6 6 6 7 7 7 8 7 8 8 7 8 6 8 5 8 5 9 5 10 5 11 6 11 6 10 6 9 7 9 8 9 8 10 7 10 7 11 8 11 9 11 9 10 9 9 10 9 10 10 10 11 11 11 11 10 11 9 11 8 11 7 10 7 10 8 9 8 9 7 9 6 10 6 11 6 11 5 11 4 11 3 10 3 9 3 9 4 9 5 8 5 8 4 8 3 8 2 8 1 9 1 10 1 10 0 9 0 8 0 7 0 7 1 7 2 6 2 5 2 5 1 6 1 6 0 5 0 4 0 3 0 2 0 2 1 3 1 4 1 4 2 4 3 5 3 6 3 7 3 7 4 6 4 5 4 4 4 4 5 4 6 3 6 3 5 3 4 3 3 3 2 2 2 2 3 1 3 1 2 1 1 1 0 0 0 0 1 0 2 0 3 0 4 0 5 0 6 1 6 1 5 1 4 2 4 2 5 2 6 2 7 1 7 1 8 0 8 0 9 0 10

여기에 이미지 설명을 입력하십시오

암호:

I=raw_input().split('\n');X=len(I[0]);Y=len(I);R=range
def S(g=0,c=0,x=0,y=0):
    if y>=Y:return 0
    if g==0:g=[[-1]*X for i in R(Y)];c=[[-1]*X for i in R(Y)]
    o={'.':set(R(7)),'w':{1,2},'b':{3,4,5,6}}[I[y][x]].copy()
    o&={0,1,3,4}if y<1 or g[y-1][x]in[0,1,5,6]else{2,5,6}
    o&={0,2,4,5}if x<1 or g[y][x-1]in[0,2,3,6]else{1,3,6}
    if y>Y-2:o&={0,1,5,6}
    if x>X-2:o&={0,2,3,6}
    if y>0 and g[y-1][x]in[2,3,4]:
        if'b'==I[y][x]and g[y-1][x]!=2:return 0
        if'b'==I[y-1][x]:o&={2}
        elif'w'==I[y-1][x]and g[y-2][x]==2:o&={5,6}
    if x>0 and g[y][x-1]in[1,4,5]:
        if'b'==I[y][x]and g[y][x-1]!=1:return 0
        if'b'==I[y][x-1]:o&={1}
        elif'w'==I[y][x-1]and g[y][x-2]==1:o&={3,6}
    h=[r[:]for r in c]
    if y>0 and g[y-1][x]in[2,3,4]:
        if x>0 and g[y][x-1]in[1,4,5]:
            if c[y-1][x]==c[y][x-1]:
                if(6 not in o)+any(any(i!=c[y-1][x]and i!=-1 for i in r)for r in c)+any(I[v][u]!='.'and(v>y)+(u>x)for v in R(y,Y)for u in R(X)):return 0
                g[y][x]=6
                for v in R(y,Y):
                    for u in R(X):
                        if v!=y or u>x:g[v][u]=0
                for y in R(Y):
                    for x in R(X):
                        if g[y][x]>0:break
                f=[];d=-1;u,v=p,q=x,y
                while(u,v)!=(p,q)or-1==d:f+=[u,v];d=([0,{0,2},{1,3},{2,3},{0,3},{0,1},{1,2}][g[v][u]]-{(d+2)%4}).pop();i,j={0:(u+1,v),1:(u,v-1),2:(u-1,v),3:(u,v+1)}[d];u,v=i,j
                return f
            else:
                for v in R(y+1):
                    for u in R(X):
                        if h[v][u]==c[y][x-1]:h[v][u]=c[y-1][x]
                h[y][x]=c[y-1][x]
        else:h[y][x]=c[y-1][x]
    elif x>0 and g[y][x-1]in[1,4,5]:h[y][x]=c[y][x-1]
    else:h[y][x]=max(max(r)for r in c)+1
    for n in sorted(list(o))[::-1]:
        if n==0:h[y][x]=-1
        if x>X-2:i,j=0,y+1
        else:i,j=x+1,y
        g[y][x]=n;r=S(g,h,i,j)
        if r!=0:return r
    return 0
for i in S():print i,

언 골프 드 :

class Grid:
    def __init__(self,input):
        self.input = input.split('\n')
        self.x = len(self.input[0])
        self.y = len(self.input)
        self.options = {'.':{0,1,2,3,4,5,6},'w':{1,2},'b':{3,4,5,6}}

    def convert(self,grid):
        directions = [None,{0,2},{1,3},{2,3},{0,3},{0,1},{1,2}]

        for y in range(self.y):
            for x in range(self.x):
                if grid[y][x] != 0:
                    break

        chain = []
        start_pos = (x,y)
        dir = -1
        pos = start_pos
        while dir == -1 or pos != start_pos:
            chain.extend(pos)
            x,y = pos
            next_dir = (directions[grid[y][x]]-{(dir+2)%4}).pop()
            if next_dir == 0: nx,ny = x+1,y
            elif next_dir == 1: nx,ny = x,y-1
            elif next_dir == 2: nx,ny = x-1,y
            elif next_dir == 3: nx,ny = x,y+1
            dir = next_dir
            pos = (nx,ny)

        return chain

    def solve(self,grid=None,chain_ids=None,pos=(0,0)):
        x,y = pos
        if y >= self.y:
            return None

        if grid is None:
            grid = [[-1]*self.x for i in range(self.y)]
        if chain_ids is None:
            chain_ids = [[-1]*self.x for i in range(self.y)]

        options = self.options[self.input[y][x]].copy()
        if y == 0 or grid[y-1][x] in [0,1,5,6]:
            options &= {0,1,3,4}
        else:
            options &= {2,5,6}
        if y == self.y-1:
            options &= {0,1,5,6}

        if x == 0 or grid[y][x-1] in [0,2,3,6]:
            options &= {0,2,4,5}
        else:
            options &= {1,3,6}
        if x == self.x-1:
            options &= {0,2,3,6}

        if y != 0 and grid[y-1][x] in [2,3,4]:
            if self.input[y][x] == 'b' and grid[y-1][x] != 2:
                return None
            if self.input[y-1][x] == 'b':
                options &= {2}
            elif self.input[y-1][x] == 'w':
                if grid[y-2][x] == 2:
                    options &= {5,6}
        if x != 0 and grid[y][x-1] in [1,4,5]:
            if self.input[y][x] == 'b' and grid[y][x-1] != 1:
                return None
            if self.input[y][x-1] == 'b':
                options &= {1}
            elif self.input[y][x-1] == 'w':
                if grid[y][x-2] == 1:
                    options &= {3,6}


        new_chain_ids = [[i for i in row] for row in chain_ids]
        if y != 0 and grid[y-1][x] in [2,3,4]:
            if x != 0 and grid[y][x-1] in [1,4,5]:

                if chain_ids[y-1][x] == chain_ids[y][x-1]:
                    if 6 not in options:
                        return None

                    if any(any(i != chain_ids[y-1][x] and i != -1 for i in row) for row in chain_ids) or \
                    any(self.input[v][u] != '.' and (v!=y or u>x) for v in range(y,self.y) for u in range(self.x)):
                        return None

                    grid[y][x] = 6
                    for v in range(y,self.y):
                        for u in range(self.x):
                            if v != y or u > x: 
                                grid[v][u] = 0

                    return self.convert(grid)

                else:
                    for v in range(y+1):
                        for u in range(self.x):
                            if new_chain_ids[v][u] == chain_ids[y][x-1]:
                                new_chain_ids[v][u] = chain_ids[y-1][x]
                    new_chain_ids[y][x] = chain_ids[y-1][x]

            else:
                new_chain_ids[y][x] = chain_ids[y-1][x]
        elif x != 0 and grid[y][x-1] in [1,4,5]:
            new_chain_ids[y][x] = chain_ids[y][x-1]
        else:
            new_chain_ids[y][x] = max(max(row) for row in chain_ids)+1

        for n in sorted(list(options),key=lambda n: -n):
            grid[y][x] = n
            if n == 0:
                new_chain_ids[y][x] = -1

            if x == self.x-1:
                nx,ny = 0,y+1
            else:
                nx,ny = x+1,y

            result = self.solve(grid,new_chain_ids,(nx,ny))
            if result is not None:
                return result

input = """

.....w.b.w..
ww..b...b...
.w.....b....
...wbww..b.b
....b.......
w.w.........
..w......b.b
.....bb.....
.....b.....w
w.ww..b.....
...w......w.
b..w.....b..

""".strip()

def print_grid(grid):
    for y,row in enumerate(grid):
        s = ""
        for i in row:
            s += {-1:'xxx',0:'   ',1:'   ',2:' | ',3:'   ',4:'   ',5:' | ',6:' | '}[i]
        s += '\n'
        for x,i in enumerate(row):
            s += {-1:'x%sx',0:' %s ',1:'-%s-',2:' %s ',3:'-%s ',4:' %s-',5:' %s-',6:'-%s '}[i] % input.split('\n')[y][x]
        s += '\n'
        for i in row:
            s += {-1:'xxx',0:'   ',1:'   ',2:' | ',3:' | ',4:' | ',5:'   ',6:'   '}[i]
        s += '\n'
        print s

result = Grid(input).solve()
print result

@Geobits 아 규칙을 충분히 읽지 않은 것 같습니다. 내가 옳다고 믿는 업데이트 된 답변
KSab

새로운 길은 나에게 좋아 보인다! +1
Geobits

1

루아, 830 810 765 752 739 729 710

board1과 board2를 정상적으로 실행하지만 board3에서 시간이 걸립니다.

첫 번째 경로 대신 모든 경로를 출력하여 9 바이트를 절약 할 수 있습니다 ...

b={}s={0,0,0}R=table.insert Z=unpack for l in io.lines()do w=#l for i=1,w do
c=({b=1,w=2,['.']=3})[l:sub(i,i)]R(b,c)s[c]=s[c]+1 end end h=#b/w for e=0,w*h-1
do function g(p,d,X,t)local function G(I,r)T={Z(t)}a=b[I+1]T[a]=T[a]+1
P={Z(p)}D={Z(d)}R(P,I%w)R(P,I/w-I/w%1)R(D,r)l=#D for U=2,#p,2 do if
I==p[U-1]+w*p[U]then return end end if I==e then if T[1]==s[1]and T[2]==s[2]then
for k=1,l do K=D[k]M=D[(k-2)%l+1]N=D[k%l+1]O=D[(k+1)%l+1]if({K==N or K~=M or
N~=O,K~=N or(K==M and N==O)})[b[1+P[2*k-1]+w*P[2*k]]]then return end end
os.exit(print(table.concat(P,' ')))end else g(P,D,I,T)end end _=X%w<w-1 and
G(X+1,1)_=X/w-X/w%1<h-1 and G(X+w,2)_=X%w>0 and G(X-1,3)_=X/w-X/w%1>0 and
G(X-w,4)end g({},{},e,{0,0,0})end
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.