S3Q2 · Column Totals in a Markdown Table¶
⚡ Quick Reference
Type: File-in, stdout-out
Core idea: parse the header, skip the separator, sum each column across all data rows.
import tempfile, sys
_, filename = tempfile.mkstemp(prefix="table_")
with open(filename, "w") as f:
f.write(sys.stdin.read())
def parse_row(line):
return [cell.strip() for cell in line.strip().strip("|").split("|")]
with open(filename) as f:
lines = [l for l in f if l.strip()]
headers = parse_row(lines[0])
# lines[1] is the separator - skip it
data_rows = [parse_row(l) for l in lines[2:]]
totals = [sum(int(row[i]) for row in data_rows) for i in range(len(headers))]
for header, total in zip(headers, totals):
print(f"{header}: {total}")
Key rules:
- Line 1: headers | Line 2: separator (skip) | Lines 3+: data
- Parse a row: strip the line, strip outer |, split on |, strip each cell
- Sum each column independently across all data rows
- Print in column order: header: total
Problem Statement¶
Problem (File I/O → stdout)
Read a markdown table from a file. Compute the sum of each column and print column_name: total for each column in order.
Example:
| Name | Score | Bonus |
|------|-------|-------|
| A | 10 | 5 |
| B | 20 | 3 |
| C | 15 | 7 |
Name: 0
Score: 45
Bonus: 15
Wait - Name column has non-integer values (A, B, C). The problem says all columns contain integer values. The example above is illustrative; in the actual problem all cell values will be integers.
Corrected example:
| Month | Revenue | Expenses |
|-------|---------|----------|
| 1 | 1000 | 600 |
| 2 | 1500 | 800 |
| 3 | 900 | 500 |
Month: 6
Revenue: 3400
Expenses: 1900
Parsing a markdown row¶
"| Month | Revenue | Expenses |"
Step 1 - strip() → "| Month | Revenue | Expenses |"
Step 2 - strip("|") → " Month | Revenue | Expenses "
Step 3 - split("|") → [" Month ", " Revenue ", " Expenses "]
Step 4 - strip each cell → ["Month", "Revenue", "Expenses"]
Solution approaches¶
import tempfile, sys
_, filename = tempfile.mkstemp(prefix="table_")
with open(filename, "w") as f:
f.write(sys.stdin.read())
def parse_row(line):
return [cell.strip() for cell in line.strip().strip("|").split("|")]
with open(filename) as f:
lines = [l for l in f if l.strip()]
headers = parse_row(lines[0])
data_rows = [parse_row(l) for l in lines[2:]] # skip separator at index 1
for i, header in enumerate(headers):
total = sum(int(row[i]) for row in data_rows)
print(f"{header}: {total}")
import tempfile, sys
_, filename = tempfile.mkstemp(prefix="table_")
with open(filename, "w") as f:
f.write(sys.stdin.read())
def parse_row(line):
# Remove surrounding whitespace, strip leading/trailing |, split on |
cells = line.strip().strip("|").split("|")
return [cell.strip() for cell in cells]
with open(filename) as f:
all_lines = [l for l in f.readlines() if l.strip()]
headers = parse_row(all_lines[0]) # header row
# all_lines[1] is the separator - skip
data_rows = [parse_row(l) for l in all_lines[2:]]
n_cols = len(headers)
totals = [0] * n_cols
for row in data_rows:
for i in range(n_cols):
totals[i] += int(row[i])
for header, total in zip(headers, totals):
print(f"{header}: {total}")
import tempfile, sys
_, filename = tempfile.mkstemp(prefix="table_")
with open(filename, "w") as f:
f.write(sys.stdin.read())
def parse_row(line):
return [cell.strip() for cell in line.strip().strip("|").split("|")]
with open(filename) as f:
lines = [l for l in f if l.strip()]
headers = parse_row(lines[0])
data_rows = [parse_row(l) for l in lines[2:]]
# Transpose: columns = list of column lists
columns = zip(*data_rows)
for header, col in zip(headers, columns):
print(f"{header}: {sum(int(v) for v in col)}")
zip(*data_rows) transposes the 2D list - each element of columns is a tuple of all values in that column. sum(int(v) for v in col) totals each column cleanly.
Key takeaways¶
Parse row: strip → strip("|") → split("|") → strip each cell
The four-step pipeline handles all whitespace variations: leading/trailing spaces on the line, spaces around the pipes, and spaces inside cells. Works regardless of how the table is formatted.
Skip the separator line at index 1
The second line contains |---|---| - not data. Use lines[2:] to skip it. Alternatively, detect separator lines by checking if a line contains only - and | characters.
zip(*data_rows) transposes rows to columns
zip(*rows) is the classic Python transpose - converts a list of rows into a list of columns. Paired with zip(headers, columns), it lets you process each column with its header in one clean loop.