In [1]:
import forge
from puzzle.puzzlepedia import puzzlepedia
puzzle = puzzlepedia.parse("""
name in {Beth, Charles, David, Frank, Jessica, Karen, Taylor, empty*8}
(room, floor) in ({A, B, C, D, E}, {1, 2, 3})
def on_floor(n, floor_number):
return sum(n[f] for f in floor[floor_number]) == 1
def floor_n(n):
return sum(n[f] for f in floor[1]) + 2*sum(n[f] for f in floor[2]) + 3*sum(n[f] for f in floor[3])
#1: 8 of the 15 rooms are empty.
# (Implicit with "name" definition above with 8 "empty" names.)
#2: 2+ people per floor.
for f in [floor[1], floor[2], floor[3]]:
sum(not r.empty for r in f) >= 2
#3: Some people share closets with guests, sorta.
closet_neighbors = [Beth, David, Jessica, Taylor]
# NB: No closet linking 3D/E3.
closet_neighbor_map = {
A1: B1,
A2: B2,
A3: B3,
}
closet_neighbor_banned_rooms = [
C1, C2, C3,
D1, D2, D3,
E1, E2, E3,
]
# Ensure, for example, that if Beth is in "A1" then "B1" is not empty.
for n in closet_neighbors:
for a, b in closet_neighbor_map.items():
if n[a]: not b.empty
if n[b]: not a.empty
for a in closet_neighbor_banned_rooms:
n[a] == False
#4a: Karen is next to someone with a closet crawlspace.
# Map of rooms-with-crawlspace-closets -> neighbors.
closet_crawlspaces = {
C1: [A1, B1],
C2: [A2, B2],
C3: [A3, B3],
E3: [D3],
}
karen_eligible = [A1, B1, A2, B2, A3, B3, D3]
# Karen needs to be in one of those closet neighbor rooms.
sum(Karen[n] for n in karen_eligible) == 1
# And the candidate room will need to be occupied.
for candidate, neighbors in closet_crawlspaces.items():
if sum(Karen[n] for n in neighbors): not candidate.empty
#4b: Two guests have closets near crawl spaces.
sum(not c.empty for c in closet_crawlspaces) == 2
#5: Beth and Jessica are on separate floors.
floor_n(Beth) != floor_n(Jessica)
#6:
def floor_addr(n):
return (
1*n.D1 + 2*n.B1 + 3*n.C1 + 4*n.E1 +
5*n.E2 + 6*n.C2 + 7*n.B2 + 8*n.D2 + 9*n.A2 +
10*n.A3 + 11*n.D3 + 12*n.B3 + 13*n.C3 + 14*n.E3
)
# For some reason the "abs(...) - 1" expression does not work!
def floor_distance(a, b):
if floor_addr(a) > floor_addr(b):
result = floor_addr(a) - floor_addr(b)
else:
result = floor_addr(b) - floor_addr(a)
return result - 1
floor_distance(Beth, Charles) * 2 == floor_distance(Jessica, Karen)
floor_distance(Beth, Charles) > 0
#7: David is one floor higher than Frank.
floor_n(David) == floor_n(Frank) + 1
#8
D1.empty + D2.empty + D3.empty < 3
""")
In [ ]: