PROBREM = '''\
530070000
600195000
098000060
800060003
400803001
700020006
060000280
000419005
000080079
'''
def main():
cells, flags = load(PROBREM)
try:
i = initialize(flags)
while True:
if increment(cells, i):
if validate(cells, i):
i = find_next(flags, i)
else:
i = back_track(flags, i)
except Exception:
print_cells(cells)
def load(probrem):
cells = []
for line in probrem:
cells.extend([int(n) for n in line.strip()])
return cells, [bool(n) for n in cells]
def initialize(flags):
return find_next(flags, -1)
def increment(cells, i):
if cells[i] == 9:
cells[i] = 0
return False
else:
cells[i] += 1
return True
def validate(cells, i):
x = i % 9
y = i // 9
return (validate_impl(cells, column(x)) and
validate_impl(cells, row(y)) and
validate_impl(cells, block(x, y)))
def column(x):
return (x + n * 9 for n in range(9))
def row(y):
return (n + y * 9 for n in range(9))
def block(x, y):
_x = x // 3 * 3
_y = y // 3 * 3
for X in range(_x, _x + 3):
for Y in range(_y, _y + 3):
yield X + Y * 9
def validate_impl(cells, indices):
indices = list(indices)
s = set()
for i in indices:
c = cells[i]
if c != 0:
if c in s:
return False
s.add(c)
return True
def validate_row(cells, y):
s = set()
for i in range(9):
c = cells[x + i * 9]
if c != 0:
if c in s:
return False
s.add(c)
return True
def find_next(flags, i):
_i = i + 1
return _i + flags[_i:].index(False)
def back_track(flags, i):
return list_rindex(flags[:i], False)
def list_rindex(_list, value):
for i in range(len(_list) - 1, -1, -1):
if _list[i] == value:
return i
raise ValueError()
def print_cells(cells):
for i in range(9):
print(''.join(str(n) for n in cells[i*9:i*9+9]))
main()
UFJPQlJFTSA9ICcnJ1wKNTMwMDcwMDAwCjYwMDE5NTAwMAowOTgwMDAwNjAKODAwMDYwMDAzCjQwMDgwMzAwMQo3MDAwMjAwMDYKMDYwMDAwMjgwCjAwMDQxOTAwNQowMDAwODAwNzkKJycnCgoKZGVmIG1haW4oKToKICAgIGNlbGxzLCBmbGFncyA9IGxvYWQoUFJPQlJFTSkKICAgIHRyeToKICAgICAgICBpID0gaW5pdGlhbGl6ZShmbGFncykKICAgICAgICB3aGlsZSBUcnVlOgogICAgICAgICAgICBpZiBpbmNyZW1lbnQoY2VsbHMsIGkpOgogICAgICAgICAgICAgICAgaWYgdmFsaWRhdGUoY2VsbHMsIGkpOgogICAgICAgICAgICAgICAgICAgIGkgPSBmaW5kX25leHQoZmxhZ3MsIGkpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBpID0gYmFja190cmFjayhmbGFncywgaSkKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgcHJpbnRfY2VsbHMoY2VsbHMpCgoKZGVmIGxvYWQocHJvYnJlbSk6CiAgICBjZWxscyA9IFtdCiAgICBmb3IgbGluZSBpbiBwcm9icmVtOgogICAgICAgIGNlbGxzLmV4dGVuZChbaW50KG4pIGZvciBuIGluIGxpbmUuc3RyaXAoKV0pCiAgICByZXR1cm4gY2VsbHMsIFtib29sKG4pIGZvciBuIGluIGNlbGxzXQoKCmRlZiBpbml0aWFsaXplKGZsYWdzKToKICAgIHJldHVybiBmaW5kX25leHQoZmxhZ3MsIC0xKQoKCmRlZiBpbmNyZW1lbnQoY2VsbHMsIGkpOgogICAgaWYgY2VsbHNbaV0gPT0gOToKICAgICAgICBjZWxsc1tpXSA9IDAKICAgICAgICByZXR1cm4gRmFsc2UKICAgIGVsc2U6CiAgICAgICAgY2VsbHNbaV0gKz0gMQogICAgICAgIHJldHVybiBUcnVlCgoKZGVmIHZhbGlkYXRlKGNlbGxzLCBpKToKICAgIHggPSBpICUgOQogICAgeSA9IGkgLy8gOQogICAgcmV0dXJuICh2YWxpZGF0ZV9pbXBsKGNlbGxzLCBjb2x1bW4oeCkpIGFuZAogICAgICAgICAgICB2YWxpZGF0ZV9pbXBsKGNlbGxzLCByb3coeSkpIGFuZAogICAgICAgICAgICB2YWxpZGF0ZV9pbXBsKGNlbGxzLCBibG9jayh4LCB5KSkpCgoKZGVmIGNvbHVtbih4KToKICAgIHJldHVybiAoeCArIG4gKiA5IGZvciBuIGluIHJhbmdlKDkpKQoKCmRlZiByb3coeSk6CiAgICByZXR1cm4gKG4gKyB5ICogOSBmb3IgbiBpbiByYW5nZSg5KSkKCgpkZWYgYmxvY2soeCwgeSk6CiAgICBfeCA9IHggLy8gMyAqIDMKICAgIF95ID0geSAvLyAzICogMwogICAgZm9yIFggaW4gcmFuZ2UoX3gsIF94ICsgMyk6CiAgICAgICAgZm9yIFkgaW4gcmFuZ2UoX3ksIF95ICsgMyk6CiAgICAgICAgICAgIHlpZWxkIFggKyBZICogOQoKCmRlZiB2YWxpZGF0ZV9pbXBsKGNlbGxzLCBpbmRpY2VzKToKICAgIGluZGljZXMgPSBsaXN0KGluZGljZXMpCiAgICBzID0gc2V0KCkKICAgIGZvciBpIGluIGluZGljZXM6CiAgICAgICAgYyA9IGNlbGxzW2ldCiAgICAgICAgaWYgYyAhPSAwOgogICAgICAgICAgICBpZiBjIGluIHM6CiAgICAgICAgICAgICAgICByZXR1cm4gRmFsc2UKICAgICAgICAgICAgcy5hZGQoYykKICAgIHJldHVybiBUcnVlCgoKZGVmIHZhbGlkYXRlX3JvdyhjZWxscywgeSk6CiAgICBzID0gc2V0KCkKICAgIGZvciBpIGluIHJhbmdlKDkpOgogICAgICAgIGMgPSBjZWxsc1t4ICsgaSAqIDldCiAgICAgICAgaWYgYyAhPSAwOgogICAgICAgICAgICBpZiBjIGluIHM6CiAgICAgICAgICAgICAgICByZXR1cm4gRmFsc2UKICAgICAgICAgICAgcy5hZGQoYykKICAgIHJldHVybiBUcnVlCgoKZGVmIGZpbmRfbmV4dChmbGFncywgaSk6CiAgICBfaSA9IGkgKyAxCiAgICByZXR1cm4gX2kgKyBmbGFnc1tfaTpdLmluZGV4KEZhbHNlKQoKCmRlZiBiYWNrX3RyYWNrKGZsYWdzLCBpKToKICAgIHJldHVybiBsaXN0X3JpbmRleChmbGFnc1s6aV0sIEZhbHNlKQoKCmRlZiBsaXN0X3JpbmRleChfbGlzdCwgdmFsdWUpOgogICAgZm9yIGkgaW4gcmFuZ2UobGVuKF9saXN0KSAtIDEsIC0xLCAtMSk6CiAgICAgICAgaWYgX2xpc3RbaV0gPT0gdmFsdWU6CiAgICAgICAgICAgIHJldHVybiBpCiAgICByYWlzZSBWYWx1ZUVycm9yKCkKCgpkZWYgcHJpbnRfY2VsbHMoY2VsbHMpOgogICAgZm9yIGkgaW4gcmFuZ2UoOSk6CiAgICAgICAgcHJpbnQoJycuam9pbihzdHIobikgZm9yIG4gaW4gY2VsbHNbaSo5OmkqOSs5XSkpCgoKbWFpbigp