comparison nono.py @ 16:a7a10e40b344

5a working after obvious bugfix, indenting debug print, 10a inf. loop
author Henry S. Thompson <ht@inf.ed.ac.uk>
date Tue, 24 Mar 2020 18:57:33 +0000
parents 22b0894c0f4c
children 6c9e371b0325
comparison
equal deleted inserted replaced
15:22b0894c0f4c 16:a7a10e40b344
106 inSeq=None 106 inSeq=None
107 maybeSeq=None 107 maybeSeq=None
108 dprint('s2',i-1,j) 108 dprint('s2',i-1,j)
109 if j is not None: 109 if j is not None:
110 # Only if we actually added a blob at some point 110 # Only if we actually added a blob at some point
111 dpush('b_s2')
111 self.checkNew(i-1) 112 self.checkNew(i-1)
113 dpop('b_s2')
112 elif self[i].val is True and maybeSeq is None: 114 elif self[i].val is True and maybeSeq is None:
113 dprint('s3',i) 115 dprint('s3',i)
114 maybeSeq=i 116 maybeSeq=i
115 dprint('s4',inSeq,i) 117 dprint('s4',inSeq,i)
116 if inSeq is not None: 118 if inSeq is not None:
119 dpush('b_s4')
117 self.checkNew(i) 120 self.checkNew(i)
121 dpop('b_s4')
118 return changed 122 return changed
119 123
120 def onepass(self,i0,iBound,scratch,stack): 124 def onepass(self,i0,iBound,scratch,stack):
121 """note that stack is not a simple run, but one with _negative_ numbers between 125 """note that stack is not a simple run, but one with _negative_ numbers between
122 and possibly before the positive ones, indicating obligatory skips 126 and possibly before the positive ones, indicating obligatory skips
264 dprint('x2b') 268 dprint('x2b')
265 if changed: 269 if changed:
266 self.resetAllRuns() 270 self.resetAllRuns()
267 271
268 def marginal(self,rng,l): 272 def marginal(self,rng,l):
269 dprint('m',rng.start,rng.stop,rng.step) 273 dprint('m%s'%self.cLet,rng.start,rng.stop,rng.step,l)
270 g=0 # length of a gap 274 g=0 # length of a gap
271 for i in rng: 275 for i in rng:
272 if self[i].val is True: 276 if self[i].val is True:
273 # Should//n't be possible? 277 # Shouldn't be possible?
274 dprint('mx0') 278 dprint('mx0')
275 return False 279 return False
276 if self[i].val is False: 280 if self[i].val is False:
277 if g>0: 281 if g>0:
278 # Block a too-small gap 282 # Block a too-small gap
279 for i in (i-g,i): 283 dprint('m1',i-g,i)
280 self.newX(i,True) 284 for j in range(i-g,i):
285 self.newX(j,True)
281 g=0 286 g=0
282 else: 287 else:
283 # None 288 # None
284 g+=1 289 g+=1
285 if g==l: 290 if g==l:
286 # run could fit here, so no go 291 # run could fit here, so no go
287 dprint('mx1') 292 dprint('mx1')
288 return False 293 return False
289 if g>0: 294 if g>0:
290 # Block a too-small gap 295 # Block a too-small gap
291 for j in (i-g,i): 296 dprint('m2',i-g,i)
297 for j in range(i+1-g,i+1):
292 self.newX(j,True) 298 self.newX(j,True)
293 return True 299 return True
294 300
295 def found0(self,i): 301 def found0(self,i):
296 dprint('found0 called on %s at %s'%(self,i)) 302 dprint('found0 called on %s at %s'%(self,i))
345 self.suffix="" 351 self.suffix=""
346 352
347 def newBlob(self,x,crossCheck=False): 353 def newBlob(self,x,crossCheck=False):
348 self[x].setVal(True) 354 self[x].setVal(True)
349 if crossCheck: 355 if crossCheck:
356 dpush('b_cc')
350 self[x].column.checkNew(self.y) 357 self[x].column.checkNew(self.y)
358 dpop('b_cc')
351 359
352 def newX(self,x,crossCheck=False): 360 def newX(self,x,crossCheck=False):
353 dprint('nx %s%s@%s'%('R',self.y,x)) 361 dprint('nx %s%s@%s'%('R',self.y,x))
354 self[x].setVal(False) 362 self[x].setVal(False)
355 if crossCheck: 363 if crossCheck:
364 dpush('x_cc')
356 self[x].column.checkX(self.y,x) 365 self[x].column.checkX(self.y,x)
366 dpop('x_cc')
357 367
358 class Column(Vector): 368 class Column(Vector):
359 cLet='C' 369 cLet='C'
360 def __init__(self,n,m,runs,pos): 370 def __init__(self,n,m,runs,pos):
361 Vector.__init__(self,n,m,runs) 371 Vector.__init__(self,n,m,runs)
394 dprint(self.header) 404 dprint(self.header)
395 405
396 def newBlob(self,y,crossCheck=False): 406 def newBlob(self,y,crossCheck=False):
397 self[y].setVal(True) 407 self[y].setVal(True)
398 if crossCheck: 408 if crossCheck:
409 dpush('b_cc')
399 self[y].row.checkNew(self.x) 410 self[y].row.checkNew(self.x)
411 dpop('b_cc')
400 412
401 def newX(self,y,crossCheck=False): 413 def newX(self,y,crossCheck=False):
402 dprint('nx %s%s@%s'%('C',self.x,y)) 414 dprint('nx %s%s@%s'%('C',self.x,y))
403 self[y].setVal(False) 415 self[y].setVal(False)
404 if crossCheck: 416 if crossCheck:
417 dpush('x_cc')
405 self[y].row.checkX(self.x,y) 418 self[y].row.checkX(self.x,y)
419 dpop('x_cc')
406 420
407 class Cell: 421 class Cell:
408 def __init__(self,row,y,column,x): 422 def __init__(self,row,y,column,x):
409 # At the intersection of row and column Vectors 423 # At the intersection of row and column Vectors
410 self.row=row 424 self.row=row
436 450
437 451
438 class Nono(dict): 452 class Nono(dict):
439 # 0,0 is upper left, so increasing y goes _downwards_, to match the standard layout 453 # 0,0 is upper left, so increasing y goes _downwards_, to match the standard layout
440 def __init__(self,runsPerRow,runsPerCol): 454 def __init__(self,runsPerRow,runsPerCol):
455 global SOLVER
441 self.loop=0 456 self.loop=0
457 self.dp=''
458 self.dstate=[]
459 SOLVER=self
442 n=self.n=len(runsPerCol) 460 n=self.n=len(runsPerCol)
443 if n!=len(runsPerRow): 461 if n!=len(runsPerRow):
444 print("losing r:%s x c:%s"%(len(runsPerRow),n),sys.stderr) 462 print("losing r:%s x c:%s"%(len(runsPerRow),n),sys.stderr)
445 exit(1) 463 exit(1)
446 self.rc=runsPerRow 464 self.rc=runsPerRow
479 for r in self.rows: 497 for r in self.rows:
480 someChanged+=r.step(r.y) 498 someChanged+=r.step(r.y)
481 print(someChanged) 499 print(someChanged)
482 print(self) 500 print(self)
483 501
502 def dpush(s):
503 SOLVER.dp+=' '
504 SOLVER.dstate.append(s)
505
506 def dpop(s):
507 assert(SOLVER.dstate.pop()==s)
508 SOLVER.dp=SOLVER.dp[1:]
509
484 def dprint(*args): 510 def dprint(*args):
511 print(SOLVER.dp,end='')
485 print(*args) 512 print(*args)
486 sys.stdout.flush() 513 sys.stdout.flush()
487 514
488 def eprint(*args,**kw): 515 def eprint(*args,**kw):
489 print(*args,file=sys.stderr) 516 print(*args,file=sys.stderr)