An instruction such as “work out the boxes” hides several choices. Does the answer include a partially filled box? Is zero a valid order? What should happen when capacity is zero? You will turn those questions into a contract for one small function. The output describes a fictional packing plan and does not control any stock, payment or delivery service.
Documentation boundary
Python’s tutorial introduces function definitions, parameters and return values. A function call has local bindings, and a function without an explicit returned value returns None. Here the worked function returns a dictionary so the caller can inspect the answer instead of relying on printed text.
Specify the contract first
Accept items as a whole-number count of at least zero and capacity as a positive whole number. Return three named quantities: the number of completely full boxes, whether a partial box is needed, and the items in that partial box. Reject invalid types and invalid ranges. In this exercise booleans are not accepted as counts, even though they can participate in integer arithmetic in Python.
| Input pair | Full boxes | Partial boxes | Items in partial box |
|---|---|---|---|
| 14 and 6 | 2 | 1 | 2 |
| 12 and 6 | 2 | 0 | 0 |
| 0 and 6 | 0 | 0 | 0 |
| 2 and 0 | Reject | Reject | Reject |
Before coding, divide fourteen objects into groups of six on paper. Two groups use twelve objects, leaving two. For twelve objects there is no remainder, so adding a partial box would be an error. The zero-item case should produce an empty plan rather than invent a delivery. These three answers make the intended meaning of the output fields concrete.
Read the worked implementation
def pack_plan(items, capacity):
if type(items) is not int or type(capacity) is not int:
raise TypeError("whole numbers required")
if items < 0 or capacity <= 0:
raise ValueError("invalid packing range")
full, remainder = divmod(items, capacity)
return {"full": full, "partial": int(remainder > 0),
"remaining_items": remainder}
assert pack_plan(14, 6) == {"full": 2, "partial": 1, "remaining_items": 2}
assert pack_plan(12, 6)["partial"] == 0
assert pack_plan(0, 6)["full"] == 0
for bad in [(2, 0), (-1, 6)]:
try:
pack_plan(*bad)
except ValueError:
pass
else:
raise AssertionError("missing range rejection")
print(pack_plan(14, 6))
For fourteen items and capacity six, the returned dictionary contains full two, partial one and remaining_items two. The total number of boxes is three, but that is a derived quantity a caller can calculate. Keeping full and partial separate makes the plan useful for a later display without forcing every caller to parse a sentence. The function itself does not print the result.
The caller’s print statement is deliberately outside the definition. A report, command-line tool or notebook could use the same returned structure differently. To check reuse, call the function twice with different inputs and preserve both answers. Neither call should depend on a value left behind by the previous call. Write the input pair beside each answer so the two plans cannot be confused.
Repair a contract violation
A tempting shortcut always adds one to items divided by capacity. It gives three boxes for twelve items and capacity six even though two boxes fit exactly. The failed table row tells you the rule is wrong, not merely that the example needs a special case. Another shortcut catches every error and returns zeros. That makes an invalid capacity look like a valid empty order, losing information the caller needs.
Ask a reviewer to explain each returned field without reading the implementation. If the reviewer thinks remaining_items means unpacked items left on a shelf, clarify that it means items assigned to the partial box. Naming and a short contract can prevent that misunderstanding earlier than another arithmetic test. The purpose is a reusable agreement between caller and function, not the shortest possible expression.
Practise a controlled extension
Add an optional requirement to report empty slots in the partial box. For fourteen and six, that answer is four; for twelve and six, there is no partial box, so define the answer as zero. Write those expected values before extending the return structure. Do not silently change the meaning of the existing fields. A caller using the old fields should still obtain the same packing plan.
Finish with the contract, the answer table and a small record of valid and rejected calls. Include a separate attempt using a text count such as “14” and explain whether conversion belongs inside this function or in an input-reading layer. Under the stated contract it belongs outside. That boundary lets the packing calculation remain focused while another component decides how to interpret external text.
Questions for this exercise
Why return a value rather than only print it?
The tutorial distinguishes returned results from printed output. A caller can inspect a returned dictionary; a function that reaches its end without returning a value returns None.
Does fourteen with capacity six need three full boxes?
No. The worked answer is two full boxes and one partial box holding two items.
Should text counts be converted automatically?
Not under this exercise’s contract. Interpret external text before calling the packing function.
Official documentation
Explore the Courses overview or use Contact for general enquiries. This is an original INTIAU editorial self-study exercise; no qualification is awarded.
Related guides
View the study diagram

