Graph, Stack, Queue, Search
Build a graph · Use a stack · Use a queue · Then write BFS and DFS yourself
Requirements
- 6 required problems. Estimated time: 2 – 3 hours.
- Submit one Python file (
.py) per problem. - The problems go in order. 1 is the graph, 2 is the stack, 3 is the queue, and 4–6 put them together. Do them in order.
- Use a plain list as your stack and queue. Only
append(),pop()andpop(0). Do not importdequeor any other module. - Never visit a node twice. Every search must keep a record of what it has already seen.
- Output format must match the samples exactly, including spaces.
The graph used in problems 1, 5 and 6
A ------- B ------- C | | | | | | D ------- E F | GDraw this on paper before you start. Almost every mistake in this homework is a drawing mistake, not a Python mistake.
Problems
Read a graph and store it as a dict: every node name maps to a list of its neighbours. Then print the neighbours of one node, in alphabetical order.
Remember that an edge is undirected. The line A B means B is a neighbour of A and A is a neighbour of B.
Input format
First line: two integers n and m — how many nodes and how many edges.Second line: n node names.Next m lines: two node names, meaning an edge between them.Every edge works in BOTH directions.Constraint: 1 ≤ n ≤ 50Last line: one node name q.Output format
One line: the neighbours of q in alphabetical order, separated by single spaces.If q has no neighbours, print noneSample 1
Input
7 7A B C D E F GA BB CA DB EC FD EE GBOutput
A C ESample 2
Input
7 7A B C D E F GA BB CA DB EC FD EE GFOutput
CSample 3
Input
3 1A B CA BCOutput
noneRequired structure
def build_graph(names, edges): # TODO: start every name with an empty list, # then add BOTH directions for every edge passdef neighbours_of(graph, node): # TODO: return the neighbour list, sorted passfirst = input().split()n = int(first[0])m = int(first[1])names = input().split()edges = []for _ in range(m): parts = input().split() edges.append((parts[0], parts[1]))q = input().strip()graph = build_graph(names, edges)result = neighbours_of(graph, q)if len(result) == 0: print("none")else: print(" ".join(result))append twice — once on each side.A drawing program keeps a log of what you did. Every undo removes the most recent action. That makes the log a stack.
Input format
First line: one integer k — how many commands.Next k lines: either do WORD record one action undo remove the most recent actionConstraint: 1 ≤ k ≤ 100Output format
For every undo, print the action that was removed.If the log was already empty, print nothingAfter all commands, print the remaining log on one line, oldest first.If the log is empty at the end, print emptySample 1
Input
5do drawdo eraseundodo fillundoOutput
erasefilldrawSample 2
Input
2undoundoOutput
nothingnothingemptySample 3
Input
4do ado bdo cundoOutput
ca bRequired structure
k = int(input())log = []for _ in range(k): parts = input().split() if parts[0] == "do": # TODO: record parts[1] pass else: # TODO: remove and print the most recent action, # or print nothing when the log is empty pass# TODO: print the remaining log, or emptylog.pop() takes the most recent action. Always check len(log) == 0 first — popping an empty list crashes.People join the back of a line and are served from the front. Same problem shape as number 2, opposite rule. Compare your two files afterwards — only one thing changed.
Input format
First line: one integer k — how many commands.Next k lines: either join NAME the person joins the back of the line serve the person at the front is servedConstraint: 1 ≤ k ≤ 100Output format
For every serve, print the name of the person served.If the line was empty, print nobodyAfter all commands, print who is still waiting on one line, front first.If nobody is waiting, print emptySample 1
Input
6join anajoin boservejoin cyserveserveOutput
anabocyemptySample 2
Input
4join anajoin boservejoin cyOutput
anabo cySample 3
Input
2serveserveOutput
nobodynobodyemptyRequired structure
k = int(input())line = []for _ in range(k): parts = input().split() if parts[0] == "join": # TODO: parts[1] joins the BACK pass else: # TODO: serve and print the person at the FRONT, # or print nobody when the line is empty pass# TODO: print who is still waiting, or emptyappend(). Only the taking changes: pop(0) instead of pop().Put the same values into a waiting list, then empty it twice: once as a queue, once as a stack. Write one function that does both, with a mode parameter.
Input format
First line: one integer n.Second line: n values separated by spaces.Constraint: 1 ≤ n ≤ 100Output format
Two lines.Line 1: the values taken out using a QUEUE, separated by single spaces.Line 2: the values taken out using a STACK.Sample 1
Input
41 2 3 4Output
1 2 3 44 3 2 1Sample 2
Input
17Output
77Sample 3
Input
510 20 30 40 50Output
10 20 30 40 5050 40 30 20 10Required structure
def take_all(items, mode): # TODO: copy every item into a waiting list, # then empty it. "queue" takes the front, # "stack" takes the back. passn = int(input())values = input().split()print(" ".join(take_all(values, "queue")))print(" ".join(take_all(values, "stack")))while loop is identical — only the line that removes an item depends on mode.Given a graph, a start node and a goal node, print the smallest number of edges you have to walk to get from the start to the goal.
You must use a queue. A stack would still find a route, but not always the shortest one.
Input format
First line: two integers n and m — how many nodes and how many edges.Second line: n node names.Next m lines: two node names, meaning an edge between them.Every edge works in BOTH directions.Constraint: 1 ≤ n ≤ 50Last line: two node names, the start and the goal.Output format
One line: the number of edges on the shortest route.Print 0 when the start is the goal.Print -1 when there is no route at all.Sample 1
Input
7 7A B C D E F GA BB CA DB EC FD EE GA FOutput
3Sample 2
Input
7 7A B C D E F GA BB CA DB EC FD EE GA GOutput
3Sample 3
Input
7 7A B C D E F GA BB CA DB EC FD EE GA AOutput
0Sample 4
Input
4 2A B C DA BC DA DOutput
-1Required structure
def build_graph(names, edges): # TODO: same as problem 1 passdef fewest_steps(graph, start, goal): frontier = [start] steps = {start: 0} # this dict is also the "already seen" record while len(frontier) > 0: # TODO: take the OLDEST cell out of frontier # TODO: if it is the goal, return steps[current] # TODO: for every unseen neighbour, # steps[nxt] = steps[current] + 1, then add it to frontier pass return -1first = input().split()n = int(first[0])m = int(first[1])names = input().split()edges = []for _ in range(m): parts = input().split() edges.append((parts[0], parts[1]))last = input().split()graph = build_graph(names, edges)print(fewest_steps(graph, last[0], last[1]))steps does two jobs at once, exactly like came_fromin class: it stores the distance, and being a key means "already seen". Sample 4 has two separate pieces, so the queue empties without ever reaching D.Print the order in which the nodes are visited, first using a queue (BFS), then using a stack (DFS). Write one function with a mode parameter, just like problem 4.
Tie-break rule: when you add the neighbours of a node, always add them in alphabetical order. Without this rule the answer would not be unique.
Input format
First line: two integers n and m — how many nodes and how many edges.Second line: n node names.Next m lines: two node names, meaning an edge between them.Every edge works in BOTH directions.Constraint: 1 ≤ n ≤ 50Last line: one node name, the start.Output format
Two lines.Line 1: the BFS visit order, separated by single spaces.Line 2: the DFS visit order.Only nodes you can actually reach appear.Sample 1
Input
7 7A B C D E F GA BB CA DB EC FD EE GAOutput
A B D C E F GA D E G B C FSample 2
Input
7 7A B C D E F GA BB CA DB EC FD EE GFOutput
F C B A E D GF C B E G D ASample 3
Input
4 3A B C DA BA CB DAOutput
A B C DA C B DRequired structure
def build_graph(names, edges): # TODO: same as problem 1, but sort every # neighbour list before you return passdef visit_order(graph, start, mode): frontier = [start] seen = {start: True} order = [] while len(frontier) > 0: # TODO: "bfs" takes the oldest, "dfs" takes the newest # TODO: add current to order # TODO: add every unseen neighbour to seen and to frontier pass return orderfirst = input().split()n = int(first[0])m = int(first[1])names = input().split()edges = []for _ in range(m): parts = input().split() edges.append((parts[0], parts[1]))start = input().strip()graph = build_graph(names, edges)print(" ".join(visit_order(graph, start, "bfs")))print(" ".join(visit_order(graph, start, "dfs")))mode parameter instead — that single line is the whole point of this week.