#!/usr/bin/env python3
"""Advent of Code 2015, Day 2: I Was Told There Would Be No Math"""


def parse_input(text):
    """Parse a file containing box dimensions LxWxH

    Returns a list of lists of ints [[L, W, H]].
    """
    return [[int(i) for i in line.split('x')]
            for line in text.splitlines()]


def surface_area(l, w, h):
    """Return the total surface area of a box"""
    return (2 * l * w) + (2 * w * h) + (2 * h * l)


def smallest_side(l, w, h):
    """Return the area of the smallest side of a box"""
    return min([(l * w), (w * h), (h * l)])


def wrapping_paper(dimensions):
    """Return total amount of wrapping paper needed for box of size dimensions

    The total wrapping paper includes enough wrapping paper for each side of
    the box, plus slack equal to the size of the smallest side.
    """
    return surface_area(*dimensions) + smallest_side(*dimensions)


def ribbon(dimensions):
    """Return total ribbon needed for box of size dimensions

    The total ribbon is equal to twice the lengths of the shortest two
    dimensions plus the product of all three dimensions.
    """
    s1, s2, s3 = sorted(dimensions)
    return (2 * s1) + (2 * s2) + (s1 * s2 * s3)


# Dimensions, wrapping total, ribbon total
TEST_BOXES = [([2, 3, 4], 58, 34),
              ([1, 1, 10], 43, 14)]


def test_wrapping_paper():
    for dimensions, expected, _ in TEST_BOXES:
        assert wrapping_paper(dimensions) == expected


def test_ribbon():
    for dimensions, _, expected in TEST_BOXES:
        assert ribbon(dimensions) == expected


def main(puzzle_input):
    # Part one
    needed_paper = sum(wrapping_paper(box) for box in puzzle_input)
    print(f'Part one, wrapping paper: {needed_paper:,}')

    # Part two
    needed_ribbon = sum(ribbon(box) for box in puzzle_input)
    print(f'Part two, ribbon: {needed_ribbon:,}')


if __name__ == '__main__':
    with open('../input/2015-02.txt') as input_file:
        puzzle_input = parse_input(input_file.read())
    main(puzzle_input)

@@ -85,16 +85,31 @@
 ath%22%22%22%0A%0A
+import pytest%0A%0A
 %0Adef par
@@ -1221,16 +1221,137 @@
 * s3)%0A%0A%0A
+def test_parse():%0A    dimensions = '''%5C%0A2x3x4%0A1x1x10%0A'''%0A    assert parse_input(dimensions) == %5B%5B2, 3, 4%5D, %5B1, 1, 10%5D%5D%0A%0A%0A
 # Dimens
@@ -1454,24 +1454,90 @@
  43, 14)%5D%0A%0A%0A
+@pytest.mark.parametrize('dimensions,wrapping_tot,_', TEST_BOXES)%0A
 def test_wra
@@ -1548,27 +1548,16 @@
 g_paper(
-):%0A    for 
 dimensio
@@ -1564,43 +1564,30 @@
 ns, 
-expected, _ in TEST_BOXES
+wrapping_tot, _)
 :%0A    
- 
-   
 asse
@@ -1615,34 +1615,102 @@
 ensions) == 
-expected%0A%0A
+wrapping_tot%0A%0A%0A@pytest.mark.parametrize('dimensions,_,ribbon_tot', TEST_BOXES)
 %0Adef test_ri
@@ -1718,19 +1718,8 @@
 bon(
-):%0A    for 
 dime
@@ -1733,36 +1733,21 @@
  _, 
-expected in TEST_BOXES:%0A    
+ribbon_tot):%0A
     
@@ -1779,16 +1779,18 @@
  == 
-expected
+ribbon_tot
 %0A%0A%0Ad

Tidy up tests