コード例 #1
0
def bf_paths(graph: Dict[int, Dict[str, int]],
             starting_room: int) -> Dict[int, List[str]]:
    qq = Queue()
    visited = set()
    qq.enqueue([starting_room])

    paths = {(starting_room, starting_room): [starting_room]}

    while qq.size > 0:
        path: List[int] = qq.dequeue()
        room = path[-1]

        if room not in visited:

            visited.add(room)
            for move, nextroom in graph[room].items():
                path_copy = path.copy()
                path_copy.append(nextroom)
                qq.enqueue(path_copy)

                paths[(starting_room,
                       nextroom)] = paths[(starting_room, room)] + [move]

    paths = {key: val[1:] for key, val in paths.items()}
    return paths
コード例 #2
0
    def test_length(self):
        queue = Queue()
        self.assertEqual(0, len(queue))
        self.assertIs(queue.first, queue.last)

        queue.enqueue(4)
        self.assertIs(queue.first, queue.last)
        self.assertEqual(1, len(queue))
コード例 #3
0
def test_primitives():
    queue = Queue()
    with pytest.raises(NotImplementedError):
        queue.head
    with pytest.raises(NotImplementedError):
        queue.tail
    with pytest.raises(NotImplementedError):
        queue.enqueue('a')
    with pytest.raises(NotImplementedError):
        queue.dequeue()
コード例 #4
0
    def test_dequeue(self):
        """retrait d'un item à la fin de la file"""
        queue = Queue()
        for i in range(5):
            queue.enqueue(i)

        self.assertEqual(5, len(queue))

        for i in range(5):
            self.assertEqual(i, queue.dequeue())
コード例 #5
0
    def bfs(self,
            start: Vertex,
            process_vertex_early: Callable[[Vertex], Any] = None,
            process_vertex_late: Callable[[Vertex], Any] = None,
            process_edge: Callable[[Vertex, Edgenode], Any] = None,
            discovered_vertices: NodeList = None,
            processed_vertices: NodeList = None,
            is_edge_processable: Callable[[Vertex, Edgenode], bool] = None):
        """Breadth-First Search
        returns the graph of processed vertices - one single connected component"""
        process_vertex_early = process_vertex_early if process_vertex_early else lambda v: None
        process_vertex_late = process_vertex_late if process_vertex_late else lambda v: None
        process_edge = process_edge if process_edge else lambda v, e: None
        is_edge_processable = is_edge_processable if is_edge_processable else lambda v, e: True

        vertices = [v for v in self.adjacency_lists]
        self.parent_edges = NodeList(vertices=vertices)  # reinit parents
        discovered = NodeList(
            vertices=vertices
        ) if discovered_vertices is None else discovered_vertices  # added to stack
        processed = NodeList(
            vertices=vertices
        ) if processed_vertices is None else processed_vertices  # processed and out of stack
        discovered[start] = True

        queue = Queue(implementation='doubly_linked_list')
        queue.enqueue(start)
        while True:
            try:
                vertex = queue.dequeue()
            except QueueEmptyError:
                break
            processed[vertex] = True
            process_vertex_early(vertex)
            adjacency_list = self.adjacency_lists[vertex]
            for edgenode in adjacency_list.edgenodes:
                if is_edge_processable(vertex, edgenode):
                    next_vertex = edgenode.tail
                    if not processed[next_vertex] or self.directed:
                        process_edge(vertex, edgenode)
                    if not discovered[next_vertex]:
                        discovered[next_vertex] = True
                        self.parent_edges[next_vertex] = edgenode.to_edge(
                            head=vertex)
                        queue.enqueue(next_vertex)
            process_vertex_late(vertex)
        processed_vertices = [v for v in processed if processed[v]]
        processed_edges = []
        for processed_vertex in processed_vertices:
            adjacency_list = self.adjacency_lists[processed_vertex]
            for edgenode in adjacency_list.edgenodes:
                processed_edges.append(edgenode.to_edge(head=processed_vertex))
        return Graph(vertices=processed_vertices,
                     edges=processed_edges,
                     directed=self.directed)
コード例 #6
0
def hotpotate(namelist, num):
    queue = Queue()
    for name in namelist:
        queue.enqueue(name)

    while queue.size() > 1:
        for i in range(num):
            queue.enqueue(queue.dequeue())
        queue.dequeue()

    return queue.dequeue()
コード例 #7
0
def mergesort(items: Sequence[KeyedItem], order=None) -> None:
    """O(n*log n)"""
    comp = lambda x, y: x > y if order == 'max' else x < y
    stack = Stack(implementation='linked_list')

    class StackItem:
        def __init__(self, low, high, status=0):
            self.low = low
            self.high = high
            self.status = status

    stack_item = StackItem(0, len(items) - 1)

    while True:
        low = stack_item.low
        high = stack_item.high
        if low != high:
            median = (low + high) // 2
            if not stack_item.status:
                # sort left
                stack_item.status = 1
                stack.push(stack_item)
                stack.push(StackItem(low, median))
            elif stack_item.status == 1:
                # sort right
                stack_item.status = 2
                stack.push(stack_item)
                stack.push(StackItem(median + 1, high))
            else:
                # merge
                left_queue = Queue(implementation='doubly_linked_list')
                for i in range(low, median+1):
                    left_queue.enqueue(items[i])
                right_queue = Queue(implementation='doubly_linked_list')
                for i in range(median+1, high+1):
                    right_queue.enqueue(items[i])
                for i in range(low, high + 1):
                    if not left_queue.head:
                        items[i] = right_queue.dequeue()
                    elif not right_queue.head:
                        items[i] = left_queue.dequeue()
                    else:
                        if comp(left_queue.head.key, right_queue.head.key):
                            items[i] = left_queue.dequeue()
                        else:
                            items[i] = right_queue.dequeue()
        try:
            stack_item = stack.pop()
        except StackEmptyError:
            break
コード例 #8
0
def bfs(g, start: Vertex):
    start.setDistance(0)
    start.setPred(None)
    vertQueue = Queue()
    vertQueue.enqueue(start)
    while (vertQueue.size() > 0):
        currentVert = vertQueue.dequeue()
        for nbr in currentVert.getConnections():
            if (nbr.getColor() == 'white'):
                nbr.setColor('gray')
                nbr.setDistance(currentVert.getDistance() + 1)
                nbr.setPred(currentVert)
                vertQueue.enqueue(nbr)
        currentVert.setColor('black')
コード例 #9
0
def test_linked_list_implementation():
    queue = Queue(implementation='doubly_linked_list')
    a, b, c, d = list('abcd')
    assert queue.head is None
    assert queue.tail is None
    queue.enqueue(a)
    assert queue.head is a
    assert queue.tail is a
    assert queue.dequeue() is a
    assert queue.head is None
    assert queue.tail is None
    queue.enqueue(b)
    queue.enqueue(c)
    assert queue.head is b
    assert queue.tail is c
    assert queue.dequeue() is b
    assert queue.head is c
    assert queue.tail is c
    queue.enqueue(d)
    assert queue.head is c
    assert queue.tail is d
    assert queue.dequeue() is c
    assert queue.head is d
    assert queue.tail is d
    assert queue.dequeue() is d
    assert queue.head is None
    assert queue.tail is None
コード例 #10
0
def BFSPuzzle(startNode):
    temp = copy.deepcopy(startNode)
    myQueue = Queue()
    myQueue.enqueue(temp)
    #temp = copy.deepcopy(myQueue.dequeue())
    puzzleStateList = []
    puzzleStateList.append(temp.numbers)

    while myQueue.size() > 0:
        temp = myQueue.dequeue()

        temp1 = copy.deepcopy(temp)  # upMovement Temp Node
        temp2 = copy.deepcopy(temp)  # downMovement Temp Node
        temp3 = copy.deepcopy(temp)  #leftMovement Temp Node
        temp4 = copy.deepcopy(temp)  # rightMovement Temp Node

        if temp.numbers == [1, 2, 5, 6, 3, 4, 7, 8, 0]:  # targetNode
            temp.toString()
            print("Arbol Genealogico")
            temp.familyTree()  #BackTrace family tree route from target to root
            print(len(puzzleStateList))
            input()
        else:  # looks for all possible movements and adds to the queue the ones that are not in the list yet
            if temp1.moveUp() != 0 and temp1.numbers not in puzzleStateList:
                temp1.setParent(temp)
                puzzleStateList.append(temp1.numbers)
                myQueue.enqueue(temp1)
            if temp2.moveDown() != 0 and temp2.numbers not in puzzleStateList:
                temp2.setParent(temp)
                puzzleStateList.append(temp2.numbers)
                myQueue.enqueue(temp2)
            if temp3.moveLeft() != 0 and temp3.numbers not in puzzleStateList:
                temp3.setParent(temp)
                puzzleStateList.append(temp3.numbers)
                myQueue.enqueue(temp3)
            if temp4.moveRight() != 0 and temp4.numbers not in puzzleStateList:
                temp4.setParent(temp)
                puzzleStateList.append(temp4.numbers)
                myQueue.enqueue(temp4)
コード例 #11
0
    def test_enqueue(self):
        """ajout d'un item au début de la file"""
        queue = Queue()
        self.assertEqual(0, len(queue))

        queue.enqueue(5)
        self.assertIs(queue.first, queue.last)
        self.assertEqual(1, len(queue))

        queue.enqueue(7)
        self.assertEqual(2, len(queue))
        self.assertIsNot(queue.first, queue.last)
        self.assertIs(queue.first.next(), queue.last)

        # il reste 1 élément
        self.assertEqual(5, queue.dequeue())
        self.assertIs(queue.first, queue.last)

        # il reste aucun élément
        self.assertEqual(7, queue.dequeue())
        self.assertIsNone(queue.first)
        self.assertIsNone(queue.last)
コード例 #12
0
def simulation(num_seconds, pages_perminute):
    lab_printer = Printer(pages_perminute)
    print_queue = Queue()
    waiting_times = []

    for current_second in range(num_seconds):
        if new_print_task():
            print(current_second)
            task = Task(current_second)
            print_queue.enqueue(task)

        if (not lab_printer.busy()) and (not print_queue.isEmpty()):
            next_task = print_queue.dequeue()
            print('cs', current_second)
            print('ts', next_task.time_stamp)
            waiting_times.append(next_task.wait_time(current_second))
            lab_printer.start_next(next_task)

        lab_printer.tick()
    print(waiting_times)
    average_wait = sum(waiting_times) / len(waiting_times)
    print("Average wait %6.2f secs %3d tasks remaining." %
          (average_wait, print_queue.size()))
コード例 #13
0
    def test_remove(self):
        queue = Queue()

        queue.enqueue(1)
        self.assertEqual(1, len(queue))
コード例 #14
0
ファイル: dice.py プロジェクト: Sultaneous/gamzia
class DiceResolver:
    def __init__(self):

        # BEDMAS ==> d()!^/%*+-
        # PEMDAS ==> d()!^*/%+-
        # Precedence weighting reflects rule; higher means priority
        # Close bracket ')' not included; it is a special case (collapses stack to '(')
        self.precedence = {
            "(": 0,
            "+": 3,
            "-": 3,
            "/": 5,
            "*": 5,
            "%": 5,
            "C": 5,
            "c": 5,
            "^": 7,
            "!": 8,
            "d": 9
        }

        # 's' is a stack used for rearranging infix arguments
        self.s = Stack()

        # 'q' is a queue used to store the postfix arguments
        self.q = Queue()
        self.error = False

    # Converts a valid infix expression (mathematical expression)
    # to postfix using Reverse Polish Notation (RPN). Infix exp-
    # ression must be valid; this function can not check validi-
    # ty.  Note that by design, this only supports integer expr-
    # ession (no floating point support). FP support can be add-
    # ed if while building numbers, the '.' character is accepted.

    # Example: Expression="1 + 2 * 3"  --> 7, NOT 9
    # RPN="1 2 3 * +"  --> 7
    # Note that the order of operations is preserved in the RPN.
    def infixToRPN(self, expression):

        # Since a number may be multiple characters, we start with an empty string,
        # and while each character is numeric, we append the number until a non-
        # numeric value is encountered.
        num = ""

        # Tokenize expression character by character
        for c in expression:
            token = str(c)

            # Case: we had accumulated a number but this character is not a
            # numeric value; so save accumulated number, and reset accumulator.
            if (num != "" and not token.isnumeric()):
                self.q.enqueue(num)
                num = ""

            # We aren't a number; so handle the token
            # '(' start brackets are simply markers of what point to return to when
            # a ')' close bracket is encountered.
            if (token == "("):
                self.s.push(token)

            # Special case; we look for this first -> it means we have to pop all
            # previous values off stack into the RPN queue until we find the '('
            elif (token == ")"):
                # pop up until the bracket
                while (self.s.peek() != "("):
                    self.q.enqueue(self.s.pop())

                # pop the bracket / throw it away (it was just a marker, we're done with it)
                self.s.pop()

            # Casee: operator handling
            # we are done handling brackets, check for a valid operator
            elif (token in self.precedence):
                while self.s.size() != 0 and (self.precedence[token] <=
                                              self.precedence[self.s.peek()]):
                    self.q.enqueue(self.s.pop())
                self.s.push(token)

            # Case: character is numeric.
        # Append to accumulator and continue parsing
            elif (token.isnumeric()):
                num += token

        # Did token end on a number? If so store accumulated number in RPN queue
        if (num != ""):
            self.q.enqueue(num)

        # Now pop items from stack to the queue to cleanup
        while (self.s.size() != 0):
            self.q.enqueue(self.s.pop())

        # At this point, we have a valid RPN in the 'q' queue
        # (if the infix expression was valid)
        # Let's return a string version:
        q_cp = self.q.copy()

        rpn = ""
        for c in q_cp:
            rpn += c + " "
        return (rpn)

    # Routine to calculate a factorial
    def factorial(self, value):
        if (value < 0):
            return (0)
        elif (value == 0 or value == 1):
            return (1)
        elif (value == 2):
            return (2)

        product = value

        for x in range(2, value):
            product = product * x
        return (product)

    # Routine to calculate "choose" (combinatorics)
    # Formula:
    # nCr (n Choose r) = n! / r!(n-r)!
    def choose(self, n, r):
        numerator = self.factorial(n)
        denominator = self.factorial(r) * self.factorial(n - r)

        # Sanity
        if (denominator == 0):
            return (0)

        # Compute
        # NOTE: Should always be an integer result, but cast
        # it anyways to be safe
        return (int(numerator / denominator))

    # Given left value, right value, and an operator, calculate.
    def calculate(self, left, right, op):
        if (op == "+"):
            return (left + right)

        elif (op == "-"):
            return (left - right)

        elif (op == "*"):
            return (left * right)

        elif (op == "/"):
            return (int(left / right))

        elif (op == "^"):
            return (left**right)

        elif (op == "%"):
            return (left % right)

        elif (op == "!"):
            return (self.factorial(left))

        elif (op == "c" or op == "C"):
            return (self.choose(left, right))

        # dice roll; handled with 'random'
        # NOTE: expressions without 'd' are deterministic;
        # expressions with 'd' are non-deterministic (variable
        # outcomes).
        elif (op == "d"):
            sum = 0

            # Left value is number of rolls; right value is die
            # IE 3d6 = 3 rolls of a 6 sided die, summed.
            for i in range(left):
                sum += random.randint(1, right)
            return (sum)

        # whoops shouldn't have happened try to be graceful
        return (0)

    # Nifty little stack and queue algorithm for evaluating
    # the RPN.  Expects a valid RPN expression.
    def evaluateRPN(self):
        workstack = Stack()

        # As we pull tokens from the queue, we validate them and if neither a number
        # nor an operator, we abort with an error.
        for t in self.q.copy():
            if (t in self.precedence):
                # As we work backwards, right value is first; validate
                right = workstack.pop()
                if (not str(right).isnumeric()
                        and not right in self.precedence):
                    self.error = True
                    break

                # Now get left value, validate
                # Special case: ! only takes one argument. Make them identical
                if (t == "!"):
                    left = right
                else:
                    left = workstack.pop()
                    if (not str(left).isnumeric()
                            and not left in self.precedence):
                        self.error = True
                        break

                # Both valid, so calculate
                workstack.push(self.calculate(left, right, t))
            else:
                workstack.push(int(t))

        # answer is now on the stack
        if (not self.error):
            return (workstack.pop())
        else:
            return (0)

    # One function to handle it all. How Pythonic.
    def resolve(self, expression, repeat=False):
        if not repeat:
            self.error = False
            self.q.clear()
            self.s.clear()
            self.infixToRPN(expression)
            return (self.evaluateRPN())
        else:
            # Repeat=True
            # This allows repeat dice rolls / calculations, without rebuilding
            # the RPN queue each time.
            return (self.evaluateRPN())

    # Heuristic to calculate expression distribution, ment to be
    # used with dice rolls (ie, 2d6).  This is done by repeating rolls
    # to a cap of n trials, then assessing the results.
    # Returns a histogram report with trial results, mean and mode.
    def getHistogram(self, expression, trials):
        # Validate min/max boundaries
        if (trials < 0):
            trials = 1
        elif (trials > 1000000):
            trials = 1000000

        # Initialize
        sb = ""
        rolls = dict()
        sum = 0
        pct = 1.0
        max = dict()
        result = dict()

        # Build
        for i in range(trials):
            if i == 0:
                roll = self.resolve(expression)
            else:
                # We already built the RPN, don't waste cycles
                # reuilding it on every iteration, set repeat=True.
                roll = self.resolve(expression, repeat=True)

            # Track the recurrences of roll values
            if (roll in rolls.keys()):
                rolls[roll] += 1
            else:
                rolls[roll] = 1

        # Nifty way to build a key sorted report
        keys = list(rolls.keys())
        keys.sort()

        # Report
        sb = f"DISTRIBUTION HISTORGRAM ({trials:,} trials):\n"
        max[0] = max[1] = 0
        for key in keys:
            result[key] = rolls[key]
            sum += key * rolls[key]
            pct = float(rolls[key]) / float(trials, ) * 100.0
            if (pct > max[0]):
                max[0] = pct
                max[1] = key

            sb += f"[{key:3}] ==> {rolls[key]:,} ({pct:.2f}%)\n"

            # Stash pct for later
            rolls[key] = pct

        mean = float(sum) / float(trials) + 0.5
        sb += f"Mean: {mean:.2f}\n"
        mode = max[1]
        sb += f"Mode: {mode}\n\n"

        # Scaling calculation uses a lambda function
        scale = lambda x, y: int(float(x / 100) * float(y) + 0.5)

        # Build histogram pictogragh
        pic = "PICTORIAL HISTOGRAM:\n"
        for key in keys:
            pic += f"[{key:3}] "
            for i in range(scale(rolls[key], 160)):
                pic += "*"
            pic += "\n"

        # Send back the report
        return (sb + pic)