apiad

Untitled

Feb 28th, 2022
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.69 KB | None | 0 0
  1. import argparse
  2. import random
  3. import math
  4. import sys
  5. import subprocess
  6.  
  7. import cspuz
  8. from cspuz import Solver, BoolGridFrame, graph
  9. from cspuz.constraints import count_true, fold_or
  10. from cspuz.puzzle import util
  11.  
  12. def solve_curve_data(height, width, *problem):
  13.     solver = Solver()
  14.     grid_frame = BoolGridFrame(solver, height - 1, width - 1)
  15.     solver.add_answer_key(grid_frame)
  16.     clue = problem[0]
  17.     border = problem[1]
  18.     for p in border:
  19.         solver.ensure(~grid_frame[p[0][0]+p[1][0],p[0][1]+p[1][1]])
  20.     is_sat = solver.solve()
  21.     cnthor=0
  22.     cntver=0
  23.     for i in range(height):
  24.         for j in range(width):
  25.             adj = []
  26.             if i > 0: adj.append(grid_frame[i*2-1,j*2])
  27.             if j > 0: adj.append(grid_frame[i*2,j*2-1])
  28.             if i + 1 < height: adj.append(grid_frame[i*2+1,j*2])
  29.             if j +1  < width : adj.append(grid_frame[i*2,j*2+1])
  30.             if clue[i][j]!=(-1,):
  31.                 solver.ensure(fold_or(adj))
  32.                 if clue[i][j]!=None:
  33.                     for c in clue[i][j][1]:
  34.                         if c[0]==0:
  35.                             cnthor+=1
  36.                         else:  
  37.                             cntver+=1
  38.             else:
  39.                 solver.ensure(~fold_or(adj))
  40.     horid=solver.int_array((height, width-1), 0,cnthor)
  41.     verid=solver.int_array((height-1, width), 0,cntver)
  42.     for i in range(height):
  43.         for j in range(width):
  44.             if i+1<height:
  45.                 solver.ensure(grid_frame[2*i+1,2*j] == (verid[i,j]!=0))
  46.             if j+1<width:
  47.                 solver.ensure(grid_frame[2*i,2*j+1] == (horid[i,j]!=0))
  48.     phor=0
  49.     pver=0
  50.     bs=[]
  51.     def addmatch(x,y,ps):
  52.         ee=[0,0,0,0]
  53.         if y+1<width:
  54.             ee[0]=horid[x][y]
  55.         if x+1<height:
  56.             ee[1]=verid[x][y]
  57.         if y>0:
  58.             ee[2]=horid[x][y-1]
  59.         if x>0:
  60.             ee[3]=verid[x-1][y]
  61.         cond=[]
  62.         for ff in ps:
  63.             cond.append((ee[0]==ff[0])&(ee[1]==ff[1])&(ee[2]==ff[2])&(ee[3]==ff[3]))
  64.         solver.ensure(fold_or(cond))
  65.     for i in range(height):
  66.         for j in range(width):
  67.             if clue[i][j]!=(-1,) and clue[i][j]!=None:
  68.                 qs=[]
  69.                 n=clue[i][j][0]
  70.                 seg=clue[i][j][1]
  71.                 segid=[-1]*(len(seg))
  72.                 chor=0
  73.                 cver=0
  74.                 for (k,c) in enumerate(seg):
  75.                     if c[0]==0:
  76.                         chor+=1
  77.                         segid[k]=chor+phor
  78.                         bs.append((segid[k],0,segid[k],0))
  79.                         qs.append((segid[k],0,segid[k],0))
  80.                     else:
  81.                         cver+=1
  82.                         segid[k]=cver+pver
  83.                         bs.append((0,segid[k],0,segid[k]))
  84.                         qs.append((0,segid[k],0,segid[k]))
  85.                 for z in range(n):
  86.                     ss=[0,0,0,0]
  87.                     for (k,c) in enumerate(seg):
  88.                         if c[0]==0 and c[1]==z:
  89.                             ss[0]=segid[k]
  90.                         if c[0]==0 and c[2]==z:
  91.                             ss[2]=segid[k]
  92.                         if c[0]==1 and c[1]==z:
  93.                             ss[1]=segid[k]
  94.                         if c[0]==1 and c[2]==z:
  95.                             ss[3]=segid[k]
  96.                     bs.append(ss)
  97.                     qs.append(ss)
  98.                 gs = BoolGridFrame(solver, height - 1, width - 1)
  99.                 for y in range(height):
  100.                     for x in range(width):
  101.                         if y + 1 < height:
  102.                             solver.ensure(gs[2 * y + 1, 2 * x] == ((verid[y, x]>pver) & (verid[y, x]<=pver+cver)))
  103.                         if x + 1 < width:
  104.                             solver.ensure(gs[2 * y, 2 * x + 1] == ((horid[y, x]>phor) & (horid[y, x]<=phor+chor)))
  105.                 graph.active_edges_connected(solver, gs)
  106.                 phor+=chor
  107.                 pver+=cver
  108.                 addmatch(i,j,qs)
  109.  
  110.     for i in range(height):
  111.         for j in range(width):
  112.             if clue[i][j]==None:
  113.                 addmatch(i,j,bs)
  114.     is_sat = solver.solve()
  115.     return is_sat, grid_frame
  116.  
  117.  
  118.  
  119. def convertborder(border, height, width):
  120.     banpair=[]
  121.     if border!=None:
  122.         vb=[]
  123.         for i in range(height):
  124.             for j in range(1,width):
  125.                 vb.append((i,j))
  126.         while len(vb)%5!=0:
  127.             vb.append((-1,-1))
  128.         t=0
  129.         for i in range(0,len(vb),5):
  130.             ch=border[t]
  131.             num=0
  132.             if ord(ch)<=ord('9'):
  133.                 num=ord(ch)-ord('0')
  134.             else:
  135.                 num=ord(ch)-ord('a')+10
  136.             for k in range(5):
  137.                 if vb[i+k]!=(-1,-1) and (num>>(4-k))&1:
  138.                     banpair.append([(vb[i+k][0],vb[i+k][1]-1),(vb[i+k][0],vb[i+k][1])])
  139.             t+=1
  140.         vb=[]
  141.         for i in range(1,height):
  142.             for j in range(width):
  143.                 vb.append((i,j))
  144.         while len(vb)%5!=0:
  145.             vb.append((-1,-1))
  146.         for i in range(0,len(vb),5):
  147.             ch=border[t]
  148.             num=0
  149.             if ord(ch)<=ord('9'):
  150.                 num=ord(ch)-ord('0')
  151.             else:
  152.                 num=ord(ch)-ord('a')+10
  153.             for k in range(5):
  154.                 if vb[i+k]!=(-1,-1) and (num>>(4-k))&1:
  155.                     banpair.append([(vb[i+k][0]-1,vb[i+k][1]),(vb[i+k][0],vb[i+k][1])])
  156.             t+=1
  157.     return banpair
  158.  
  159. def tonum(w):
  160.     if ord(w) <= ord('9') and ord(w)>=ord('0'):
  161.         return ord(w) - ord('0')
  162.     elif ord(w) <= ord('f') and ord(w) >= ord('a'):
  163.         return ord(w) - ord('a') + 10
  164.     else:
  165.         assert False
  166.  
  167. def decodeshape(h,w,code):
  168.     bits=[0]*(h*w)
  169.     l=h*w
  170.     for i in range(0,l-1,2):
  171.         num=tonum(code[i//2])
  172.         bits[i]=num&3
  173.         bits[i+1]=(num&12)>>2
  174.     for id in range(l):
  175.         x=id%w
  176.         y=id//w
  177.         if x > 0 and (bits[y * w + x - 1] & 1):
  178.             bits[id]|=4
  179.         if y > 0 and (bits[(y - 1) * w + x] & 2):
  180.             bits[id]|=8
  181.     nid=[-1]*(h*w)
  182.     seg=[]
  183.     cnt=0
  184.     for id in range(l):
  185.         if not bits[id] in [0,5,10]:
  186.             nid[id]=cnt
  187.             cnt+=1
  188.     for id in range(l):
  189.         if nid[id]==-1:
  190.             continue
  191.         if bits[id]&1:
  192.             y=id+1
  193.             while nid[y]==-1:
  194.                 y+=1
  195.             seg.append((0,nid[id],nid[y]))
  196.         if bits[id]&2:
  197.             y=id+w
  198.             while nid[y]==-1:
  199.                 y+=w
  200.             seg.append((1,nid[id],nid[y]))
  201.     return (cnt,seg)
  202.  
  203. def convert(url):
  204.     part = url.split("curvedata")[1].split("/")[1:]
  205.     if part[0]=="v:":
  206.         part=part[1:]
  207.     width = int(part[0])
  208.     height = int(part[1])
  209.     code = part[2]
  210.     part = part[3:]
  211.     border=[]
  212.     while len(part)!=0 and part[0]=="":
  213.         part = part[1:]
  214.     if len(part)>0 and part[0][0]=='b':
  215.         border = convertborder(part[0][1:], height, width)
  216.         part=part[1:]
  217.     assert(len(part)%3==0)
  218.     pclue =[]
  219.     for i in range(0,len(part),3):
  220.         w = int(part[i])
  221.         h = int(part[i+1])
  222.         pclue.append(decodeshape(h, w, part[i+2]))
  223.    
  224.     clue = [[None for j in range(width)] for i in range(height)]
  225.     def nextpos(px, py):
  226.         return px + (py + 1) // width , (py + 1) % width
  227.     l = 0
  228.     px = 0
  229.     py = 0
  230.     while l < len(code):
  231.         if ord(code[l])>=ord('g') and ord(code[l])<=ord('z'):
  232.             for k in range(ord(code[l])-ord('g')):
  233.                 px, py = nextpos(px, py)
  234.         elif code[l]=='=':
  235.             clue[px][py] = (-1, )
  236.         elif code[l]=='.':
  237.             return 0,0,[],[]
  238.         elif code[l]=='-':
  239.             d=tonum(code[l+1])*16+tonum(code[l+2])
  240.             clue[px][py]=pclue[d]
  241.             l+=2
  242.         else:
  243.             d=tonum(code[l])
  244.             clue[px][py]=pclue[d]
  245.         l+=1
  246.         px, py = nextpos(px, py)
  247.     return height, width, clue,border
  248.  
  249. def solve_curve_data_url(url):
  250.     height, width, clue, border = convert(url)
  251.     if height == 0 or width == 0:
  252.         return False, "not supported"
  253.     is_sat, is_line = solve_curve_data(height, width, clue, border)
  254.     return is_sat, is_line
  255.  
  256. def _main():
  257.     if len(sys.argv) == 1:
  258.         url = "https://puzz.link/p?curvedata/14/14/0g1g0g2zn3t4g5g6t7l8n9m4n2man2mcgbgdzzx01h02/3/3/9024/2/3/ba1/1/3/a/3/3/2aa5/3/3/c021/3/3/8430/2/3/b30/2/3/321/2/3/ba0/2/3/330/2/3/2b0/3/3/2630/3/3/bc95/3/3/7c05"
  259.         is_sat, is_line = solve_curve_data_url(url)
  260.         print('has answer:', is_sat)
  261.         if is_sat:
  262.             print(util.stringify_grid_frame(is_line))
  263.             util.draw_grid_frame(is_line)
  264.  
  265. if __name__ == '__main__':
  266.     _main()
  267.  
Advertisement
Add Comment
Please, Sign In to add comment