Skip to content

Instantly share code, notes, and snippets.

@ppmotskula
Created January 19, 2024 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ppmotskula/c56383f4ee94d40234409b3ca8eef75d to your computer and use it in GitHub Desktop.
Save ppmotskula/c56383f4ee94d40234409b3ca8eef75d to your computer and use it in GitHub Desktop.
9cardpuzzle solver
#!/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