Last active
February 15, 2022 21:08
-
-
Save jthemphill/1a0165950095eeb24e1ad0aa467969ed to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import collections | |
horiz_edges = [ | |
[">", "<", ">", ">"], | |
["<", " ", "<", ">"], | |
[">", ">", "<", " "], | |
["<", " ", ">", "<"], | |
[" ", " ", ">", ">"], | |
] | |
assert len(horiz_edges) == 5 | |
assert all((len(row) == 4 for row in horiz_edges)) | |
vert_edges = [ | |
[">", "<", " ", " ", " "], | |
[" ", " ", ">", ">", ">"], | |
[">", "<", "<", ">", " "], | |
[" ", " ", " ", "<", ">"], | |
] | |
assert len(vert_edges) == 4 | |
assert all((len(col) == 5 for col in vert_edges)) | |
STEEL = 1 | |
ELECTRIC = 2 | |
GROUND = 3 | |
FIGHTING = 4 | |
FLYING = 5 | |
BEATS_LIST: "list[tuple[int, int]]" = [ | |
(ELECTRIC, STEEL), | |
(GROUND, STEEL), | |
(FIGHTING, STEEL), | |
(STEEL, FLYING), | |
(GROUND, ELECTRIC), | |
(ELECTRIC, FLYING), | |
(FLYING, GROUND), | |
(FLYING, FIGHTING), | |
] | |
beats: "collections.defaultdict[int, list[int]]" = collections.defaultdict(list) | |
for winner, loser in BEATS_LIST: | |
beats[winner].append(loser) | |
def does_beat(type_1: int, type_2: int) -> bool: | |
assert type_1 > 0 | |
assert type_2 > 0 | |
return type_2 in beats[type_1] | |
def is_valid(grid: "list[list[int]]"): | |
assert len(grid) == 5 | |
assert all((len(row) == 5 for row in grid)) | |
# Row uniqueness | |
for row in grid: | |
for t in range(STEEL, FLYING + 1): | |
if row.count(t) > 1: | |
return False | |
# Column uniqueness | |
for c in range(5): | |
col = [grid[r][c] for r in range(5)] | |
for t in range(STEEL, FLYING + 1): | |
if col.count(t) > 1: | |
return False | |
# Horizontal inequality | |
for r in range(5): | |
for c in range(4): | |
left = grid[r][c] | |
if left == 0: | |
continue | |
right = grid[r][c + 1] | |
if right == 0: | |
continue | |
if horiz_edges[r][c] == ">" and not does_beat(left, right): | |
return False | |
elif horiz_edges[r][c] == "<" and not does_beat(right, left): | |
return False | |
# Vertical inequality | |
for r in range(4): | |
for c in range(5): | |
up = grid[r][c] | |
if up == 0: | |
continue | |
down = grid[r + 1][c] | |
if down == 0: | |
continue | |
if vert_edges[r][c] == ">" and not does_beat(up, down): | |
return False | |
elif vert_edges[r][c] == "<" and not does_beat(down, up): | |
return False | |
return True | |
def solve(grid: "list[list[int]]"): | |
assert len(grid) == 5 | |
assert all((len(row) == 5 for row in grid)) | |
if all((all((t != 0 for t in row)) for row in grid)): | |
render(grid) | |
return | |
for r in range(5): | |
for c in range(5): | |
if grid[r][c] == 0: | |
for t in range(STEEL, FLYING + 1): | |
grid[r][c] = t | |
if is_valid(grid): | |
solve(grid) | |
grid[r][c] = 0 | |
return | |
def render_type(t: int): | |
if t == STEEL: | |
return "steel" | |
elif t == ELECTRIC: | |
return "electric" | |
elif t == GROUND: | |
return "ground" | |
elif t == FIGHTING: | |
return "fighting" | |
elif t == FLYING: | |
return "flying" | |
def render(grid: "list[list[int]]"): | |
print("---") | |
for row in grid: | |
line = "" | |
for t in row: | |
line += f"{render_type(t):10}" | |
print(line) | |
print("---") | |
grid = [[0 for c in range(5)] for r in range(5)] | |
solve(grid) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment