Advertisement
Guest User

Untitled

a guest
Jan 20th, 2020
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.11 KB | None | 0 0
  1. from functools import reduce
  2.  
  3. def gen_row(w, s):
  4.     """Create all patterns of a row or col that match given runs."""
  5.     def gen_seg(o, sp):
  6.         if not o:
  7.             return [[2] * sp]
  8.         return [[2] * x + o[0] + tail
  9.                 for x in range(1, sp - len(o) + 2)
  10.                 for tail in gen_seg(o[1:], sp - x)]
  11.  
  12.     return [x[1:] for x in gen_seg([[1] * i for i in s], w + 1 - sum(s))]
  13.  
  14.  
  15. def deduce(hr, vr):
  16.     """Fix inevitable value of cells, and propagate."""
  17.     def allowable(row):
  18.         return reduce(lambda a, b: [x | y for x, y in zip(a, b)], row)
  19.  
  20.     def fits(a, b):
  21.         return all(x & y for x, y in zip(a, b))
  22.  
  23.     def fix_col(n):
  24.         """See if any value in a given column is fixed;
  25.        if so, mark its corresponding row for future fixup."""
  26.         c = [x[n] for x in can_do]
  27.         cols[n] = [x for x in cols[n] if fits(x, c)]
  28.         for i, x in enumerate(allowable(cols[n])):
  29.             if x != can_do[i][n]:
  30.                 mod_rows.add(i)
  31.                 can_do[i][n] &= x
  32.  
  33.     def fix_row(n):
  34.         """Ditto, for rows."""
  35.         c = can_do[n]
  36.         rows[n] = [x for x in rows[n] if fits(x, c)]
  37.         for i, x in enumerate(allowable(rows[n])):
  38.             if x != can_do[n][i]:
  39.                 mod_cols.add(i)
  40.                 can_do[n][i] &= x
  41.  
  42.     def show_gram(m):
  43.         # If there's 'x', something is wrong.
  44.         # If there's '?', needs more work.
  45.         for x in m:
  46.             print(" ".join("x#.?"[i] for i in x))
  47.         print()
  48.  
  49.     w, h = len(vr), len(hr)
  50.     rows = [gen_row(w, x) for x in hr]
  51.     cols = [gen_row(h, x) for x in vr]
  52.     can_do = list(map(allowable, rows))
  53.  
  54.     # Initially mark all columns for update.
  55.     mod_rows, mod_cols = set(), set(range(w))
  56.  
  57.     while mod_cols:
  58.         for i in mod_cols:
  59.             fix_col(i)
  60.         mod_cols = set()
  61.         for i in mod_rows:
  62.             fix_row(i)
  63.         mod_rows = set()
  64.  
  65.     if all(can_do[i][j] in (1, 2) for j in range(w) for i in range(h)):
  66.         print("Solution would be unique")  # but could be incorrect!
  67.     else:
  68.         print("Solution may not be unique, doing exhaustive search:")
  69.  
  70.     # We actually do exhaustive search anyway. Unique solution takes
  71.     # no time in this phase anyway, but just in case there's no
  72.     # solution (could happen?).
  73.     out = [0] * h
  74.  
  75.     def try_all(n = 0):
  76.         if n >= h:
  77.             for j in range(w):
  78.                 if [x[j] for x in out] not in cols[j]:
  79.                     return 0
  80.             show_gram(out)
  81.             return 1
  82.         sol = 0
  83.         for x in rows[n]:
  84.             out[n] = x
  85.             sol += try_all(n + 1)
  86.         return sol
  87.  
  88.     n = try_all()
  89.     if not n:
  90.         print("No solution.")
  91.     elif n == 1:
  92.         print("Unique solution.")
  93.     else:
  94.         print(n, "solutions.")
  95.     print()
  96.  
  97.  
  98. def solve(s, show_runs=True):
  99.     s = [[[ord(c) - ord('A') + 1 for c in w] for w in l.split()]
  100.          for l in p.splitlines()]
  101.     if show_runs:
  102.         print("Horizontal runs:", s[0])
  103.         print("Vertical runs:", s[1])
  104.     deduce(s[0], s[1])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement