Exercises: tuples, sets, dictionaries, and files
Module 6: records and files
Name:
Student number:
Choose one answer for each multiple-choice question. Complete the state trace table. Present algorithms in pseudocode, a flowchart, or Python. Explain representation choices using words, tables, sketches, or pseudocode; short code examples are optional. Follow any answer-form requirement in the individual question. Show the reasoning and checks requested in each question.
M1) Number or not?
In Listing 1, we have four versions of a Python function split_values_per_type that receives a list of values and splits them into two lists: one with the numbers and another with the non-numbers. The function should return the two lists as the tuple (numbers, non_numbers).
For this question, a value is numeric exactly when type(value) in (int, float) is True. Therefore, integers and floating-point values are numeric, while strings and Boolean values are non-numeric.
Which implementation of split_values_per_type in Listing 1 correctly splits every input value and returns (numbers, non_numbers)?
split_values_per_type(values)must return its two result lists as a tuple. For example, input[2, "X"]should produce([2], ["X"]); empty input should produce([], []).type(value)returns the value’s type:type(2)isint,type(2.5)isfloat, andtype(True)isbool.values.append(item)adds one item to the end of that list and returnsNone. For example, appending"B"to["A"]changes it to["A", "B"].
M2) Splitting a tuple
In Listing 2, a program creates a tuple and splits it into two tuples.
Python tuple indices are zero-based. A slice includes its starting index but excludes its stopping index. Therefore, arr1[:b] contains the items before index b, while arr1[b:] starts with the item at index b.
arr1, and prints the two resulting tuples (Question 2).
What is printed when the code in Listing 2 is executed?
1: (True, False, False) / 2: (True, False, False)1: (0, 10, 20) / 2: (30, 40, 50)1: (0, 10, 20) / 2: (0, 10, 20)1: (30, 40, 50) / 2: (0, 10, 20)
len(sequence)returns its number of items;len((4, 8, 12))is3.- For integer operands,
//performs floor division: it divides and rounds the result down to an integer. For example,7 // 2is3. printdisplays its arguments separated by spaces and ends with a new line. For example,print("Value:", 8)displaysValue: 8.
M3) Replacing negative tuple values
A measurement tuple contains integers. zero_negatives(values) must return a tuple with the same length and order, replacing each negative value with 0 and retaining every other value. The input tuple must remain unchanged.
For values = (1, -2, 3, -4, 5), the required result is (1, 0, 3, 0, 5). Empty input must return ().
Compare the four implementations in Listing 3.
Which implementation satisfies the stated requirements?
len(values)returns the number of items.range(stop)visits integers from0up to, but excluding,stop:list(range(2))is[0, 1].listcollects values into a new list, andrange(0)is empty.result.append(value)adds one value to the end of the list and returnsNone; appending6to[4]changes it to[4, 6].tuple(result)creates a tuple containing the list’s items in order:tuple([4, 6])is(4, 6).
M4) Sorted distinct values
A table contains integer measurements. The function in Listing 4 retains only values from 1 through 10, removes duplicates, and returns its result in ascending order.
sorted returns a list in ascending order.
What is printed by Listing 4?
[1, 2, 7, 9, 10][7, 2, 11, 10, 1, 2, 9][2, 0, 0, 0, 0, 0, 2, 0, 1, 1][7, 2, 11, -1, 10, 1, 2, 9, 7, 0, -1]
bounded_distinct(table)receives a nested list of integers and returns a sorted list of distinct values in the inclusive range1through10. For example,bounded_distinct([[3, 3, 12]])returns[3], andbounded_distinct([])returns[].set()creates an empty set.found.add(value)adds a value and returnsNone; adding4twice still leaves only one4in the set.sorted(values)returns a new list in ascending order without changing the input:sorted({4, 2})is[2, 4].print(value)displays the value and ends with a new line.
M5) Distinct labels in encounter order
In Listing 5, we have a Python function range_to_string that receives a rectangular range represented as a nested list of strings and returns a comma-separated string.
range_to_string that returns the unique values from a two-dimensional list as a comma-separated string. The join method concatenates the strings in unique_values with commas (Question 5).
[["A", "D"], ["1", "1"], ["C", "A"]].
| A | B | |
|---|---|---|
| 1 | A | D |
| 2 | 1 | 1 |
| 3 | C | A |
What is returned by range_to_string when it receives the nested list represented in Table 1?
A,1,C,D,1,AA,1,C,DA,D,1,CA,D,1,1,C,A
range_to_string(cell_range)must return distinct labels in the order they are first encountered, one row at a time. For example,range_to_string([["X", "X"], ["Y", "X"]])should return"X,Y".set()creates an empty set.seen.add(value)adds a value once and returnsNone; adding"X"again does not create another member.unique_values.append(value)adds one item to the end of the list and returnsNone.",".join(values)returns the strings joined by commas:",".join(["X", "Y"])is"X,Y", and joining[]returns"".
M6) Glasses for face shape
An example glasses app recommends a frame style using a fixed rule. In this app, Round maps to Aviator, Oval to Wayfarer, and Square to Round.
Figure 1 illustrates these three rules with display mannequins. The face outline identifies the input category, and the frames show the style the app should return.
The app supports English, Spanish, and Dutch. For example, the English input Round should yield Aviator, the Spanish input Redonda should yield Aviador, and the Dutch input Rond should yield Aviator.
The dictionary in Table 2 stores the greeting and recommendation message for each language.
LANGUAGE_MESSAGES.
| Message type | Language | Message |
|---|---|---|
| greeting | EN | Hello! What is your face shape? Options: Round, Oval, Square. |
| greeting | ES | ¡Hola! ¿Cuál es la forma de tu cara? Opciones: Redonda, Ovalada, Cuadrada. |
| greeting | NL | Hallo! Wat is de vorm van je gezicht? Opties: Rond, Ovaal, Vierkant. |
| recommendation | EN | Based on your face shape, we recommend the style of glasses: |
| recommendation | ES | Según la forma de tu cara, recomendamos las gafas de estilo: |
| recommendation | NL | Op basis van de vorm van je gezicht, raden we de brilstijl aan: |
The list in Table 3 stores face shapes and frame styles in one three-record block per language. offset is the zero-based index of the first record in the selected block.
FRAME_ROWS. The offset is the index of the first item in the selected language block.
| List index | Face shape | Language | Glasses style |
|---|---|---|---|
| 0 | Round | EN | Aviator |
| 1 | Oval | EN | Wayfarer |
| 2 | Square | EN | Round |
| 3 | Redonda | ES | Aviador |
| 4 | Ovalada | ES | Wayfarer |
| 5 | Cuadrada | ES | Redonda |
| 6 | Rond | NL | Aviator |
| 7 | Ovaal | NL | Wayfarer |
| 8 | Vierkant | NL | Rond |
The complete message dictionary and frame list are supplied in Listing 6 and Listing 7.
LANGUAGE_MESSAGES = {
"EN": {
"greeting": (
"Hello! What is your face shape? Options: "
"Round, Oval, Square."
),
"recommendation": (
"Based on your face shape, we recommend "
"the style of glasses:"
),
},
"ES": {
"greeting": (
"¡Hola! ¿Cuál es la forma de tu cara? "
"Opciones: Redonda, Ovalada, Cuadrada."
),
"recommendation": (
"Según la forma de tu cara, recomendamos "
"las gafas de estilo:"
),
},
"NL": {
"greeting": (
"Hallo! Wat is de vorm van je gezicht? "
"Opties: Rond, Ovaal, Vierkant."
),
"recommendation": (
"Op basis van de vorm van je gezicht, "
"raden we de brilstijl aan:"
),
},
}FRAME_ROWS = [
{
"face_shape": "Round",
"language": "EN",
"style": "Aviator",
},
{
"face_shape": "Oval",
"language": "EN",
"style": "Wayfarer",
},
{
"face_shape": "Square",
"language": "EN",
"style": "Round",
},
{
"face_shape": "Redonda",
"language": "ES",
"style": "Aviador",
},
{
"face_shape": "Ovalada",
"language": "ES",
"style": "Wayfarer",
},
{
"face_shape": "Cuadrada",
"language": "ES",
"style": "Redonda",
},
{
"face_shape": "Rond",
"language": "NL",
"style": "Aviator",
},
{
"face_shape": "Ovaal",
"language": "NL",
"style": "Wayfarer",
},
{
"face_shape": "Vierkant",
"language": "NL",
"style": "Rond",
},
]The function recommend_glasses in Listing 8 selects the language block and prepares two messages. Its call to find_glasses uses one of the four implementations in Listing 9. To run the example, first run both data listings, define one of those implementations, and then run the main listing.
recommend_glasses function receives the language, face shape, message dictionary, and frame list, and returns two messages. It normalizes the language code, selects the start of the corresponding three-item block, and calls find_glasses.
def recommend_glasses(
language, face, texts, frames
):
language = language.strip().upper()
if language == "EN":
offset = 0
elif language == "ES":
offset = 3
else:
# Other language codes use the Dutch block.
language = "NL"
offset = 6
style = find_glasses(
face, offset, frames
)
greeting = texts[language]["greeting"]
prompt = texts[language]["recommendation"]
return greeting, f"{prompt} {style}"
greeting, result = recommend_glasses(
"ES", " REDONDA ",
LANGUAGE_MESSAGES, FRAME_ROWS,
)
print(greeting)
print(result)Compare the four implementations of find_glasses in Listing 9. The input may include extra whitespace or use a different letter case. A shape absent from the selected block must produce "No matching glasses style found.".
find_glasses (Question 6).
def find_glasses(
face, offset, frames
):
shape = face.strip().lower()
row1 = frames[offset]
row2 = frames[offset + 1]
row3 = frames[offset + 2]
if shape == (
row1["face_shape"]
.strip().lower()
):
return row1["style"]
elif shape == (
row2["face_shape"]
.strip().lower()
):
return row2["style"]
elif shape == (
row3["face_shape"]
.strip().lower()
):
return row3["style"]
else:
return (
"No matching glasses "
"style found."
)Which pair of implementations correctly retrieves the frame style for the supplied face shape in its language block?
find_glasses(face, offset, frames)should return the frame style forfacein the three records starting atoffsetinframes. For example,find_glasses("Oval", 0, FRAME_ROWS)should return"Wayfarer". If the shape is absent, it should return"No matching glasses style found.".recommend_glasses(language, face, texts, frames)returns the greeting and completed recommendation as a tuple of two strings. It receives a language code, a face shape, the message dictionary, and the frame list. Language codes other than"EN"and"ES"select the Dutch block. With English and"Oval", the recommendation ends in"Wayfarer".text.strip()removes leading and trailing whitespace;text.lower()andtext.upper()return lowercase and uppercase copies. For example," OVAL ".strip().lower()is"oval", and"es".upper()is"ES".range(start, stop)visits integers fromstartup to, but excluding,stop. For example,list(range(2, 4))is[2, 3].list(values)collects the supplied values in a list. For example,list((2, 3))is[2, 3].print(message)displays a message and ends with a new line. For example,print("Hello!")displaysHello!.- An f-string inserts values into text; with
style = "Round",f"Style: {style}"produces"Style: Round".
M7) Payback period calculation for warehouse design projects
You are comparing seven warehouse projects that require an investment in Material Handling Equipment (MHE). For this exercise, the company accepts a project when its payback period is at most 3.0 years, including exactly 3.0 years.
The payback period is calculated by dividing the initial investment by the annual profit generated by the equipment:
\[ \text{Payback period} = \frac{\text{Initial investment}}{\text{Annual profit}} \]
This period represents the time it takes (in years) for the project to recover the initial investment through the annual profits generated.
The supplied Python function payback_years(investment, profit) in Listing 10 takes an initial investment and annual profit in the same currency and returns the payback period in years. Both amounts are positive. For example, payback_years(50_000, 20_000) returns 2.5.
payback_years to compute the payback period for MHE projects based on the initial investment and annual profit.
The supplied function is_viable_project(years, limit_years) in Listing 11 takes two numbers measured in years:
years: the calculated payback period for one project.limit_years: the company’s maximum acceptable payback period.
It returns the Boolean value True when the project meets this payback criterion, and False otherwise. Both inputs are nonnegative.
For example, with a limit of 4.0 years, is_viable_project(2.5, 4.0) returns True, is_viable_project(4.0, 4.0) returns True, and is_viable_project(4.5, 4.0) returns False. The function checks the supplied limit; it does not calculate the payback period.
Table 4 gives the investment and annual profit for each project.
| Project name | Initial investment | Annual profit |
|---|---|---|
| Automated Guided Vehicles (AGVs) | 500,000 | 150,000 |
| Forklift Fleet Upgrade | 300,000 | 100,000 |
| Automated Storage and Retrieval System (AS/RS) | 1,200,000 | 400,000 |
| Conveyor System Installation | 400,000 | 120,000 |
| Pallet Shuttle System | 700,000 | 200,000 |
| Voice Picking System | 150,000 | 50,000 |
| Robotic Palletizers | 800,000 | 250,000 |
The same input is stored as a list of dictionary records in Listing 12. Each record uses the fields name, initial_investment, and annual_profit.
projects = [
{
"name": "Automated Guided Vehicles (AGVs)",
"initial_investment": 500_000,
"annual_profit": 150_000,
},
{
"name": "Forklift Fleet Upgrade",
"initial_investment": 300_000,
"annual_profit": 100_000,
},
{
"name": (
"Automated Storage and Retrieval "
"System (AS/RS)"
),
"initial_investment": 1_200_000,
"annual_profit": 400_000,
},
{
"name": "Conveyor System Installation",
"initial_investment": 400_000,
"annual_profit": 120_000,
},
{
"name": "Pallet Shuttle System",
"initial_investment": 700_000,
"annual_profit": 200_000,
},
{
"name": "Voice Picking System",
"initial_investment": 150_000,
"annual_profit": 50_000,
},
{
"name": "Robotic Palletizers",
"initial_investment": 800_000,
"annual_profit": 250_000,
},
]Use the fixed setting in Listing 13 for every project. Both supplied functions are available to all four implementations.
Compare the four implementations in Listing 14. Each starts with an empty results list. Append one dictionary per project with these fields:
name: the project’s name.payback_period: its calculated payback period in years.viable: the Boolean result returned byis_viable_project.
Which implementation correctly processes every project using the fixed limit_years and appends its result to results?
results.append(record) adds one complete record at the list’s end and returns None. Starting with results = [], results.append({"name": "AGVs"}) leaves results as [{"name": "AGVs"}].
M8) Rating frequencies in a dictionary
A transportation service lets customers rate a trip in a five-star app. In this example, customers may submit any integer from 0 through 5, including a zero-star rating.
As Figure 2 shows, each submitted rating is added to a list in arrival order. The first three customers submit 0, 2, and 3, so the list begins [0, 2, 3, ...]. Repeated ratings remain separate entries.
get_frequency(ratings) summarizes that list as a dictionary:
- The keys are all six possible ratings, from
0through5. - Each value counts how often its rating appears, including a count of
0for an unused rating. - An empty input list produces all six keys with counts of
0.
For the complete example [0, 2, 3, 1, 4, 2, 5, 3, 1, 2], the required result is {0: 1, 1: 2, 2: 3, 3: 2, 4: 1, 5: 1}. For instance, rating 2 appears three times, so its dictionary entry is 2: 3.
Compare the four implementations in Listing 15.
Which implementation satisfies the stated requirements?
range(stop)gives integers from0up to, excluding,stop.range(start, stop)begins atstart.range(0)is empty.list(values)collects the supplied values into a list. For example,list(range(3))is[0, 1, 2], andlist(range(2, 4))is[2, 3].len(ratings)returns the number of entries, including repeats:len([2, 2, 5])is3.
M9) Counting missing record values
A list contains dictionary records. Apply these requirements to count_empty(records):
- Count every None value across all records.
- Do not count
0or an empty string; both are recorded values. - Every key is present. Count missing values, not absent keys.
- No variable named
worksheetis defined.
The example in Listing 16 has three missing values. record.values() visits the values stored in one dictionary.
Compare the four implementations in Listing 17.
Which implementation satisfies the stated requirements?
record.values()provides the dictionary’s stored values without its keys and leaves it unchanged. An empty dictionary has no values to visit.list(values)collects visited values into a list. Forrecord = {"X": 4, "Y": None},list(record.values())gives[4, None].
M10) Copying dictionary records within a threshold
A table is stored as a list of dictionaries. The first dictionary contains the column labels; every later dictionary contains an experiment ID and a numeric KPI (a measured performance value). copy_below_threshold(t, table) must return a new table containing a copied header followed by a copy of every data record whose KPI is less than or equal to t. It must preserve input order, record structure, and the input table.
The example in Listing 18 has threshold 0.7. Its required output contains the header and experiment IDs 1, 3, and 5. record.copy() creates a new dictionary with the same keys and values.
Compare the four implementations in Listing 19.
Which implementation satisfies the stated requirements?
record.copy()returns a new dictionary with the same keys and values. Forrecord = {"id": 8, "kpi": 0.4}, its copy is{"id": 8, "kpi": 0.4}. The records here contain only numbers or strings.record.items()visits(key, value)pairs: a record{"id": 8}yields the pair("id", 8).result.append(item)adds one item to the end of the list and returnsNone.- A slice
table[1:]selects every item from position1onward without changingtable.
M11) Finding a value in a text file
A text file named values.txt contains one integer per line, in the order shown in Listing 21. It has no header or blank lines. All file operations succeed. The supplied helper in Listing 20 reads the file; the function in Listing 22 searches the returned lines in file order.
What is printed by Listing 22?
45-10
read_lines(path)receives the path of an existing UTF-8 text file and returns its lines in file order as a list of strings. For a separate file containing8and3on two lines, it returns["8\n", "3\n"].file.readlines()reads all remaining lines. Each string retains its ending newline, when present; a final line without one remains unchanged. An empty file returns[].open(path, "r", encoding="utf-8")opens the file for reading and returns a file object. Thewithblock closes it beforeread_linesreturns. The returned list remains available to the caller.- Assume every line represents an integer, with no header or blank lines, and all file operations succeed.
int("8\n")returns the integer8. find_in_file(path, value)receives the file path and the integer to find. It returns the first matching zero-based position or-1if absent. For a separate file containing8,3, and8on three lines, searching for8returns0, and searching for9returns-1. An empty file returns-1.len(lines)counts the lines;range(stop)visits0throughstop - 1, andrange(0)is empty.print(value)displays the value and a new line.
M12) Writing a Markdown report
Markdown is a lightweight markup language with plain-text formatting syntax. It is often used to format README files, write messages in online discussion forums, and create rich text using a plain-text editor. Listing 23 presents a main function that tests a function matrix_to_markdown that converts a matrix and headers (see Figure 3) to a Markdown table (see Figure 3 (b)).
matrix_to_markdown function to convert the matrix and headers shown in Figure 3 (a) into the Markdown table shown in Figure 3 (b).
The main function does the following:
- Calls the
read_datafunction to return the supplied nested listdata. - Initializes the list
headerswith the table headers:OrderId,OrderLine, andQuantity. - Calls the
matrix_to_markdownfunction to convert the matrix and headers to Markdown format (as shown in Figure 3 (b)) and writes the result toorders.md, replacing any existing contents. The file is closed on leaving thewithblock. All file operations succeed.
List headers:
\[ \begin{bmatrix} OrderId & OrderLine & Quantity \end{bmatrix}. \]
Nested list data:
\[ \begin{bmatrix} 1 & 1 & 2 & 2 & 3 & 3 \\ A & B & A & B & A & B \\ 10 & 20 & 15 & 25 & 30 & 40 \end{bmatrix}. \]
The nested list has three outer items, one for each attribute. Each inner list contains the values of that attribute for the six data points. Therefore, attributes are selected with the first index and data points with the second index.
main function to test the matrix_to_markdown function (columns represent data points and rows represent attributes).
matrix_to_markdown function should transform the input data and headers (as shown in Figure 3 (a)) into a Markdown table (as shown in Figure 3 (b)).
In Listing 25, we have four alternative implementations of the matrix_to_markdown function. The function receives a nested list data and a list headers with the column headers and returns a string in Markdown format representing the table. It should handle an empty matrix by returning an empty string. The header is created by the get_header_row function, which returns this string, including the newline after the alignment row:
See Listing 24.
Which implementation of the matrix_to_markdown function in Listing 25 correctly converts the matrix and headers (e.g., as shown in Figure 3 (a)) to the complete Markdown table written to orders.md (as shown in Figure 3 (b)) when main (in Listing 23) is executed?
matrix_to_markdown function. The function receives a nested list data and a list headers and returns a string in Markdown format representing the table. The function creates the header using get_header_row and then iterates over the data matrix to create the data rows. The string "\n" inserts a newline character (Question 12).
read_data()is a supplied helper with no arguments. It returns the complete nested list shown in Figure 3 (a); for example, its first inner list is[1, 1, 2, 2, 3, 3].get_header_row(headers)returns the Markdown header and alignment rows, with a newline after each. Withheaders = ["Item"], it returns"| Item |\n|:---:|\n".main()takes no arguments and writes the converted string toorders.md; it has no explicit return value.len(sequence)returns its number of items;len([2, 4])is2.range(stop)visits0up to, but excluding,stop;range(0)is empty.str(4)returns the string"4".open(path, "w", encoding="utf-8")opens a text file for writing, replacing its contents, and returns a file object.file.write("Hello\n")writes that text and returns its character count,6. Thewithblock closes the file when it ends.
Evaluate the bounds of the loops and the way the data matrix is accessed.
M13) Collections as dictionary keys
A dictionary stores route labels using keys that describe city names. Listing 26 defines four candidate keys: a tuple, a list, a set, and a tuple containing a list.
Which candidates can be used directly as a dictionary key, without converting them to another type? Consider each candidate separately.
pairandgrouponly.paironly.stopsandcitiesonly.- All four candidates.
M14) Converting collections to distinct values
A report needs distinct priority codes in ascending order, stored as a tuple. Listing 27 starts with a list and combines type conversions with sorting.
What are the type and value of result?
- A list with value
[1, 3, 4]. - A tuple with value
(4, 1, 4, 3, 1). - A set containing
1,3, and4. - A tuple with value
(1, 3, 4).
set(values)creates a new set containing each distinct value once; it does not preserve sequence order. For integers,set([8, 8, 6])contains8and6; an empty input gives an empty set.sorted(values)returns a new list in ascending order. It keeps duplicates:sorted([8, 6, 8])gives[6, 8, 8]; an empty input gives[].tuple(values)collects the supplied values into a tuple in their traversal order.tuple([8, 6])gives(8, 6); an empty input gives().
These operations leave their input collections unchanged. All codes here are integers, so they can be placed in a set and compared when sorting.
M16) Identifying parts of a file path
A program saves a report at the file path shown in Listing 29. Each / separates names. The first / is the root directory, the top-level folder where this path begins.
Use the definitions in Table 5 to identify the parts of the report’s path.
| Part | What to identify |
|---|---|
| Parent directory | The folder immediately containing the file, written as its complete path. |
| File name | The name after the last /, including its extension. |
| Stem | The file name with only its final suffix removed. |
| Final suffix (file extension) | The last dot and everything after it. |
Which choice correctly identifies all four parts?
- Parent
/course/reports; file nameorders.summary.csv.
Stemorders; suffix.summary.csv. - Parent
/course; file namereports/orders.summary.csv.
Stemorders.summary; suffix.csv. - Parent
/course/reports; file nameorders.summary.csv.
Stemorders.summary; suffix.csv. - Parent
/course/reports; file nameorders.summary.
Stemorders.summary.csv; suffixcsv.
- Directory separators and dots have different roles:
/separates path components, while a filename may contain several dots. - For example,
result.final.txthas the stemresult.finaland the final suffix.txt. Removing the final suffix leaves earlier dots in the stem.
M17) Using dictionary keys and values together
A workshop stores its product quantities in a dictionary named stock. Each key is a product name, and its value is the number of units available. The workshop wants at least target units of every product.
The function shortages(stock, target) identifies products that need restocking. It receives the current quantities in stock and the desired quantity per product in target. Its result must satisfy these rules:
- Include only products whose current quantity is below
target. Exclude products already at or above the target. - Use each product name as a key and the additional units needed as its value. For example,
shortages({"clips": 1}, 3)must return{"clips": 2}because two more clips are needed. - Return a new dictionary and leave
stockunchanged.
All quantities and the target are nonnegative integers. An empty stock produces {}. The order of entries does not affect the required result.
Listing 30 supplies three products and a target of 5. The required result is {"bolts": 3, "washers": 5}: bolts need three additional units, washers need five, and nuts are already at the target.
Compare the implementations in Listing 31. In each loop, name is intended to identify a product and qty its available quantity.
Which implementation satisfies all the requirements?
stock.items()is a dictionary method that takes no arguments. It returns a view that yields each(key, value)pair as a tuple when visited by a loop, without changing the dictionary. For example,{"red": 4, "blue": 7}.items()yields("red", 4)and("blue", 7); an empty dictionary yields no pairs. The view reflects changes to the dictionary, so keep its entries unchanged while this loop visits them.- In
for key, value in mapping.items():, unpacking assigns the first item of each pair tokeyand the second tovalue. For the pair("red", 4), these names receive"red"and4. Unpacking into two names requires a pair of two items.
Q1) Trace state while processing pairs
A Python program compares the integer pairs [(2, 5), (4, 1), (0, 3)], stored as tuples. In each iteration, it adds the first value to a running total and calculates first - second. It then assigns a string to status:
"first larger"when the difference is positive."equal"when the difference is zero."second larger"when the difference is negative.
The list and its tuples are inputs. Unpacking reads each tuple’s two values into first and second, in that order.
Trace the Python program in Listing 32. The comment marks the point at which you record the state.
pairs = [(2, 5), (4, 1), (0, 3)]
running_total = 0
for first, second in pairs:
running_total += first
difference = first - second
if difference > 0:
status = "first larger"
elif difference == 0:
status = "equal"
else:
status = "second larger"
# Record the state here.
print(running_total, difference, status)- Complete Table 6 at the marked checkpoint after each iteration. The first row shows how to record the values. The Total column records
running_total. - Write the final line printed by the program.
- Explain which variables carry information between iterations, which values are replaced each time, and whether reading the pairs changes them.
| Iteration | Pair | first |
second |
Total | Difference | Status |
|---|---|---|---|---|---|---|
| 1 | (2, 5) |
2 | 5 | 2 | -3 | "second larger" |
| 2 | (4, 1) |
|||||
| 3 | (0, 3) |
print displays its arguments separated by spaces and ends with a new line. For example, print(4, -2, "second larger") displays 4 -2 second larger. It returns None and leaves the displayed values unchanged.
Q2) Represent and query origin-destination records
The origin is the warehouse where a shipment departs; the destination is the warehouse where it arrives. An origin-destination (OD) pair names these two warehouses in that order. A to B and B to A are different pairs. Table 7 contains four fictional shipment records.
| Origin | Destination | Shipments |
|---|---|---|
| A | B | 12 |
| B | A | 7 |
| A | C | 0 |
| C | A | 4 |
Each pair occurs once. Include the recorded zero when finding or printing pairs. Work with recorded pairs, rather than every possible combination of warehouses. Pairs from a warehouse to itself are outside this task. Any result order is acceptable.
- Propose one data structure and show how it stores these four records. You may use a list, a dictionary, or a matrix stored as a list of lists.
- Present algorithms in pseudocode, a flowchart, or Python for the four queries in Table 8. Each query uses your stored records and leaves them unchanged.
| Query | Additional input | Required result |
|---|---|---|
| a. Print all known OD pairs | None | Print each recorded origin, destination, and count; with no records, print nothing |
| b. Find destinations of an origin | An origin | All destinations in its recorded pairs; an empty collection if none |
| c. Find origins of a destination | A destination | All origins in its recorded pairs; an empty collection if none |
| d. Find a specific OD pair | An origin and destination | Its shipment count, including zero, or Unknown if unrecorded |
Q3) Design a reusable housing-search skill
You are creating an agentic solution to search for rental houses in the Netherlands. The orchestrator below is already defined in Listing 33.
Input: Path, Criteria, Email
Output: One email
Start
Set Websites to Call Read Sites(Path)
Set Matches to an empty list
For each Website in Websites
Set Offers to Call Get Offers(Website)
For each Offer in Offers
Set Accepted to Call Check Offer(
Offer, Criteria)
If Accepted is Yes Then
Append Offer to Matches
End If
End For
End For
Set Selected to Call Select Three(Matches)
Call Send Summary(Email, Selected)
EndImplement the real estate agent’s
Check Offer(Offer, Criteria)in pseudocode or a flowchart. Its two inputs are:Offer: one house record containing its city, monthly rent in euros, area in square meters, and webpage URL.Criteria: the required city, maximum monthly rent, and minimum area.
Return Yes only when all three rules hold:
- The offer’s city matches the required city.
- Its rent is at most the maximum monthly rent.
- Its area is at least the minimum area.
Otherwise, return No. Rent and area equal to their limits are accepted. Leave both inputs unchanged.
The orchestrator receives a text-file path (Path), the student’s email address (Email), and Criteria. Assume valid inputs and successful operations. Every offer is currently available and appears once across all websites.
These operations are already defined.
Read Sites(Path)reads website addresses from the text file. It returns a list in line order, trims spaces, skips blank lines, and closes the file without changing it. An empty file returns an empty list.Get Offers(Website)retrieves today’s available offers from one website address. It returns offer records in listing order without changing the website. A website with no offers returns an empty list.Select Three(Matches)receives a list of matching offers and returns a new list of up to three offers ordered by lowest rent. Equal rents keep encounter order. It leaves the input unchanged; an empty list gives an empty list.Send Summary(Email, Selected)receives an email address and a list of selected offers. It sends one summary email containing each offer’s city, rent, area, and URL in list order. With an empty list, the summary saysNo matching houses found.It returns no value and leaves the list unchanged.
Listing 34 shows the website file sites.txt.
Read Sites("sites.txt")returns the two addresses in file order.Get Offers("https://one.example")returns A01, A02, and A03 from Table 9, in that order.Select Three([A01, B01])returns B01 then A01 because B01 has lower rent.Send Summary("student@example.test", [])sends one email sayingNo matching houses found.
- For city
Enschede, maximum monthly rent1000euros, and minimum area40m², use the offers in Table 9. Which three houses will appear in the email, and in what order? Briefly justify your selection.
| Site | House | City | Rent (EUR/month) | Area (m²) |
|---|---|---|---|---|
| 1 | A01 | Enschede | 900 | 50 |
| 1 | A02 | Enschede | 1000 | 40 |
| 1 | A03 | Enschede | 850 | 35 |
| 2 | B01 | Enschede | 800 | 45 |
| 2 | B02 | Utrecht | 700 | 70 |
| 2 | B03 | Enschede | 850 | 55 |
A skill stores reusable instructions for a task. An AI agent follows instructions and uses available tools. The orchestrator coordinates the search through nested loops over websites and offers; the real estate agent checks individual offers. Each role is a named procedure with explicit inputs and outputs.
A handoff delegates one offer check. The orchestrator passes the offer and criteria to the real estate agent and receives its Yes or No decision. The supplied version waits for that decision before checking the next offer.
In agentic programming, a developer uses an AI coding agent to draft a design, test it, inspect the results, and revise it. The resulting skill can be reused with another website file or different criteria.