{"id":"more-lists-matrices","slug":"matrices","title":"Matrices: rows and columns","text":"A table of numbers with rows and columns is called a **matrix**. In Python it's a list of rows, and each row is a list of numbers. Here are a café's sales for three days, one row per day and one column per product (coffee, tea and cake):\n\n```python\nsales = [\n    [14, 6, 3],\n    [20, 4, 7],\n    [11, 9, 5],\n]\n\nprint(sales[1][2])\nsales[1][2] = 8\nprint(sales[1])\n```\n\n```output\n7\n[20, 4, 8]\n```\n\nThe first index picks the row and the second the column, both counting from zero: `sales[1][2]` is the cakes of the second day. The same two indexes change one value.\n\n### Going through a matrix\n\nA `for` loop over a matrix gets one row at a time. A second loop inside the first goes through the numbers of that row:\n\n```python\nsales = [\n    [14, 6, 3],\n    [20, 4, 7],\n    [11, 9, 5],\n]\n\ntotal = 0\nfor row in sales:\n    for amount in row:\n        print(amount, end=\" \")\n        total += amount\n    print()\n\nprint(\"Total:\", total)\n```\n\n```output\n14 6 3\n20 4 7\n11 9 5\nTotal: 79\n```\n\n### A row and a column\n\nOne row is easy to get: it's `sales[0]`, a list of its own. A column is spread over all the rows, at the same index in each of them. So a function for a column goes through the rows and takes one item from each:\n\n```python\ndef row_total(matrix: list, row_index: int) -> int:\n    return sum(matrix[row_index])\n\n\ndef column_total(matrix: list, column_index: int) -> int:\n    total = 0\n    for row in matrix:\n        total += row[column_index]\n    return total\n\n\nsales = [\n    [14, 6, 3],\n    [20, 4, 7],\n    [11, 9, 5],\n]\nprint(\"Day 1:\", row_total(sales, 0))\nprint(\"Tea:\", column_total(sales, 1))\n```\n\n```output\nDay 1: 23\nTea: 19\n```\n\n### Changing every value\n\nThis attempt to multiply every number by ten changes nothing:\n\n```python\ngrid = [[1, 2], [3, 4]]\nfor row in grid:\n    for number in row:\n        number *= 10\nprint(grid)\n```\n\n```output\n[[1, 2], [3, 4]]\n```\n\n`number *= 10` changes only the variable `number`, not the list it came from. To change the list, the loop needs the indexes. With `range`, the rows go from 0 to `len(grid) - 1`, and the columns of row `i` from 0 to `len(grid[i]) - 1`:\n\n```python\ngrid = [[1, 2], [3, 4]]\nfor i in range(len(grid)):\n    for j in range(len(grid[i])):\n        grid[i][j] *= 10\nprint(grid)\n```\n\n```output\n[[10, 20], [30, 40]]\n```\n","task":"Fill in the blanks so the function `column_max(matrix, column_index)` returns the largest number in the given column. For example, `column_max([[3, 9], [7, 2], [5, 4]], 0)` returns `7`.\n","kind":"fill","seed":"def column_max(matrix: list, column_index: int) -> int:\n    largest = matrix[0][column_index]\n    for row in matrix:\n        if row[[[column_index]]] > largest:\n            largest = row[[[column_index]]]\n    return largest\n\n\nif __name__ == \"__main__\":\n    numbers = [\n        [3, 9],\n        [7, 2],\n        [5, 4],\n    ]\n    print(column_max(numbers, 0))\n","solution":"def column_max(matrix: list, column_index: int) -> int:\n    largest = matrix[0][column_index]\n    for row in matrix:\n        if row[column_index] > largest:\n            largest = row[column_index]\n    return largest\n\n\nif __name__ == \"__main__\":\n    numbers = [\n        [3, 9],\n        [7, 2],\n        [5, 4],\n    ]\n    print(column_max(numbers, 0))\n","hints":["The loop gets one row at a time. Which item of the row belongs to the column you're looking at?","The column's number is the same index in every row: `row[column_index]`."],"tests":[{"name":"column_max([[3, 9], [7, 2], [5, 4]], 0)","stdin":"","call":"column_max([[3, 9], [7, 2], [5, 4]], 0)\n","expect":"7","hidden":false,"returns":true},{"name":"column_max([[3, 9], [7, 2], [5, 4]], 1)","stdin":"","call":"column_max([[3, 9], [7, 2], [5, 4]], 1)\n","expect":"9","hidden":true,"returns":true},{"name":"column_max([[-5, 1, 0], [-2, 8, 3]], 0)","stdin":"","call":"column_max([[-5, 1, 0], [-2, 8, 3]], 0)\n","expect":"-2","hidden":true,"returns":true}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"matrix = [[1, 2, 3], [4, 5, 6]]\nmatrix[0][2] = 10\nfor row in matrix:\n    print(row[1] + row[2])\nprint(len(matrix), len(matrix[0]))\nprint(matrix[1])\n","solution":"matrix = [[1, 2, 3], [4, 5, 6]]\nmatrix[0][2] = 10\nfor row in matrix:\n    print(row[1] + row[2])\nprint(len(matrix), len(matrix[0]))\nprint(matrix[1])\n","hints":["`matrix[0][2] = 10` changes the last number of the first row, so the first row is now `[1, 2, 10]`.","The loop prints one line per row, adding the items at index 1 and 2 of that row.","`len(matrix)` is the number of rows, and `len(matrix[0])` is the number of items in the first row."],"tests":[{"name":"Output","stdin":"","expect":"12\n11\n2 3\n[4, 5, 6]","hidden":false}],"require":[],"forbid":[],"lines":["12","11","2 3","[4, 5, 6]"]},{"task":"Write a function `column_totals(matrix)` that returns a list with the sum of each column. All the rows have the same length.\n\nFor example, `column_totals([[14, 6, 3], [20, 4, 7], [11, 9, 5]])` returns `[45, 19, 15]`.\n","kind":"code","seed":"def column_totals(matrix: list) -> list:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(column_totals([[14, 6, 3], [20, 4, 7], [11, 9, 5]]))\n","solution":"def column_totals(matrix: list) -> list:\n    totals = []\n    for j in range(len(matrix[0])):\n        total = 0\n        for row in matrix:\n            total += row[j]\n        totals.append(total)\n    return totals\n\n\nif __name__ == \"__main__\":\n    print(column_totals([[14, 6, 3], [20, 4, 7], [11, 9, 5]]))\n","hints":["There are as many columns as there are items in a row, so `range(len(matrix[0]))` gives the index of every column.","For each column index, go through the rows and add up the item at that index, as `column_total` in the lesson does. Then `append` the sum to the result list.","Another way: start with a list of zeros, one per column, and add each row's numbers to it with `totals[j] += row[j]`."],"tests":[{"name":"column_totals([[14, 6, 3], [20, 4, 7], [11, 9, 5]])","stdin":"","call":"column_totals([[14, 6, 3], [20, 4, 7], [11, 9, 5]])\n","expect":"[45, 19, 15]","hidden":false,"returns":true},{"name":"column_totals([[1, 2], [3, 4], [5, 6], [7, 8]])","stdin":"","call":"column_totals([[1, 2], [3, 4], [5, 6], [7, 8]])\n","expect":"[16, 20]","hidden":true,"returns":true},{"name":"column_totals([[5, -1, 0, 2]])","stdin":"","call":"column_totals([[5, -1, 0, 2]])\n","expect":"[5, -1, 0, 2]","hidden":true,"returns":true}],"require":[],"forbid":[]}]}