comparison nono.py @ 74:0245bc07f16c simple

try to simplify Rows/Cols (do without?) by hiving off the run-counts copletely
author Henry Thompson <ht@markup.co.uk>
date Sat, 09 Aug 2025 15:59:19 -0400
parents 63e87db2bc31
children
comparison
equal deleted inserted replaced
73:63e87db2bc31 74:0245bc07f16c
8 # sum(len(rn) for rn in rows U cols) 8 # sum(len(rn) for rn in rows U cols)
9 # My own strategy seems to be FIFO for pass 0, then LIFO, for the queue of new/changed runs 9 # My own strategy seems to be FIFO for pass 0, then LIFO, for the queue of new/changed runs
10 # By cases, wrt types of change of a cell in its runs 10 # By cases, wrt types of change of a cell in its runs
11 # Change at the margin: 11 # Change at the margin:
12 # New fill: complete the run and discard it, kill the other end and queue it 12 # New fill: complete the run and discard it, kill the other end and queue it
13 # dead: advance margin and add fill to any internal sequences of fills (always?), queue the new fill(s) 13 # dead: advance margin and append a new fill to any internal sequences of fills (always?), queue the new fill(s)
14 # Change in the middle 14 # Change in the middle
15 # New dead: If deterministic, split the run in two and requeue the cell (now in two runs) 15 # New dead: If deterministic, split the run in two and requeue the cell (now in two runs)
16 # fill: If deterministic single gap at any end, kill, split, and requeue the cell (now in two runs) 16 # fill: If deterministic single gap at any end, kill, split, and requeue the cell (now in two runs)
17 # ---------- 17 # ----------
18 # Doesn't yet cover everything, e.g. killing gaps that are too small to be filled 18 # Doesn't yet cover everything, e.g. killing gaps that are too small to be filled
19 # Do we need to actually represent run-internal segments, e.g. skips and bars? 19 # Do we need to actually represent run-internal segments, e.g. skips and bars?
20 20
21 # Hypothesis: we only need Columns and Rows for printing
21 22
22 import sys 23 import sys
23 24
24 Red = "" 25 Red = ""
25 eRed = "" 26 eRed = ""
26 RedFmt = Red + "%s" + eRed 27 RedFmt = Red + "%s" + eRed
27 28
28 29
29 class Run: 30 class Run:
30 '''What we're looking for, converted eventually into what 31 '''What we're looking for, converted eventually into what we've found.
31 we've found.
32 "left" and "right" make sense for Rows, for Columns read "above" and "below"''' 32 "left" and "right" make sense for Rows, for Columns read "above" and "below"'''
33 33
34 def __init__(self, n, i, j): 34 def __init__(self, n, i, j):
35 # A run of length n, starting within [i,j] 35 # A run of length n, starting within [i,j]
36 self.n = n 36 self.n = n
71 return "" 71 return ""
72 72
73 73
74 class Vector(list): 74 class Vector(list):
75 # reads top-to-bottom or left-to-right 75 # reads top-to-bottom or left-to-right
76 def __init__(self, n, m): 76 def __init__(self, m, left, right):
77 self.n = n = (left.x - right.x) + 1 # size
77 list.__init__(self, list(range(n))) 78 list.__init__(self, list(range(n)))
78 self.n = n # size
79 self.m = m # parent NoNo 79 self.m = m # parent NoNo
80 self.margin0 = 0 # a run can start here, so if >0 then self[m0-1].val must be False 80 self.margin0 = 0 # a run can start here, so if >0 then self[m0-1].val must be False
81 self.marginN = n - 1 # a run can end here, so if <n-1 then self[mN+1].val ditto 81 self.marginN = n - 1 # a run can end here, so if <n-1 then self[mN+1].val ditto
82 82
83 def initRuns(self, runs): 83 def initRuns(self, runs):
194 194
195 195
196 class Row(Vector): 196 class Row(Vector):
197 cLet = "R" 197 cLet = "R"
198 198
199 def __init__(self, n, m, pos): 199 def __init__(self, m, left, right):
200 Vector.__init__(self, n, m) 200 Vector.__init__(self, left, right, m)
201 self.y = pos 201 self.y = left.y
202 202
203 def __repr__(self): 203 def __repr__(self):
204 return "R@%s%s:%s" % (self.y, self.runs, list.__repr__(self)) 204 return "R@%s%s:%s" % (self.y, self.runs, list.__repr__(self))
205 205
206 def initDisp(self): 206 def initDisp(self):
231 231
232 232
233 class Column(Vector): 233 class Column(Vector):
234 cLet = "C" 234 cLet = "C"
235 235
236 def __init__(self, n, m, pos): 236 def __init__(self, m, top, bottom):
237 Vector.__init__(self, n, m) 237 Vector.__init__(self, top, bottom, m)
238 self.x = pos 238 self.x = top.x
239 239
240 def __repr__(self): 240 def __repr__(self):
241 return "C@%s%s:%s" % (self.x, self.runs, list.__repr__(self)) 241 return "C@%s%s:%s" % (self.x, self.runs, list.__repr__(self))
242 242
243 def initDisp(self): 243 def initDisp(self):
278 self.header = self.fmt % header 278 self.header = self.fmt % header
279 dprint(self.header) 279 dprint(self.header)
280 280
281 281
282 class Cell: 282 class Cell:
283 def __init__(self, row, y, column, x): 283 def __init__(self, x, y):
284 # At the intersection of row and column Vectors
285 self.row = row
286 self.column = column
287 self.x = x 284 self.x = x
288 self.y = y 285 self.y = y
289 self.val = None # three valued: None(unknown), True(filled), False(empty) 286 self.val = None # three valued: None(unknown), True(filled), False(empty)
290 self.row[x] = self
291 self.column[y] = self
292 287
293 def __repr__(self): 288 def __repr__(self):
294 return "c@(%s,%s):%s" % (self.x, self.y, self.val) 289 return "c@(%s,%s):%s" % (self.x, self.y, self.val)
295 290
296 def __str__(self): 291 def __str__(self):
324 global SOLVER 319 global SOLVER
325 self.loop = 0 320 self.loop = 0
326 self.dp = "" # old depth hack 321 self.dp = "" # old depth hack
327 self.debug = debug 322 self.debug = debug
328 self.dstate = [] 323 self.dstate = []
324 self.pending = [] # newly filled/dead cells whose runs need to be checkedo
329 SOLVER = self 325 SOLVER = self
330 n = self.n = len(runsPerCol) 326 n = self.n = len(runsPerCol)
331 if n != len(runsPerRow): 327 if n != len(runsPerRow):
332 print("losing r:%s x c:%s" % (len(runsPerRow), n), sys.stderr) 328 print("losing r:%s x c:%s" % (len(runsPerRow), n), sys.stderr)
333 exit(1) 329 exit(1)
330 list.__init__(self,list(list(list(range(n)) for _ in range(n))))
334 self.rc = runsPerRow 331 self.rc = runsPerRow
335 self.cc = runsPerCol 332 self.cc = runsPerCol
336 # print col nums>9 vertically :-( 333 # print col nums>9 vertically :-(
337 self.columns = cc = [Column(n, self, i) for i in range(n)] 334 self.rows = [[(self[x,y] := Cell(x,y)) for y in range(n)] for x in range(n)]
338 self.rows = rr = [Row(n, self, i) for i in range(n)]
339 for x in range(n):
340 for y in range(n):
341 self[x, y] = Cell(rr[y], y, cc[x], x)
342 # Need cells in place for the following 335 # Need cells in place for the following
343 for row, runs in zip(rr, runsPerRow): 336 maxCRheight = 0
344 row.initRuns(runs) 337 for i in range(n):
345 for col, runs in zip(cc, runsPerCol): 338 self.initRuns([Cell[i,y] for y in range(n)], runsPerRow[i])
346 col.initRuns(runs) 339 self.initRuns([Cell[x,i] for x in range(n)], runsPerCol[i])
347 self.maxCRheight = maxCRheight = max(col.height for col in cc) 340 maxCRheight = max(maxCRheight = max(col.height for col in cc)
341 self.maxCRheight = maxCRheight
348 for c in cc: 342 for c in cc:
349 c.updateHeader(maxHeight=maxCRheight) 343 c.updateHeader(maxHeight=maxCRheight)
350 maxRRwidth = max(row.width for row in rr) 344 maxRRwidth = max(row.width for row in rr)
351 for r in rr: 345 for r in rr:
352 r.updateHeader(maxWidth=maxRRwidth) 346 r.updateHeader(maxWidth=maxRRwidth)