Advertisement
dzocesrce

[VI] Football

Apr 16th, 2024 (edited)
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.82 KB | None | 0 0
  1. #zadaca za vezbanje prv kol
  2. import bisect
  3.  
  4. class Problem:
  5.     def __init__(self, initial, goal=None):
  6.         self.initial = initial
  7.         self.goal = goal
  8.  
  9.     def successor(self, state):
  10.         """Given a state, return a dictionary of {action : state} pairs reachable
  11.        from this state. If there are many successors, consider an iterator
  12.        that yields the successors one at a time, rather than building them
  13.        all at once.
  14.  
  15.        :param state: given state
  16.        :return:  dictionary of {action : state} pairs reachable
  17.                  from this state
  18.        :rtype: dict
  19.        """
  20.         raise NotImplementedError
  21.  
  22.     def actions(self, state):
  23.         """Given a state, return a list of all actions possible
  24.        from that state
  25.  
  26.        :param state: given state
  27.        :return: list of actions
  28.        :rtype: list
  29.        """
  30.         raise NotImplementedError
  31.  
  32.     def result(self, state, action):
  33.         """Given a state and action, return the resulting state
  34.  
  35.        :param state: given state
  36.        :param action: given action
  37.        :return: resulting state
  38.        """
  39.         raise NotImplementedError
  40.  
  41.     def goal_test(self, state):
  42.         """Return True if the state is a goal. The default method compares
  43.        the state to self.goal, as specified in the constructor. Implement
  44.        this method if checking against a single self.goal is not enough.
  45.  
  46.        :param state: given state
  47.        :return: is the given state a goal state
  48.        :rtype: bool
  49.        """
  50.         return state == self.goal
  51.  
  52.     def path_cost(self, c, state1, action, state2):
  53.         """Return the cost of a solution path that arrives at state2 from state1
  54.        via action, assuming cost c to get up to state1. If the problem is such
  55.        that the path doesn't matter, this function will only look at state2.
  56.        If the path does matter, it will consider c and maybe state1 and action.
  57.        The default method costs 1 for every step in the path.
  58.  
  59.        :param c: cost of the path to get up to state1
  60.        :param state1: given current state
  61.        :param action: action that needs to be done
  62.        :param state2: state to arrive to
  63.        :return: cost of the path after executing the action
  64.        :rtype: float
  65.        """
  66.         return c + 1
  67.  
  68.     def value(self):
  69.         """For optimization problems, each state has a value.
  70.        Hill-climbing and related algorithms try to maximize this value.
  71.  
  72.        :return: state value
  73.        :rtype: float
  74.        """
  75.         raise NotImplementedError
  76.  
  77.  
  78. """
  79. Definition of the class for node structure of the search.
  80. The class Node is not inherited
  81. """
  82.  
  83.  
  84. class Node:
  85.     def __init__(self, state, parent=None, action=None, path_cost=0):
  86.         """Create node from the search tree,  obtained from the parent by
  87.        taking the action
  88.  
  89.        :param state: current state
  90.        :param parent: parent state
  91.        :param action: action
  92.        :param path_cost: path cost
  93.        """
  94.         self.state = state
  95.         self.parent = parent
  96.         self.action = action
  97.         self.path_cost = path_cost
  98.         self.depth = 0  # search depth
  99.         if parent:
  100.             self.depth = parent.depth + 1
  101.  
  102.     def __repr__(self):
  103.         return "<Node %s>" % (self.state,)
  104.  
  105.     def __lt__(self, node):
  106.         return self.state < node.state
  107.  
  108.     def expand(self, problem):
  109.         """List the nodes reachable in one step from this node.
  110.  
  111.        :param problem: given problem
  112.        :return: list of available nodes in one step
  113.        :rtype: list(Node)
  114.        """
  115.         return [self.child_node(problem, action)
  116.                 for action in problem.actions(self.state)]
  117.  
  118.     def child_node(self, problem, action):
  119.         """Return a child node from this node
  120.  
  121.        :param problem: given problem
  122.        :param action: given action
  123.        :return: available node  according to the given action
  124.        :rtype: Node
  125.        """
  126.         next_state = problem.result(self.state, action)
  127.         return Node(next_state, self, action,
  128.                     problem.path_cost(self.path_cost, self.state,
  129.                                       action, next_state))
  130.  
  131.     def solution(self):
  132.         """Return the sequence of actions to go from the root to this node.
  133.  
  134.        :return: sequence of actions
  135.        :rtype: list
  136.        """
  137.         return [node.action for node in self.path()[1:]]
  138.  
  139.     def solve(self):
  140.         """Return the sequence of states to go from the root to this node.
  141.  
  142.        :return: list of states
  143.        :rtype: list
  144.        """
  145.         return [node.state for node in self.path()[0:]]
  146.  
  147.     def path(self):
  148.         """Return a list of nodes forming the path from the root to this node.
  149.  
  150.        :return: list of states from the path
  151.        :rtype: list(Node)
  152.        """
  153.         x, result = self, []
  154.         while x:
  155.             result.append(x)
  156.             x = x.parent
  157.         result.reverse()
  158.         return result
  159.  
  160.     """We want the queue of nodes at breadth_first_search or
  161.    astar_search to not contain states-duplicates, so the nodes that
  162.    contain the same condition we treat as the same. [Problem: this can
  163.    not be desirable in other situations.]"""
  164.  
  165.     def __eq__(self, other):
  166.         return isinstance(other, Node) and self.state == other.state
  167.  
  168.     def __hash__(self):
  169.         return hash(self.state)
  170.  
  171.  
  172. """
  173. Definitions of helper structures for storing the list of generated, but not checked nodes
  174. """
  175.  
  176.  
  177. class Queue:
  178.     """Queue is an abstract class/interface. There are three types:
  179.        Stack(): Last In First Out Queue (stack).
  180.        FIFOQueue(): First In First Out Queue.
  181.        PriorityQueue(order, f): Queue in sorted order (default min-first).
  182.    """
  183.  
  184.     def __init__(self):
  185.         raise NotImplementedError
  186.  
  187.     def append(self, item):
  188.         """Adds the item into the queue
  189.  
  190.        :param item: given element
  191.        :return: None
  192.        """
  193.         raise NotImplementedError
  194.  
  195.     def extend(self, items):
  196.         """Adds the items into the queue
  197.  
  198.        :param items: given elements
  199.        :return: None
  200.        """
  201.         raise NotImplementedError
  202.  
  203.     def pop(self):
  204.         """Returns the first element of the queue
  205.  
  206.        :return: first element
  207.        """
  208.         raise NotImplementedError
  209.  
  210.     def __len__(self):
  211.         """Returns the number of elements in the queue
  212.  
  213.        :return: number of elements in the queue
  214.        :rtype: int
  215.        """
  216.         raise NotImplementedError
  217.  
  218.     def __contains__(self, item):
  219.         """Check if the queue contains the element item
  220.  
  221.        :param item: given element
  222.        :return: whether the queue contains the item
  223.        :rtype: bool
  224.        """
  225.         raise NotImplementedError
  226.  
  227.  
  228. class Stack(Queue):
  229.     """Last-In-First-Out Queue."""
  230.  
  231.     def __init__(self):
  232.         self.data = []
  233.  
  234.     def append(self, item):
  235.         self.data.append(item)
  236.  
  237.     def extend(self, items):
  238.         self.data.extend(items)
  239.  
  240.     def pop(self):
  241.         return self.data.pop()
  242.  
  243.     def __len__(self):
  244.         return len(self.data)
  245.  
  246.     def __contains__(self, item):
  247.         return item in self.data
  248.  
  249.  
  250. class FIFOQueue(Queue):
  251.     """First-In-First-Out Queue."""
  252.  
  253.     def __init__(self):
  254.         self.data = []
  255.  
  256.     def append(self, item):
  257.         self.data.append(item)
  258.  
  259.     def extend(self, items):
  260.         self.data.extend(items)
  261.  
  262.     def pop(self):
  263.         return self.data.pop(0)
  264.  
  265.     def __len__(self):
  266.         return len(self.data)
  267.  
  268.     def __contains__(self, item):
  269.         return item in self.data
  270.  
  271.  
  272. class PriorityQueue(Queue):
  273.     """A queue in which the minimum (or maximum) element is returned first
  274.     (as determined by f and order). This structure is used in
  275.     informed search"""
  276.  
  277.     def __init__(self, order=min, f=lambda x: x):
  278.         """
  279.        :param order: sorting function, if order is min, returns the element
  280.                      with minimal f (x); if the order is max, then returns the
  281.                      element with maximum f (x).
  282.        :param f: function f(x)
  283.        """
  284.         assert order in [min, max]
  285.         self.data = []
  286.         self.order = order
  287.         self.f = f
  288.  
  289.     def append(self, item):
  290.         bisect.insort_right(self.data, (self.f(item), item))
  291.  
  292.     def extend(self, items):
  293.         for item in items:
  294.             bisect.insort_right(self.data, (self.f(item), item))
  295.  
  296.     def pop(self):
  297.         if self.order == min:
  298.             return self.data.pop(0)[1]
  299.         return self.data.pop()[1]
  300.  
  301.     def __len__(self):
  302.         return len(self.data)
  303.  
  304.     def __contains__(self, item):
  305.         return any(item == pair[1] for pair in self.data)
  306.  
  307.     def __getitem__(self, key):
  308.         for _, item in self.data:
  309.             if item == key:
  310.                 return item
  311.  
  312.     def __delitem__(self, key):
  313.         for i, (value, item) in enumerate(self.data):
  314.             if item == key:
  315.                 self.data.pop(i)
  316.  
  317.  
  318. """
  319. Uninformed graph search
  320. The main difference is that here we do not allow loops,
  321. i.e. repetition of states
  322. """
  323.  
  324.  
  325. def graph_search(problem, fringe):
  326.     """Search through the successors of a problem to find a goal.
  327.      If two paths reach a state, only use the best one.
  328.  
  329.    :param problem: given problem
  330.    :param fringe: empty queue
  331.    :return: Node
  332.    """
  333.     closed = {}
  334.     fringe.append(Node(problem.initial))
  335.     while fringe:
  336.         node = fringe.pop()
  337.         if problem.goal_test(node.state):
  338.             return node
  339.         if node.state not in closed:
  340.             closed[node.state] = True
  341.             fringe.extend(node.expand(problem))
  342.     return None
  343.  
  344.  
  345. def breadth_first_graph_search(problem):
  346.     """Search the shallowest nodes in the search tree first.
  347.  
  348.    :param problem: given problem
  349.    :return: Node
  350.    """
  351.     return graph_search(problem, FIFOQueue())
  352.  
  353.  
  354. class Football(Problem):
  355.     def __init__(self, initial, goal=None):
  356.         super().__init__(initial, goal)
  357.  
  358.     def actions(self, state):
  359.         return self.successor(state).keys()
  360.  
  361.     def result(self, state, action):
  362.         return self.successor(state)[action]
  363.  
  364.     def goal_test(self, state):
  365.         ball_pos = state[1]
  366.         return ball_pos in self.goal
  367.  
  368.     @staticmethod
  369.     def check_valid(state, opponents):
  370.         man_pos = state[0]
  371.         ball_pos = state[1]
  372.         #print(ball_pos)
  373.         return man_pos[0] >= 0 and man_pos[0] < 8 and \
  374.             man_pos[1] >= 0 and man_pos[1] < 6 and \
  375.             ball_pos[0] >= 0 and ball_pos[0] < 8 and \
  376.             ball_pos[1] >= 0 and ball_pos[1] < 6 and ball_pos not in \
  377.             ((2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2), (4, 3), (4, 4), (3, 5), (3, 6), (4, 5), (4, 6),(5, 4), (5, 5), (5, 6))
  378.  
  379.     def successor(self, state):
  380.         successors = dict()
  381.  
  382.         man_pos = state[0]
  383.         ball_pos = state[1]
  384.         opp_pos = state[2]
  385.  
  386.         if self.check_valid(((man_pos[0], man_pos[1]+1), ball_pos), opp_pos):
  387.             successors["Pomesti coveche gore"] = ((man_pos[0], man_pos[1]+1), ball_pos, opp_pos)
  388.  
  389.         if self.check_valid(((man_pos[0], man_pos[1]-1), ball_pos), opp_pos):
  390.             successors["Pomesti coveche dolu"] = ((man_pos[0], man_pos[1]-1), ball_pos, opp_pos)
  391.  
  392.         if self.check_valid(((man_pos[0] + 1, man_pos[1]), ball_pos), opp_pos):
  393.             successors["Pomesti coveche desno"] = ((man_pos[0] + 1, man_pos[1]), ball_pos, opp_pos)
  394.  
  395.         if self.check_valid(((man_pos[0] + 1, man_pos[1] + 1), ball_pos), opp_pos):
  396.             successors["Pomesti coveche gore-desno"] = ((man_pos[0] + 1, man_pos[1] + 1), ball_pos, opp_pos)
  397.  
  398.         if self.check_valid(((man_pos[0]+1, man_pos[1]-1), ball_pos), opp_pos):
  399.             successors["Pomesti coveche dolu-desno"] = ((man_pos[0] + 1, man_pos[1] - 1), ball_pos, opp_pos)
  400.  
  401.         if man_pos[0] == ball_pos[0] and man_pos[1] == ball_pos[1] - 1 and self.check_valid(
  402.                 ((man_pos[0], man_pos[1] + 1), (ball_pos[0], ball_pos[1] + 1)), opp_pos):
  403.             successors["Turni topka gore"] = ((man_pos[0], man_pos[1] + 1), (ball_pos[0], ball_pos[1] + 1), opp_pos)
  404.  
  405.         if man_pos[0] == ball_pos[0] and man_pos[1] == ball_pos[1] + 1 and self.check_valid(
  406.                 ((man_pos[0], man_pos[1] - 1), (ball_pos[0], ball_pos[1] - 1)), opp_pos):
  407.             successors["Turni topka dolu"] = ((man_pos[0], man_pos[1] - 1), (ball_pos[0], ball_pos[1] - 1), opp_pos)
  408.  
  409.         if man_pos[1] == ball_pos[1] and man_pos[0] == ball_pos[0] - 1 and self.check_valid(
  410.                 ((man_pos[0] + 1, man_pos[1]), (ball_pos[0] + 1, ball_pos[1])), opp_pos):
  411.             successors["Turni topka desno"] = ((man_pos[0] + 1, man_pos[1]), (ball_pos[0] + 1, ball_pos[1]), opp_pos)
  412.  
  413.         if man_pos[1] == ball_pos[1] - 1 and man_pos[0] == ball_pos[0] - 1 and self.check_valid(
  414.                 ((man_pos[0] + 1, man_pos[1] + 1), (ball_pos[0] + 1, ball_pos[1] + 1)), opp_pos):
  415.             successors["Turni topka gore-desno"] = ((man_pos[0] + 1, man_pos[1] + 1), (ball_pos[0] + 1, ball_pos[1] + 1), opp_pos)
  416.  
  417.         if man_pos[1] == ball_pos[1] + 1 and man_pos[0] == ball_pos[0] - 1 and self.check_valid(
  418.                 ((man_pos[0] + 1, man_pos[1] - 1), (ball_pos[0] + 1, ball_pos[1] - 1)), opp_pos):
  419.             successors["Turni topka dolu-desno"] = ((man_pos[0] + 1, man_pos[1] - 1), (ball_pos[0] + 1, ball_pos[1] - 1), opp_pos)
  420.  
  421.         return successors
  422.  
  423.  
  424. if __name__ == '__main__':
  425.     man_pos = tuple(map(int, input().split(',')))
  426.     ball_pos = tuple(map(int, input().split(',')))
  427.  
  428.     opponents = ((3, 3), (5, 4))
  429.  
  430.     goal_state = ((7, 2), (7, 3))
  431.  
  432.     football = Football((man_pos, ball_pos, opponents), goal_state)
  433.  
  434.     answer = breadth_first_graph_search(football)
  435.     if answer is None:
  436.         print("None")
  437.     else:
  438.         print(answer.solution())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement