diff nono.py @ 7:13f600be3a1b

implemented newBlob and found0, refactoring display
author Henry S. Thompson <ht@inf.ed.ac.uk>
date Wed, 11 Mar 2020 17:13:05 +0000
parents a56d5285575b
children 3276cf6ee6df
line wrap: on
line diff
--- a/nono.py	Tue Mar 10 19:56:07 2020 +0000
+++ b/nono.py	Wed Mar 11 17:13:05 2020 +0000
@@ -28,8 +28,8 @@
     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 <n-1 then self[mN+1].val ditto
     self.runs=self.origRuns=runs
-    self.initialComplete=[]
-    self.finalComplete=[]
+    self.initialComplete=""
+    self.finalComplete=""
     self.resetAllRuns()
 
   def __repr__(self):
@@ -38,6 +38,9 @@
   def __str__(self):
     return '%s|'%('|'.join(str(c) for c in self))
 
+  def myPrintSize(self):
+    return sum(len(str(run)) for run in self.runs)+len(self.runs)-1
+
   def resetAllRuns(self):
     # compute the set of all possible layouts for runs
     self.rn=len(self.runs)
@@ -71,17 +74,26 @@
       dprint('=====pass %s======'%k)
       self.onepass(0,self.n,scratch,runs.copy())
     dprint(scratch)
+    newSeq=False
+    inSeq=False
     for i in range(self.n):
       if scratch[i]==self.nar:
         # If blobby in _every_ pass, then must be a blob
+        if inSeq:
+          newSeq=False
+        else:
+          inSeq=True
+          newSeq=True
         if self[i].val is None:
-          self[i].setVal(True)
+          self.newBlob(i,newSeq)
         elif self[i].val is True:
           # already there
           pass
         else:
           print("Shouldn't happen: attempt to blob where x already present! %s at %s"%(self,i),file=sys.stderr)
           exit(101)
+      else:
+        inSeq=newSeq=False
 
   def onepass(self,i0,iBound,scratch,stack):
     """note that stack is not a simple run, but one with _negative_ numbers between
@@ -199,7 +211,7 @@
     changed=False
     # First, find our boundaries:
     s=pos # start index of our run
-    while s>self.marginO and self[s-1].val is True:
+    while s>self.margin0 and self[s-1].val is True:
       s-=1
     f=pos # finish index of our run
     while f<self.marginN and self[f+1].val is True:
@@ -213,16 +225,16 @@
     j=self.runs.index(l)
     if j==0:
       # is it safely left marginal, i.e. no blobs or big enough gaps before us?
-      if marginal(range(self.margin0,s)):
+      if self.marginal(range(self.margin0,s),l):
         changed=True
         # mark our margins
-        for i in range(margin0+1,s):
+        for i in range(self.margin0+1,s):
           if self[i].val is None:
             self[i].setVal(False)
-        if f<marginN-1:
+        if f<self.marginN-1:
           if self[f+1].val is None:
             self[f+1].setVal(False)
-            if f<marginN-2 and self[f+2].val is True:
+            if f<self.marginN-2 and self[f+2].val is True:
               dprint('n1')
               self.checkNew(f+2) # I think@@
         self.found0(f) # pull in the start margin at least to f+2
@@ -231,13 +243,13 @@
         if self.marginal(range(self.marginN-1,r,-1),l):
           changed=True
           # mark our margins
-          for i in range(marginN-1,f,-1):
+          for i in range(self.marginN-1,f,-1):
             if self[i].val is None:
               self[i].setVal(False)
-          if s>margin0+1:
+          if s>self.margin0+1:
             if self[s-1].val is None:
               self[s-1].setVal(False)
-              if s>margin0+2 and self[s-2].val is True:
+              if s>self.margin0+2 and self[s-2].val is True:
                 dprint('n2')
                 self.checkNew(s-2) # I think@@
           self.foundN(s) # pull in the finish margin at least to s-2
@@ -258,29 +270,59 @@
           return False
     return True
 
+  def found0(self,i):
+    dprint('found0 called on %s at %s'%(self,i))
+    i=self.margin0
+    while self[i].val is False:
+      i+=1
+    if self[i].val is True:
+      r=self.runs.pop(0)
+      self.initialComplete+=(RedFmt%r)
+      self.margin0+=r+1
+
+  def foundN(self,i):
+    print('foundN called on %s at %s'%(self,i),file=sys.stderr)
+
 class Row(Vector):
-  def __init__(self,n,m,runs,pos,dprintWidth):
+  def __init__(self,n,m,runs,pos):
     Vector.__init__(self,n,m,runs)
     self.y=pos
-    self.dprintWidth=dprintWidth
-    self.fmt="%%%ss|"%dprintWidth
+    self.width=self.myPrintSize()
 
   def __str__(self):
     return ((self.fmt%(' '.join(str(r) for r in self.runs)))+
             Vector.__str__(self))
 
+  def updateHeader(self,maxWidth):
+    self.maxWidth=maxWidth
+    self.fmt="%s%%s|"%(' '*(maxWidth-self.width))
+
+  def newBlob(self,x,newSeq):
+    self[x].setVal(True)
+    self[x].column.checkNew(self.y)
+    if newSeq:
+      # We don't always check ourself, to avoid unnecessary duplication...
+      self.checkNew(x)
+
 class Column(Vector):
-  def __init__(self,n,m,runs,pos,dprintHeight):
+  def __init__(self,n,m,runs,pos):
     Vector.__init__(self,n,m,runs)
     self.x=pos
-    self.dprintHeight=dprintHeight
-    self.fmt="%%%ss"%self.dprintHeight
-    self.updateHeader()
+    self.height=self.myPrintSize()
 
-  def updateHeader(self):
+  def updateHeader(self,maxHeight):
+    self.maxHeight=maxHeight
+    self.fmt="%s%%s"%(' '*(maxHeight - self.height))
     header=('-'.join(str(c) for c in self.runs))
     self.header=self.fmt%header # pad to same 'height'
 
+  def newBlob(self,y,newSeq):
+    self[y].setVal(True)
+    self[y].row.checkNew(self.x)
+    if newSeq:
+      # We don't always check ourself, to avoid unnecessary duplication...
+      self.checkNew(y)
+
 class Cell:
   def __init__(self,row,y,column,x):
     # At the intersection of row and column Vectors
@@ -306,9 +348,6 @@
         # No-op
         return
       self.val=v
-      self.row.checkNew(self.x)
-      self.column.checkNew(self.y)
-      # @@ check row/col completed
     else:
       if self.val is not None:
         print("Warning: %s -> %s at %s,%s"%(self.val,v,self.x,self.y),file=sys.stderr)
@@ -316,26 +355,30 @@
 
 class Nono(dict):
   # 0,0 is upper left, so increasing y goes _downwards_, to match the standard layout
-  def __init__(self,rows,cols):
-    n=self.n=len(cols)
-    if n!=len(rows):
-      print("losing r:%s x c:%s"%(len(rows),n),sys.stderr)
+  def __init__(self,runsPerRow,runsPerCol):
+    n=self.n=len(runsPerCol)
+    if n!=len(runsPerRow):
+      print("losing r:%s x c:%s"%(len(runsPerRow),n),sys.stderr)
       exit(1)
-    self.rc=rows
-    rowDprintWidth=max(sum(len(str(r)) for r in row)+len(row)-1 for row in rows)
-    self.rowfmt="%s|%%s"%(' '*rowDprintWidth)
-    self.cc=cols
-    # dprint col nums>9 vertically :-(
-    self.colDprintHeight=max(sum(len(str(c)) for c in col)+len(col)-1 for col in cols)
-    self.columns=cc=[Column(n,self,cols[i],i,self.colDprintHeight) for i in range(20)]
-    self.rows=rr=[Row(n,self,rows[i],i,rowDprintWidth) for i in range(20)]
+    self.rc=runsPerRow
+    self.cc=runsPerCol
+    # print col nums>9 vertically :-(
+    self.columns=cc=[Column(n,self,runsPerCol[i],i) for i in range(20)]
+    self.maxCRheight=maxCRheight=max(col.height for col in cc)
+    for c in cc:
+      c.updateHeader(maxCRheight)
+    self.rows=rr=[Row(n,self,runsPerRow[i],i) for i in range(20)]
+    maxRRwidth=max(row.width for row in rr)
+    for r in rr:
+      r.updateHeader(maxRRwidth)
+    self.rowfmt="%s|%%s|"%(' '*maxRRwidth)
     for x in range(20):
       for y in range(20):
         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'
-           for j in range(self.colDprintHeight)]
+           for j in range(self.maxCRheight)]
     lines+=[str(r) for r in self.rows]
     return "\n".join(lines)