Initial commit

This commit is contained in:
Dominic Zimmer 2021-07-11 12:17:03 +02:00
commit a0de5b03b7
10 changed files with 397 additions and 0 deletions

9
10.in Normal file
View File

@ -0,0 +1,9 @@
801004002
204000000
050200410
002700000
000158000
000009800
000000703
026003040
305400908

9
11.in Normal file
View File

@ -0,0 +1,9 @@
000819700
040050801
080002090
021500000
800000009
000006210
010200030
305060070
008137000

9
12.in Normal file
View File

@ -0,0 +1,9 @@
005000018
000008604
400003009
090075000
800000001
000920060
300700006
206500000
170000900

9
13.in Normal file
View File

@ -0,0 +1,9 @@
004870020
000502090
200000000
120790603
600000009
309054017
060017800
050903000
000000006

9
38.in Normal file
View File

@ -0,0 +1,9 @@
000025000
400107000
050600071
091000008
580001967
300900410
270003150
000509003
035410000

9
7.in Normal file
View File

@ -0,0 +1,9 @@
000690070
700000006
602807300
004000698
080000010
216000700
009204105
300000002
020036000

9
9.in Normal file
View File

@ -0,0 +1,9 @@
020000065
070450090
000007400
400023006
062000350
300890001
001200000
030079020
290000010

34
foo.py Executable file
View File

@ -0,0 +1,34 @@
#!/bin/python3.10
from dataclasses import dataclass, field
from typing import Union, Iterator
@dataclass(frozen=True)
class Infty:
def __repr__(self):
return ""
inf = Infty()
@dataclass(frozen=True)
class WrappedNumber:
value: int = 5
def __add__(self, other):
match other:
case Infty():
return inf
case WrappedNumber(val):
return WrappedNumber(self.value + val)
case _:
raise Exception("Invalid argument")
def __mul__(self, other):
return WrappedNumber(self.value + other.value)
def __matmul__(self, other):
return WrappedNumber(self.value ** other.value)
W = WrappedNumber
MYNat = WrappedNumber | Infty

82
main.py Normal file
View File

@ -0,0 +1,82 @@
CORPUS = "craze.txt"
from dataclasses import dataclass, field
from itertools import chain
from random import choices
from typing import Optional
from time import sleep
import sys
@dataclass(frozen=True)
class Token:
value: str
@dataclass(frozen=True)
class PureToken(Token):
pass
@dataclass(frozen=True)
class EndToken(Token):
pass
def tokenize(lines: list[str]) -> list[Token]:
tokenlists = [ line.strip().split() for line in lines ]
words = chain.from_iterable(tokenlists) # flattened
return list(map(Token, words))
class МарковNode:
def __init__(self, token):
self.successors = {} # othertoken -> count
self.count = 0 # total number of successors
self.token = token
def insert(self, other):
self.successors[other] = self.successors.get(other, 0) + 1
self.count += 1
def step(self) -> Optional[Token]:
# TODO: Tag token if 2-gram was deterministic
match (choices(list(self.successors.keys()), list(self.successors.values()))):
case [x]:
return x
case _:
return None
class Марков:
# tokens : list[Token] = []
def __init__(self, filename):
with open(filename, "r") as f:
lines = f.readlines()
self.tokens : list[Token]= tokenize(lines)
self.chain = { token: МарковNode(token) for token in set(self.tokens) } # Token -> MarkowNode
for (a,b) in zip(self.tokens, self.tokens[1:]):
self.chain[a].insert(b)
def step(self, token: Token) -> Optional[Token]:
return self.chain[token].step()
mc = Марков(CORPUS)
def gen(s: Optional[Token]):
while s:
yield s
s = mc.step(s)
def ihateGen(s):
s = mc.step(s)
return [s, lambda: ihateGen(s)]
g = gen(Token("The"))
while True:
print(next(g).value, end=" ")
sys.stdout.flush()
sleep(0.2)
#
#

218
sudoku.py Executable file
View File

@ -0,0 +1,218 @@
#!/bin/python3.10
from dataclasses import dataclass, field
from typing import Union, Iterator
from random import choices, choice
from math import prod
@dataclass(frozen=True, repr=False)
class Cell:
row: int
col: int
@dataclass(frozen=True)
class FilledCell(Cell):
value: int
def __repr_(self):
return f"f{self.value}"
@dataclass(frozen=True, repr=False)
class GivenCell(FilledCell):
def __repr__(self):
return f"{self.value}"
@dataclass(frozen=True, repr=False)
class SolvedCell(FilledCell):
def __repr__(self):
return f"{self.value}"
@dataclass(frozen=True, repr=False)
class EmptyCell(Cell):
def __repr__(self):
return "."
@dataclass(frozen=True, repr=False)
class UninitializedCell():
def __repr__(self):
return "."
@dataclass(frozen=True, repr=False)
class Thermo:
value: int
def __repr__(self):
return f"{self.value}"
@dataclass(frozen=True)
class Link:
fr: FilledCell
to: FilledCell
def pp(c: Cell):
if isinstance(c, GivenCell):
return f"{c.value!s}"
if isinstance(c, SolvedCell):
return f"\u001b[32;1m{str(c.value)}\u001b[0m"
if isinstance(c, EmptyCell):
return " "
return "_"
Path = list[Link]
def empty_grid() -> list[list[UninitializedCell]]:
return [ [ UninitializedCell() for _j in range(9)] for _i in range(9) ]
class Sudoku:
def __init__(self, grid):
self.grid = grid
def _row_values(self, i):
return [ self.grid[i][j].value for j in range(9) if isinstance(self.grid[i][j], FilledCell) ]
def _col_values(self, j):
return [ self.grid[i][j].value for i in range(9) if isinstance(self.grid[i][j], FilledCell) ]
def _blk_values(self, i,j):
return [ self.grid[(i//3)*3 + ioff ][(j//3)*3 + joff].value for ioff in range(3) for joff in range(3) if isinstance(self.grid[(i//3)*3 + ioff ][(j//3)*3 + joff], FilledCell) ]
def _possible(self, i, j, v):
return (v not in self._row_values(i)) and (v not in self._col_values(j)) and (v not in self._blk_values(i,j))
def __repr__(self):
return "\n".join(map(lambda x: "".join(str(x)), self.grid))
def solve(self):
for i in range(9):
for j in range(9):
if isinstance(self.grid[i][j], EmptyCell):
for v in range(1,10):
if self._possible(i, j, v):
self.grid[i][j] = SolvedCell(row=i, col=j, value=v)
yield from self.solve()
self.grid[i][j] = EmptyCell(row = i, col = j)
return
yield [ [ entry for entry in row ] for row in self.grid ]
def read_grid() -> list[list[Cell]]:
grid : list[list[Union[Cell,UninitializedCell]]] = empty_grid()
for i in range(9):
row = input()
for j in range(9):
if row[j] == " " or row[j] == "0":
grid[i][j] = EmptyCell(row = i, col = j)
else:
grid[i][j] = GivenCell(row=i, col=j, value=int(row[j]))
return grid
grid: list[list[Cell]] = Sudoku.read_grid()
s = Sudoku(grid)
solution: list[list[FilledCell]] = [x for x in s.solve()][0]
offset_list = [ [0, 1], [1, 0], [1, 1], [-1, 1] ]
def gen_links(grid) -> Iterator[Link]:
for i in range(9):
for j in range(9):
for offset in offset_list:
c1 = grid[i][j]
x, y = i + offset[0], j + offset[1]
if (x < 0 or x > 8 or y < 0 or y > 8):
continue
c2 = grid[x][y]
if (c1.value > c2.value):
yield Link(c2, c1)
if (c1.value < c2.value):
yield Link(c1, c2)
printable = [ " ".join(list(map(pp, row))) for row in solution ]
print("\n".join(printable))
# build implicit graph
links = [link for link in gen_links(solution)]
adj = [ ([ [] for j in range(9) ]) for i in range(9) ]
#print(links)
for link in links:
#print(link)
adj[link.fr.row][link.fr.col].append(link.to)
neighbor_matrix = [[-1,-1], [0, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [0, 1], [1, 1]]
def neighbors(board: list[list[FilledCell]], cell: Cell) -> Iterator[FilledCell]:
for offset in neighbor_matrix:
x, y = cell.row + offset[1], cell.col + offset[0]
if (x < 0 or x > 8 or y < 0 or y > 8):
continue
yield board[x][y]
def all_cells_of_value(board: list[list[FilledCell]], filter: int) -> Iterator[FilledCell]:
#fields = [ field for row in board for field in row ]
fields = all_cells(board)
for field in [ f for f in fields if f.value == filter ]:
yield field
def all_cells(board: list[list[FilledCell]]) -> Iterator[FilledCell]:
yield from [ field for row in board for field in row ]
# print path
def pP(path: Path) -> str:
return " ".join(list(map(lambda link: str(link.to.value), path)))
paths: dict[FilledCell, list[Path]] = {}
for cell in all_cells_of_value(solution, 9):
paths[cell] = []
for value in range(8,0, -1):
cells = all_cells_of_value(solution, value)
for cell in cells:
paths[cell] = []
for neighbor in neighbors(solution, cell):
if neighbor.value <= cell.value: continue
# neighbor is larger
new_path: Path = [Link(cell, neighbor)]
extended_paths : list[Path] = [ new_path + path for path in paths[neighbor]]
all_paths = [new_path] + extended_paths
paths[cell].extend(all_paths)
# for path in paths[cell]:
# print(f"{cell} has path {pP(path)}")
all_paths : list[Path] = [ path for cell in all_cells(solution) for path in paths[cell] ]
print(len(all_paths))
def get_cells(path: Path) -> Iterator[FilledCell]:
yield path[0].fr
for link in path:
yield link.to
def ilike(path: Path) -> bool:
if len(path) < 4: return False
#def four_fold_link(link: Link) -> bool:
# return abs(link.fr.row - link.to.row) + abs(link.fr.col - link.to.col) == 1
cells = [cell for cell in get_cells(path) ]
given_cells = [ cell for cell in cells if isinstance(cell, GivenCell)]
if isinstance(cells[0], GivenCell) or isinstance(cells[-1], GivenCell): return False
#neighboring_values = list(zip(solved_values, solved_values[1:]))
#combinations = prod( map(lambda x: x[1] - x[0] - 1, neighboring_values) )
#print(combinations, solved_values)
#all_four_fold = all( [ four_fold_link(link) for link in path] )
max_one_solved = len(given_cells) < 2
return max_one_solved
hints : list[list[Thermo | Cell]]= empty_grid()
used_cells: set[FilledCell] = set()
num_paths = 4
while num_paths > 0:
while True:
path: Path = choice([path for path in all_paths])
cells = [ cell for cell in get_cells(path)]
if not all([ cell not in used_cells for cell in cells ]): continue
if not ilike(path): continue
for index, cell in enumerate(cells):
used_cells.add(cell)
row, col = cell.row, cell.col
hints[row][col] = Thermo(index)
num_paths -= 1
break
#out = [ " ".join(list(map(str, row))) for row in hints ]
strs = [ " ".join([str(entry) for entry in row]) for row in hints]
print("\n".join(strs))