สร้อยคอไข่มุก


18

ภาพรวม

Pearls (หรือ Masyu)เป็นเกมลอจิกที่เล่นบนกริด มีไข่มุกสีดำและสีขาววางอยู่บนตาราง วัตถุคือการสร้างวงปิดเดี่ยวที่เดินทางผ่านแต่ละมุกโดยใช้เฉพาะส่วนของเส้นตรงและมุมฉาก

มีกฎบางอย่างที่ควบคุมว่าลูปโต้ตอบกับไข่มุกอย่างไร:

  • ไข่มุกสีขาวจะต้องเดินทางตรงผ่าน แต่ห่วงจะต้องเปิดในก่อนหน้านี้และ / หรือเซลล์ถัดไปในเส้นทางของมัน
  • ไข่มุกดำจะต้องหันเมื่อ แต่ห่วงจะต้องเดินทางตรงผ่านต่อไปและเซลล์ก่อนหน้าในเส้นทางของมัน
  • การวนซ้ำต้องไม่ข้ามหรือตัดกันเอง เซลล์ทั้งหมดมีการวนเข้า / ออกจากศูนย์หรือสองอย่างแน่นอน

ตัวอย่างปริศนาจาก 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, 590 640 760 880 963 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 / Brute force ค่อนข้างเร็ว / C ค่อนข้างเร็ว /
kirbyfan64sos

9

Python - 1669

ยังค่อนข้างยาว แต่เร็วพอที่จะเรียกใช้ตัวอย่างล่าสุดได้ในไม่กี่วินาทีบนคอมพิวเตอร์ของฉัน อาจเป็นไปได้ที่จะทำให้ความเร็วในการใช้งานสั้นลง แต่ตอนนี้มันใกล้เคียงกับโค้ดที่ไม่ได้รับการดัดแปลง

ตัวอย่างผลลัพธ์สำหรับกรณีทดสอบล่าสุด:

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,

Ungolfed:

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

รันบอร์ด 1 และบอร์ด 2 ได้ดี แต่ใช้เวลาสักครู่บนบอร์ด 3

มันสามารถบันทึก 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.