DFS 求解金字塔10*10等腰直角三角形擺放

# -*- coding:utf8 -*-
shape={
       0:[(0,0),(1,0),(1,1),(1,2)],
       1:[(0,0),(0,1),(1,0),(1,1),(1,2)],
       2:[(0,0),(1,0),(1,1),(1,2),(1,3)],
       3:[(0,1),(1,0),(1,1),(1,2),(1,3)],

       4:[(0,0),(0,1),(1,1),(1,2),(1,3)],
       5:[(0,0),(1,0),(1,1)],
       6:[(0,0),(1,0),(2,0),(2,1),(2,2)],
       7:[(0,0),(1,0),(1,1),(2,1),(2,2)],

       8:[(0,0),(0,1),(1,0),(2,0),(2,1)],
       9:[(0,0),(0,1),(0,2),(0,3)],
       10:[(0,0),(1,0),(1,1),(0,1)],
       11:[(1,0),(0,1),(1,1),(1,2),(2,1)],
}
allshape={}
field=[]
prepos=[]

def rotate(v, d):
       ibin=[0]*5
       rv0=max([vi[0] for vi in v])
       rv1=max([vi[1] for vi in v])
       dd=d/4
       d%=4
       ta= 1 if d<2 else -1
       tb= -1 if (d%2)==1 else 1
       for vi in v:
              v0= vi[0] if ta>0 else (rv0+vi[0]*ta)
              v1= vi[1] if tb>0 else (rv1+vi[1]*tb)
              v0,v1 = (v1,v0) if dd==1 else (v0,v1)
              ibin[v1] |= (1<<v0)

       vmap=reduce(lambda x,y: x|y, ibin)
       rot=0
       while vmap&(1<<rot)==0:
              rot+=1
       if rot>0:
              ibin=map(lambda x:x<<1, ibin)

       trim=0
       if ibin[trim]==0:
              trim+=1
       ibin=ibin[trim:]
       trim=0
       while trim<len(ibin) and ibin[trim]!=0:
              trim+=1
       return tuple(ibin[:trim])

def init():
       for k,v in shape.items():
              allshape[k]=set()
              for d in xrange(8):
                     ret=rotate(v, d)
                     allshape[k].add(ret)
class bcolors:
       block=['\033[91m','\033[92m','\033[93m','\033[94m','\033[95m',
              '\033[96m','\033[97m','\033[98m','\033[99m','\033[100m',
              '\033[90m','\033[89m' ]
       ENDC = '\033[0m'
       BOLD = '\033[1m'
       UNDERLINE = '\033[4m'

def dump(binmap, info, pos):
       print info
       print "^^"*5
       for b in binmap:
              print str(bin(b))[2:]
       print "**"*5
import unicodedata
def dumpput(blocks):
       fields=[' '*10]*10
       binfield=[0]*10
       for i,b in enumerate(blocks):
              for y,c in enumerate(b[0]):
                     binfield[b[2]+y]|=c<<b[1]
                     pos=0
                     while c>0:
                            if c&1 == 1:
                                   fields[b[2]+y] = fields[b[2]+y][:pos+b[1]] +  chr(ord('a')+i) + fields[b[2]+y][pos+b[1]+1:]
                            pos+=1
                            c>>=1
       for col,f in enumerate(fields):
              f=f[:col+1]
              for i in xrange(12):
                     f=f.replace(chr(ord('a')+i), ["❤️","🧡","💛","💚","💙","💜","🖤","💗","💓","💕","💝","💘"][i])
              f=f.replace(' ','⭕')
              print f
       #
       # print "----"*4
       #
       # for f in binfield:
       #        print bin(f)[2:]
       print "===="*4
def addoneshape(target, current, used, shapeid, shape, pos):
       pass

def rmoneshape(current, used, shapeid, shape):
       pass

def tryfeed(targetmap, ks):
       feed=[0]*10
       check1=[0]*10
       check2=[0]*10
       bakcheck=[0]*10
       for i,onek in enumerate(ks):
           block=onek[0]
           x0=onek[1]
           y0=onek[2]
           for y,b in enumerate(block):
                  if y0+y>=10: return False
                  feed[y0+y] |= b<<x0
                  if i&1 == 0:
                      check1[y0+y] |= b<<x0
                      check2[y0+y] &= b<<x0
                  else:
                      check1[y0+y] &= b<<x0
                      check2[y0+y] |= b<<x0
           if i&1==0:
                  if check2!=bakcheck:
                         return False
           else:
                  if check1!=bakcheck:
                         return False
       if feed==targetmap:
           return True
       print feed
       return False
       
def checkfeed(target, feed, failedpos):
    cnt=0
    for f in feed:
           cnt+=1
           if cnt%1000000 == 0:
                 print cnt
           if tryfeed(target, f):
                  print f
    return None

import itertools
maxdeep=0
def findans():
       targetfield=[]
       for i in xrange(0,10):
              targetfield.append(((1<<(i+1))-1))

       allshapes = allshape.values()
       print "try......", targetfield
       def putoneblock(targetfield, shapes, putblock):
              global maxdeep
              if len(shapes) == 0:
                     print putblock
                     return True
              if len(putblock)>maxdeep:
                     maxdeep=len(putblock)
                     if maxdeep>=10:
                            print putblock
                            dumpput(putblock)

                     print "deep:",maxdeep
              for s in shapes[0]:
                     for x in xrange(10):
                            for y in xrange(10):
                                   backfield=targetfield[:]
                                   passput=False
                                   for ybase,sc in enumerate(s):
                                          if y+ybase>=10:
                                                 passput=True
                                                 break
                                          checkv=targetfield[y+ybase]
                                          targetfield[y+ybase]^=sc<<x
                                          if checkv!=(targetfield[y+ybase]|sc<<x):
                                                 passput=True
                                                 break
                                   if passput:
                                          targetfield=backfield[:]
                                          continue
                                   putblock.append((s,x,y))
                                   putoneblock(targetfield, shapes[1:], putblock[:])
                                   del putblock[-1]
                                   targetfield=backfield[:]
              return False

       putoneblock(targetfield, allshapes, [])
       # ips=[]
       # for ip in allshape.values():
       #        ips.append(itertools.product(ip, range(10), range(10)))
       #
       # putpos=itertools.product(*ips)

       # ret=checkfeed(targetfield, putpos, failedpos)
       # return ret

init()
findans()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章