Created
January 19, 2024 14:46
-
-
Save ppmotskula/c56383f4ee94d40234409b3ca8eef75d to your computer and use it in GitHub Desktop.
9cardpuzzle solver
This file contains 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
#!/usr/bin/env python3 | |
"""Solver for the 9 card puzzles made by Portel.ee | |
Usage: | |
1. Edit the CARDS constant to contain 9 card faces coded as follows: | |
Values (clockwise from the top): A/B/C/D for heads, a/b/c/d for tails | |
2. Run 9cards.py | |
""" | |
__author__ = "Peeter P. Mõtsküla" | |
__copyright__ = "Copyright (c) 2024 Peeter P. Mõtsküla" | |
__license__ = "MIT" | |
CARDS = ('aCBD', 'Acbd', 'BCad', 'AdbC', 'BAcd', 'DBCa', 'aBAC', 'dDba', 'CcBd') | |
class Card: | |
S = 'ABCD+abcd' | |
I = [1, 2, 3, 4, 0, -1, -2, -3, -4] | |
# face: 4 letters, order NESW, values ABCD for heads and abcd for tails, + for empty | |
def __init__(self, face='++++'): | |
self.face = face | |
self.values = [] | |
for i in range(4): | |
self.values.append(self.I[self.S.index(face[i])]) | |
def __str__(self): | |
return self.face | |
def n(self): | |
return self.face[0] | |
def e(self): | |
return self.face[1] | |
def s(self): | |
return self.face[2] | |
def w(self): | |
return self.face[3] | |
def rotate(self): | |
self.values.append(self.values.pop(0)) | |
self.face = self.face[1:4] + self.face[0] | |
def mask(self, heading: int, value1: int, value2 = 0) -> bool: | |
# heading must be 0 (N) to 3 (W); not currently checked | |
if value1 not in self.values: | |
return False # value1 not found | |
elif (value2 != 0) and (self.values[(self.values.index(value1) + 1) % 4] != value2): | |
return False # value2 not found 90 degrees clocwise from value1 | |
else: | |
while self.values[heading] != value1: | |
self.rotate() | |
return True | |
class Grid: | |
def __init__(self): | |
self.c = Card() | |
self.n = Card() | |
self.ne = Card() | |
self.e = Card() | |
self.se = Card() | |
self.s = Card() | |
self.sw = Card() | |
self.w = Card() | |
self.nw = Card() | |
def __STR__(self): # use this as __str__ for shorthand output | |
return(f''' | |
{self.nw.face} {self.n.face} {self.ne.face} | |
{self.w.face} {self.c.face} {self.e.face} | |
{self.sw.face} {self.s.face} {self.se.face} | |
''') | |
def __str__(self): # use this as __str__ for visual output | |
return(f''' | |
{self.nw.n()} | {self.n.n()} | {self.ne.n()} | |
{self.nw.w()} {self.nw.e()} | {self.n.w()} {self.n.e()} | {self.ne.w()} {self.ne.e()} | |
{self.nw.s()} | {self.n.s()} | {self.ne.s()} | |
-------+-------+------- | |
{self.w.n()} | {self.c.n()} | {self.e.n()} | |
{self.w.w()} {self.w.e()} | {self.c.w()} {self.c.e()} | {self.e.w()} {self.e.e()} | |
{self.w.s()} | {self.c.s()} | {self.e.s()} | |
-------+-------+------- | |
{self.sw.n()} | {self.s.n()} | {self.se.n()} | |
{self.sw.w()} {self.sw.e()} | {self.s.w()} {self.s.e()} | {self.se.w()} {self.se.e()} | |
{self.sw.s()} | {self.s.s()} | {self.se.s()} | |
''') | |
class Deck(list): | |
def __init__(self, faces: tuple): | |
super().__init__() | |
for i in range(0, len(faces)): | |
super().append(Card(faces[i])) | |
def solve(faces: tuple): | |
deck = Deck(faces) | |
grid = Grid() | |
NULL = Card() | |
for c in range(9): | |
grid.c = deck[c] | |
deck[c] = NULL | |
for n in range(9): | |
if deck[n].mask(2, -grid.c.values[0]): | |
grid.n = deck[n] | |
deck[n] = NULL | |
for ne in range(9): | |
if deck[ne].mask(3, -grid.n.values[1]): | |
grid.ne = deck[ne] | |
deck[ne] = NULL | |
for e in range(9): | |
if deck[e].mask(3, -grid.c.values[1], -grid.ne.values[2]): | |
grid.e = deck[e] | |
deck[e] = NULL | |
for se in range(9): | |
if deck[se].mask(0, -grid.e.values[2]): | |
grid.se = deck[se] | |
deck[se] = NULL | |
for s in range(9): | |
if deck[s].mask(0, -grid.c.values[2], -grid.se.values[3]): | |
grid.s = deck[s] | |
deck[s] = NULL | |
for sw in range(9): | |
if deck[sw].mask(1, -grid.s.values[3]): | |
grid.sw = deck[sw] | |
deck[sw] = NULL | |
for w in range(9): | |
if deck[w].mask(1, -grid.c.values[3], -grid.sw.values[0]): | |
grid.w = deck[w] | |
deck[w] = NULL | |
for nw in range(9): | |
if deck[nw].mask(1, -grid.n.values[3], -grid.w.values[0]): | |
grid.nw = deck[nw] | |
deck[nw] = NULL | |
print(grid) | |
deck[nw] = grid.nw | |
grid.nw = NULL | |
deck[w] = grid.w | |
grid.w = NULL | |
deck[sw] = grid.sw | |
grid.sw = NULL | |
deck[s] = grid.s | |
grid.s = NULL | |
deck[se] = grid.se | |
grid.se = NULL | |
deck[e] = grid.e | |
grid.e = NULL | |
deck[ne] = grid.ne | |
grid.ne = NULL | |
deck[n] = grid.n | |
grid.n = NULL | |
deck[c] = grid.c | |
grid.c = NULL | |
solve(CARDS) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment