# HG changeset patch # User Henry Thompson # Date 1685640116 -3600 # Node ID 057b527468502e7aa32c88275f0a183191763be5 # Parent 40273cb7c7fc35a11ea46f814cdee9520d56aaee use Run and Space classes in Vector.runs diff -r 40273cb7c7fc -r 057b52746850 nono.py --- a/nono.py Mon May 29 23:14:59 2023 +0100 +++ b/nono.py Thu Jun 01 18:21:56 2023 +0100 @@ -13,28 +13,69 @@ for vals in zip(*args): yield from vals +class Run: + def __init__(self,n,i,j): + # A run of length n, starting within [i,j] + self.n=n + self.i=i + self.j=j + self.done=False + + def __str__(self): + return str(self.n) + +class Space: + def __init__(self,n,i,j): + # A space of length 1..n, starting within [i,j] + # Once done, length == n + assert n>0 + self.n=n + self.i=i + self.j=j + self.done=False + + def __str__(self): + return '-' + class Vector(list): # reads top-to-bottom or left-to-right - def __init__(self,n,m,runs): + def __init__(self,n,m): list.__init__(self,list(range(n))) self.n=n # size self.m=m # parent NoNo self.margin0=0 # a run can start here, so if >0 then self[m0-1].val must be False self.marginN=n-1 # a run can end here, so if space: + for p in range(p+space,p+run): + self[p].setVal(True) + p+=1 + else: + p+=run + p+=1 class Row(Vector): cLet='R' - def __init__(self,n,m,runs,pos): - Vector.__init__(self,n,m,runs) + def __init__(self,n,m,pos): + Vector.__init__(self,n,m) self.y=pos + + def initDisp(self): self.width=self.myPrintSize() def __str__(self): @@ -371,24 +427,12 @@ class Column(Vector): cLet='C' - def __init__(self,n,m,runs,pos): - Vector.__init__(self,n,m,runs) + def __init__(self,n,m,pos): + Vector.__init__(self,n,m) self.x=pos - self.height=self.myPrintSize() -#=============new simple============ - def pass0(self): - need=sum(1+self.runs[k] for k in range(self.rn))-1 - space=self.n-need - p=0 - for run in self.runs: - if run>space: - for p in range(p+space,p+run): - self[p].setVal(True) - p+=1 - else: - p+=run - p+=1 + def initDisp(self): + self.height=self.myPrintSize() def updateHeader(self,*,maxHeight=None,r=None,pre=None): dprint('CuH',r,pre) @@ -454,18 +498,14 @@ return ' ' if self.val is None else ('\u25A0' if self.val else 'x') def setVal(self,v): - if v is True: - if self.val is False: - wprint("Warning: x -> * at %s,%s"%(self.x,self.y)) - elif self.val is True: - # No-op - return - self.val=v - else: - if self.val is not None: - wprint("Warning: %s -> %s at %s,%s"%(self.val,v,self.x,self.y)) - self.val=v - + # Returns true iff old value was None + assert v in (True, False) + if v == self.val: + return False + if self.val is not None: + eprint("Reset not allowed: %s -> %s at %s,%s"%(self.val, v, self.x,self.y),err=103) + self.val=v + return True class Nono(dict): # 0,0 is upper left, so increasing y goes _downwards_, to match the standard layout @@ -482,18 +522,24 @@ self.rc=runsPerRow self.cc=runsPerCol # print col nums>9 vertically :-( - self.columns=cc=[Column(n,self,runsPerCol[i],i) for i in range(n)] + self.columns=cc=[Column(n,self,i) for i in range(n)] + self.rows=rr=[Row(n,self,i) for i in range(n)] + for x in range(n): + for y in range(n): + self[(x,y)]=Cell(rr[y],y,cc[x],x) + # Need cells in place for the following + for row,runs in zip(rr,runsPerRow): + row.initRuns(runs) + for col,runs in zip(cc,runsPerCol): + col.initRuns(runs) self.maxCRheight=maxCRheight=max(col.height for col in cc) for c in cc: c.updateHeader(maxHeight=maxCRheight) - self.rows=rr=[Row(n,self,runsPerRow[i],i) for i in range(n)] maxRRwidth=max(row.width for row in rr) for r in rr: r.updateHeader(maxWidth=maxRRwidth) self.rowfmt="%s|%%s|"%(' '*maxRRwidth) - for x in range(n): - for y in range(n): - self[(x,y)]=Cell(rr[y],y,cc[x],x) + def __str__(self): lines=[self.rowfmt%('|'.join([(self.columns[i]).header[j] for i in range(self.n)])) # 'rotate' @@ -505,6 +551,8 @@ def pass0(self): # do columns of empty layout for c in self.columns: c.pass0() + for r in self.rows: + r.pass0() def solve(self): self.pass0() @@ -561,5 +609,6 @@ rows=[[int(i) for i in v.split('.')] for v in vv[n:]] solver=Nono(rows,cols) + breakpoint() solver.solve()