Skip to content

Commit 43d94e9

Browse files
Add combo module
1 parent 7ede93b commit 43d94e9

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

solve/combo.py

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
from dataclasses import dataclass
2+
from typing import Self
3+
4+
from .key_sets import *
5+
from .shapes import Shape2D
6+
from .states import StateOfAllRooms, StateOfAllStatues, init_rooms, init_statues
7+
8+
9+
@dataclass(frozen=True, slots=True)
10+
class Node:
11+
inner: Shape2D
12+
available: tuple[Shape2D, Shape2D]
13+
14+
@property
15+
def code(self, /) -> str:
16+
"""
17+
Numeric code for this node.
18+
"""
19+
return f'{self.inner.code}[{self.available[0].code}{self.available[1].code}]'
20+
21+
@classmethod
22+
def from_inner_and_other(cls, inner: Shape2D, other: Shape2D, /) -> Self:
23+
"""
24+
Creates a new node using inner shape and other shape.
25+
Both inner shape and other shape are added as available.
26+
"""
27+
return cls(inner, (inner, other))
28+
29+
30+
@dataclass(frozen=True, kw_only=True, slots=True)
31+
class Combination:
32+
left: Node
33+
middle: Node
34+
right: Node
35+
36+
@property
37+
def code(self, /) -> str:
38+
"""
39+
Numeric code for this combination.
40+
"""
41+
return f'{self.left.code}-{self.middle.code}-{self.right.code}'
42+
43+
def to_room_state(self, key_set: KeySetType, /) -> StateOfAllRooms:
44+
return init_rooms(
45+
left_inner_shape=self.left.inner,
46+
left_other_shape=self.left.available[1],
47+
middle_inner_shape=self.middle.inner,
48+
middle_other_shape=self.middle.available[1],
49+
right_inner_shape=self.right.inner,
50+
right_other_shape=self.right.available[1],
51+
key_set=key_set,
52+
)
53+
54+
def to_statue_state(self, key_set: KeySetType, /) -> StateOfAllStatues:
55+
return init_statues(
56+
left_inner_shape=self.left.inner,
57+
left_held_shape=self.left.available[0] + self.left.available[1],
58+
middle_inner_shape=self.middle.inner,
59+
middle_held_shape=self.middle.available[0] + self.middle.available[1],
60+
right_inner_shape=self.right.inner,
61+
right_held_shape=self.right.available[0] + self.right.available[1],
62+
key_set=key_set,
63+
)
64+
65+
66+
code_to_best_ks = {
67+
'0[03]-3[34]-4[40]': KSDouble2,
68+
'0[04]-3[30]-4[43]': KSDouble1,
69+
'0[03]-4[40]-3[34]': KSDouble2,
70+
'0[04]-4[43]-3[30]': KSDouble1,
71+
'3[30]-0[04]-4[43]': KSDouble1,
72+
'3[34]-0[03]-4[40]': KSDouble2,
73+
'3[30]-4[43]-0[04]': KSDouble1,
74+
'3[34]-4[40]-0[03]': KSDouble2,
75+
'4[40]-0[03]-3[34]': KSDouble2,
76+
'4[43]-0[04]-3[30]': KSDouble1,
77+
'4[40]-3[34]-0[03]': KSDouble2,
78+
'4[43]-3[30]-0[04]': KSDouble1,
79+
}
80+
81+
82+
def get_best_double_key(*, rooms: Combination | None, statues: Combination | None) -> KeySetType:
83+
"""
84+
Determines the best double key set for provided combinations.
85+
86+
At first evaluates the best key set for room combination.
87+
If there is no best key or the combination is not provided,
88+
then it uses statue combination for evaluation.
89+
If either evaluation is indifferent, returns ``KSDouble1``.
90+
"""
91+
if rooms is not None:
92+
best_ks = code_to_best_ks.get(rooms.code)
93+
if best_ks is not None:
94+
return best_ks
95+
96+
if statues is not None:
97+
best_ks = code_to_best_ks.get(statues.code)
98+
if best_ks is not None:
99+
return best_ks
100+
101+
return KSDouble1
102+
103+
104+
__all__ = 'Node', 'Combination', 'get_best_double_key'

0 commit comments

Comments
 (0)