Mercurial > hg > python
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 = "[31m" | 25 Red = "[31m" |
| 25 eRed = "[39m" | 26 eRed = "[39m" |
| 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) |
