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