Instructions for trainInventory

(produced at 11:22 a.m. UTC on 2024-03-10)

This task is part of project07 which is due at 23:00 EDT on 2024-03-15.

You have the option to work with a partner on this task if you wish. Working with a partner requires more work to coordinate schedules, but if you work together and make sure that you are both understanding the code you write, you will make progress faster and learn more.

You can download the starter code for this task using this link.

You can submit this task using this link.

Put all of your work for this task into the file trainInventory.py
(you will create this file from scratch)

Overview

In this task, you will practice nested loops by implementing a program to manage inventory on trains. Each train is represented as a list of train cars, and each train car is a list of tuples indicating the name and total weight (in kilograms) of each item stored in that car. For example, the following train is carrying grain in one car and some furniture in another.

train = [
    [('grain', 100000)],
    [('chairs', 2000), ('sofas', 2300), ('chairs', 1000), ('tables', 4000)]
]

We've written it split across multiple lines for easy reading, but note that if you printed it, it would appear on one line.

Functions to Define

Note that as usual, we require that you include docstrings in every function and we expect that you will complete the project faster if you write these first, before you start to write any code.

Part A: Printing the inventory

Your first goal is define a function printInventory that displays the inventory in a train split across multiple lines of output so that it's easier to read. It takes a single argument, which is a train (i.e., a list of lists of tuples which contain strings an numbers). It must use print to display the contents of the train such that

  • Each train car is labeled as 'Car #' followed by the index of that car (starting from 0).
  • After each train car label, the items in that car appear on separate lines, with their weight first, then the suffix 'kg', and finally their name. Each item starts with two spaces of indentation (whereas the car names aren't indented).

These printInventory examples demonstrate how it should work.

Notes:

  • Your printInventory function must use a nested loop
  • You can test printInventory and the other trainInventory functions by running the file test_trainInventory.py.

Part B: Summing weights

Next, you must define a function totalWeightOf which, given a train and a specific item name, counts the total weight of items with that name anywhere on the train. Remember that each item is stored as a tuple with a name and a weight; you need to add up those weights, but only for items whose name matches.

These totalWeightOf examples demonstrate how it should work.

Notes:

Part C: Listing items

Define a function listItems which, given a train and a specific item name, returns a list containing each item with that name from throughout the train. Remember that each item is stored as a tuple with a name and a weight, your goal here is to create a list containing all such tuples whose names match the specified name. The items in the list should appear in the same order that they appear in the train.

These listItems examples demonstrate how it should work.

Notes:

Part D: Listing the weight of each car

Define a function listWeights which, given a train, returns a list containing the total weight of each car in the train. Remember that each item is stored as a tuple with a name and a weight, your goal here is to sum up the weights within each car, and then append those sums to a list.

These listWeights examples demonstrate how it should work.

Notes:

Part E: Finding the heaviest car

Write a function heaviestCar which when given a train, returns the index within that train of the heaviest single car, or the index of the earliest heaviest car if several are tied for heaviest. Although you may choose to use a nested loop to solve this problem, you do not have to.

These heaviestCar examples demonstrate how it should work.

Part F: Inventory by weight

First, you must write a function itemWeight which when given an item (a tuple containing a name and a weight) returns the weight of that item (just the second part of the tuple). This function should be one line of code; you will use it as a sort key later.

Next, write a function inventoryByWeight which when given a train, returns a list containing all of the items on the train, sorted by their weights.

These itemWeight examples and inventoryByWeight examples show how both functions should work.

Notes:

Ungraded Challenges

If you'd like completely optional and un-graded challenges, we've included some tests in the test_trainInventory.py file which will test the following functions:

Challenge A: Repacking Cars

A function named repackCars can be written which takes a train and a weight limit, and then tries to re-pack the items from the train into new cars so that each of them is below the weight limit. When a single item from the original train is above the weight limit, it should be put into its own car, and the items should maintain their order (which might result in a less-than-optimal solution).

Essentially, you should grab items from the first train, starting with the first item in the first car and continuing in order, and throw them into a new car until it would go over the weight limit, at which point you throw the item you're considering into a new train car and start to fill the new car in the same manner.

Challenge B: Removing Items

A function called removeItems can be written which takes a train and an item name, and removes all items with that name from the train, putting them into a separate list which it returns, sorted by weight. It needs to both return the sorted list and modify the original train.

This is quite challenging to do correctly and is not part of the rubric for this task, so only attempt it if you want an extra challenge. As a hint, it will be useful to iterate using a backwards index loop as part of this problem.

Examples

printInventory examples

These examples demonstrate how printInventory should word. Note the indentation and added units ('kg').

In []:
printInventory( [ [('grain', 100000)], [('chairs', 2000), ('sofas', 2300), ('chairs', 1000), ('tables', 4000)], ] )
Prints
Car #0 100000 kg grain Car #1 2000 kg chairs 2300 kg sofas 1000 kg chairs 4000 kg tables
In []:
printInventory( [ [('electronics', 2000), ('cloth', 40000), ('toys', 8000)], [('racoons', 8), ('opossum', 5), ('rabbits', 37), ('deer', 82)], [('steel', 22000), ('iron', 45000), ('cobalt', 12000)], [('helium', 4000), ('electronics', 50)], ] )
Prints
Car #0 2000 kg electronics 40000 kg cloth 8000 kg toys Car #1 8 kg racoons 5 kg opossum 37 kg rabbits 82 kg deer Car #2 22000 kg steel 45000 kg iron 12000 kg cobalt Car #3 4000 kg helium 50 kg electronics

totalWeightOf examples

These examples demonstrate how totalWeightOf should word.

In []:
totalWeightOf( [ [('grain', 100000)], [('chairs', 2000), ('sofas', 2300), ('chairs', 1000), ('tables', 4000)], ], 'grain' )
Out[]:
100000
In []:
totalWeightOf( [ [('grain', 100000)], [('chairs', 2000), ('sofas', 2300), ('chairs', 1000), ('tables', 4000)], ], 'chairs' )
Out[]:
3000
In []:
totalWeightOf( [ [('electronics', 2000), ('cloth', 40000), ('toys', 8000)], [('racoons', 8), ('opossum', 5), ('rabbits', 37), ('deer', 82)], [('steel', 22000), ('iron', 45000), ('cobalt', 12000)], [('helium', 4000), ('electronics', 50)], ], 'electronics' )
Out[]:
2050

listItems examples

These examples demonstrate how listItems should word. Note that items are listed in the same order they appear in within the train.

In []:
listItems( [ [('grain', 100000)], [('chairs', 2000), ('sofas', 2300), ('chairs', 1000), ('tables', 4000)], ], 'chairs' )
Out[]:
[('chairs', 2000), ('chairs', 1000)]
In []:
listItems( [ [('wheat', 122000)], [('wheat', 148000)], [('semolina', 90000)], [('semolina', 93000)], [('semolina', 89000)], [('spelt', 91000), ('barley', 24000)], ], 'barley' )
Out[]:
[('barley', 24000)]
In []:
listItems( [ [('electronics', 2000), ('cloth', 40000), ('toys', 8000)], [('racoons', 8), ('opossum', 5), ('rabbits', 37), ('deer', 82)], [('steel', 22000), ('iron', 45000), ('cobalt', 12000)], [('helium', 4000), ('electronics', 50)], ], 'electronics' )
Out[]:
[('electronics', 2000), ('electronics', 50)]

listWeights examples

These examples demonstrate how listWeights should word.

In []:
listWeights( [ [('grain', 100000)], [('chairs', 2000), ('sofas', 2300), ('chairs', 1000), ('tables', 4000)], ] )
Out[]:
[100000, 9300]
In []:
listWeights( [ [('wheat', 122000)], [('wheat', 148000)], [('semolina', 90000)], [('semolina', 93000)], [('semolina', 89000)], [('spelt', 91000), ('barley', 24000)], ] )
Out[]:
[122000, 148000, 90000, 93000, 89000, 115000]
In []:
listWeights( [ [('electronics', 2000), ('cloth', 40000), ('toys', 8000)], [('racoons', 8), ('opossum', 5), ('rabbits', 37), ('deer', 82)], [('steel', 22000), ('iron', 45000), ('cobalt', 12000)], [('helium', 4000), ('electronics', 50)], ] )
Out[]:
[50000, 132, 79000, 4050]

heaviestCar examples

These examples demonstrate how heaviestCar should word. Note that the return value is an index, starting from 0.

In []:
heaviestCar( [ [('grain', 100000)], [('chairs', 2000), ('sofas', 2300), ('chairs', 1000), ('tables', 4000)], ] )
Out[]:
0
In []:
heaviestCar( [ [('wheat', 122000)], [('wheat', 148000)], [('semolina', 90000)], [('semolina', 93000)], [('semolina', 89000)], [('spelt', 91000), ('barley', 24000)], ] )
Out[]:
1
In []:
heaviestCar( [ [('electronics', 2000), ('cloth', 40000), ('toys', 8000)], [('racoons', 8), ('opossum', 5), ('rabbits', 37), ('deer', 82)], [('steel', 22000), ('iron', 45000), ('cobalt', 12000)], [('helium', 4000), ('electronics', 50)], ] )
Out[]:
2

itemWeight examples

These examples demonstrate how itemWeight should word.This function is very simple, but it needs to be defined as a function in order to be used as a sort key.

In []:
itemWeight(('chairs', 2000))
Out[]:
2000
In []:
itemWeight(('helium', 40000))
Out[]:
40000

inventoryByWeight examples

These examples demonstrate how inventoryByWeight should word. Note that items are sorted by their weights, and multiple entries with the same name are NOT merged.

In []:
inventoryByWeight( [ [('grain', 100000)], [('chairs', 2000), ('sofas', 2300), ('chairs', 1000), ('tables', 4000)], ] )
Out[]:
[ ('chairs', 1000), ('chairs', 2000), ('sofas', 2300), ('tables', 4000), ('grain', 100000), ]
In []:
inventoryByWeight( [ [('electronics', 2000), ('cloth', 40000), ('toys', 8000)], [('racoons', 8), ('opossum', 5), ('rabbits', 37), ('deer', 82)], [('steel', 22000), ('iron', 45000), ('cobalt', 12000)], [('helium', 4000), ('electronics', 50)], ] )
Out[]:
[ ('opossum', 5), ('racoons', 8), ('rabbits', 37), ('electronics', 50), ('deer', 82), ('electronics', 2000), ('helium', 4000), ('toys', 8000), ('cobalt', 12000), ('steel', 22000), ('cloth', 40000), ('iron', 45000), ]

Rubric

Group goals:
 
unknown All functions are documented
Each function you define must include a non-empty documentation string as the very first thing in the function.
 
unknown printInventory must print the correct output
The output printed when your printInventory function is run must match the solution output.
 
unknown totalWeightOf must return the correct result
The result returned when your totalWeightOf function is run must match the solution result.
 
unknown listItems must return the correct result
The result returned when your listItems function is run must match the solution result.
 
unknown listItems must not modify the train.
We will call listItems to make sure it does not alter values in the train it is given.
 
unknown listWeights must return the correct result
The result returned when your listWeights function is run must match the solution result.
 
unknown listWeights must not modify the train.
We will call listWeights to make sure it does not alter values in the train it is given.
 
unknown heaviestCar must return the correct result
The result returned when your heaviestCar function is run must match the solution result.
 
unknown itemWeight must return the correct result
The result returned when your itemWeight function is run must match the solution result.
 
unknown inventoryByWeight must return the correct result
The result returned when your inventoryByWeight function is run must match the solution result.
 
unknown totalWeightOf must return the correct result
The result returned when your totalWeightOf function is run must match the solution result.
 
unknown itemWeight must return the correct result
The result returned when your itemWeight function is run must match the solution result.
 
unknown heaviestCar must return the correct result
The result returned when your heaviestCar function is run must match the solution result.
 
unknown Define printInventory
Use def to define printInventory
 
unknown Use any kind of loop
Within the definition of printInventory, use any kind of loop in at least one place.
 
unknown Use any kind of loop
Within the loop within the definition of printInventory, use any kind of loop in at least one place.
 
unknown Call print
Within the definition of printInventory, call print in at least one place.
 
unknown Define totalWeightOf
Use def to define totalWeightOf
 
unknown Use any kind of loop
Within the definition of totalWeightOf, use any kind of loop in at least one place.
 
unknown Use any kind of loop
Within the loop within the definition of totalWeightOf, use any kind of loop in at least one place.
 
unknown Define listItems
Use def to define listItems
 
unknown Use any kind of loop
Within the definition of listItems, use any kind of loop in at least one place.
 
unknown Use any kind of loop
Within the loop within the definition of listItems, use any kind of loop in at least one place.
 
unknown Define listWeights
Use def to define listWeights
 
unknown Use any kind of loop
Within the definition of listWeights, use any kind of loop in at least one place.
 
unknown Use any kind of loop
Within the loop within the definition of listWeights, use any kind of loop in at least one place.
 
unknown Define heaviestCar
Use def to define heaviestCar
 
unknown Define itemWeight with 1 parameter
Use def to define itemWeight with 1 parameter
 
unknown Do not use any kind of loop
Within the definition of itemWeight with 1 parameter, do not use any kind of loop.
 
unknown Define inventoryByWeight
Use def to define inventoryByWeight
 
unknown Use any kind of loop
Within the definition of inventoryByWeight, use any kind of loop in at least one place.
 
unknown Use any kind of loop
Within the loop within the definition of inventoryByWeight, use any kind of loop in at least one place.