Initial commit
This commit is contained in:
commit
a0de5b03b7
9
10.in
Normal file
9
10.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
801004002
|
||||||
|
204000000
|
||||||
|
050200410
|
||||||
|
002700000
|
||||||
|
000158000
|
||||||
|
000009800
|
||||||
|
000000703
|
||||||
|
026003040
|
||||||
|
305400908
|
||||||
9
11.in
Normal file
9
11.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
000819700
|
||||||
|
040050801
|
||||||
|
080002090
|
||||||
|
021500000
|
||||||
|
800000009
|
||||||
|
000006210
|
||||||
|
010200030
|
||||||
|
305060070
|
||||||
|
008137000
|
||||||
9
12.in
Normal file
9
12.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
005000018
|
||||||
|
000008604
|
||||||
|
400003009
|
||||||
|
090075000
|
||||||
|
800000001
|
||||||
|
000920060
|
||||||
|
300700006
|
||||||
|
206500000
|
||||||
|
170000900
|
||||||
9
13.in
Normal file
9
13.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
004870020
|
||||||
|
000502090
|
||||||
|
200000000
|
||||||
|
120790603
|
||||||
|
600000009
|
||||||
|
309054017
|
||||||
|
060017800
|
||||||
|
050903000
|
||||||
|
000000006
|
||||||
9
38.in
Normal file
9
38.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
000025000
|
||||||
|
400107000
|
||||||
|
050600071
|
||||||
|
091000008
|
||||||
|
580001967
|
||||||
|
300900410
|
||||||
|
270003150
|
||||||
|
000509003
|
||||||
|
035410000
|
||||||
9
7.in
Normal file
9
7.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
000690070
|
||||||
|
700000006
|
||||||
|
602807300
|
||||||
|
004000698
|
||||||
|
080000010
|
||||||
|
216000700
|
||||||
|
009204105
|
||||||
|
300000002
|
||||||
|
020036000
|
||||||
9
9.in
Normal file
9
9.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
020000065
|
||||||
|
070450090
|
||||||
|
000007400
|
||||||
|
400023006
|
||||||
|
062000350
|
||||||
|
300890001
|
||||||
|
001200000
|
||||||
|
030079020
|
||||||
|
290000010
|
||||||
34
foo.py
Executable file
34
foo.py
Executable 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
82
main.py
Normal 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
218
sudoku.py
Executable 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))
|
||||||
Loading…
Reference in New Issue
Block a user