Optimization

This commit is contained in:
Lukas Wölfer
2019-04-20 02:17:08 +02:00
parent 7ebc254294
commit 90ab536240
4 changed files with 93 additions and 82 deletions

View File

@@ -1,5 +1,5 @@
"""Contains function to iterate different kinds of possible actions"""
from typing import Iterator, List
from typing import Iterator, List, Tuple
from . import board
from . import board_actions
@@ -168,29 +168,33 @@ def possible_field_move_actions(
"""Enumerate all possible move actions
from one field stack to another field stack"""
first_empty_field_id = -1
my_id = search_board.state_identifier
for index, stack in enumerate(_get_cardstacks(search_board)):
if not stack:
continue
# TODO: sort all substacks by length
for substack in (stack[i:] for i in range(len(stack))):
for other_index, other_stack in enumerate(search_board.field):
if index == other_index:
cardstacks = [(index, stack)
for index, stack in enumerate(_get_cardstacks(search_board))]
cardstacks = [x for x in cardstacks if x[1]]
cardstacks = sorted(cardstacks, key=lambda x: len(x[1]))
substacks: List[Tuple[int, List[board.Card]]] = []
for index, stack in cardstacks:
substacks.extend((index, substack)
for substack in (stack[i:]
for i in range(len(stack))))
for index, substack in substacks:
for other_index, other_stack in enumerate(search_board.field):
if index == other_index:
continue
if other_stack:
if not _can_stack(other_stack[-1], substack[0]):
continue
if other_stack:
if not _can_stack(other_stack[-1], substack[0]):
continue
elif first_empty_field_id == -1:
first_empty_field_id = other_index
elif other_index != first_empty_field_id:
continue
elif len(substack) == len(search_board.field[index]):
continue
assert search_board.state_identifier == my_id
yield board_actions.MoveAction(
cards=substack, source_id=index, destination_id=other_index
)
assert search_board.state_identifier == my_id
elif len(substack) == len(search_board.field[index]):
continue
elif first_empty_field_id == -1:
first_empty_field_id = other_index
elif other_index != first_empty_field_id:
continue
yield board_actions.MoveAction(
cards=substack, source_id=index, destination_id=other_index
)
def possible_actions(

View File

@@ -54,30 +54,31 @@ class SolitaireSolver:
self.stack = ActionStack()
self.stack.push(self.search_board)
def solve(self) -> List[board_actions.Action]:
max_goal = 0
action = None
def solve(self) -> Iterator[List[board_actions.Action]]:
while self.stack:
assert (self.search_board.state_identifier ==
self.stack.state_stack[-1])
action = self.stack.get()
if not action:
self.stack.pop()
self.stack.action_stack[-1].undo(self.search_board)
assert (self.search_board.state_identifier
in self.state_set)
continue
action.apply(self.search_board)
if self.search_board.solved():
return self.stack.action_stack
yield self.stack.action_stack
if self.search_board.state_identifier in self.state_set:
action.undo(self.search_board)
assert self.search_board.state_identifier in self.state_set
continue
self.state_set.add(self.search_board.state_identifier)
self.stack.push(self.search_board)
if sum(self.search_board.goal.values()) > max_goal:
max_goal = sum(self.search_board.goal.values())
print(self.search_board.goal)
return self.stack.action_stack

View File

@@ -2,7 +2,8 @@
import unittest
from .context import shenzhen_solitaire
from shenzhen_solitaire.board import NumberCard, SpecialCard, Board
from shenzhen_solitaire.board import NumberCard, SpecialCard, Board, Position
from shenzhen_solitaire.board_actions import MoveAction, BunkerizeAction, GoalAction, HuaKillAction
from shenzhen_solitaire import board_possibilities
from .boards import my_board
@@ -15,52 +16,57 @@ class ChainTestClass(unittest.TestCase):
self.assertTrue(my_board.check_correct())
sequence = [
0,
4,
0,
1,
0,
0,
8,
0,
1,
3,
0,
9,
0,
2,
0,
1,
1,
1,
2,
0,
2,
1,
6,
12,
0,
0,
1,
0,
0,
17,
11,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0]
for action_index in sequence:
MoveAction(
cards=[
NumberCard(
suit=NumberCard.Suit.Red,
number=7),
NumberCard(
suit=NumberCard.Suit.Green,
number=6)],
source_id=3,
destination_id=7),
BunkerizeAction(
card=NumberCard(
suit=NumberCard.Suit.Red,
number=6),
bunker_id=0,
field_id=2,
to_bunker=True),
GoalAction(
card=NumberCard(
suit=NumberCard.Suit.Green,
number=1),
source_id=2,
source_position=Position.Field),
MoveAction(
cards=[
NumberCard(
suit=NumberCard.Suit.Red,
number=4)],
source_id=2,
destination_id=5),
GoalAction(
card=NumberCard(
suit=NumberCard.Suit.Red,
number=1),
source_id=2,
source_position=Position.Field),
HuaKillAction(source_field_id=2),
MoveAction(
cards=[
NumberCard(
suit=NumberCard.Suit.Black, number=9),
NumberCard(suit=NumberCard.Suit.Red, number=8)],
source_id=6,
destination_id=2),
GoalAction(
card=NumberCard(
suit=NumberCard.Suit.Green, number=2),
source_id=6,
source_position=Position.Field)
]
for action in sequence:
step = list(board_possibilities.possible_actions(my_board))
step[action_index].apply(my_board)
self.assertIn(action, step)
action.apply(my_board)

View File

@@ -5,9 +5,9 @@ from .boards import my_board
def main() -> None:
A = solver.SolitaireSolver(my_board)
B = A.solve()
print(*B, sep='\n')
print(len(B))
for _, B in zip(range(1), A.solve()):
print(*B, sep='\n')
print(len(B))
if __name__ == "__main__":
main()