From 0bbb2dc72c8e8920be184b8a76db7d8a134b7dc6 Mon Sep 17 00:00:00 2001 From: DanielSchuette Date: Sat, 2 Mar 2019 03:00:35 +0100 Subject: [PATCH] improve Python and Rust test coverage --- input_files/test011.txt | 3 +++ py_src/problem011.py | 25 +++++++----------- py_src/problem019.py | 55 +++++++++++++++++++++------------------ py_src/test.py | 39 +++++++++++++++++++++++++++ rust_src/src/main.rs | 3 ++- rust_src/src/tests/mod.rs | 9 ++++++- 6 files changed, 92 insertions(+), 42 deletions(-) create mode 100644 input_files/test011.txt diff --git a/input_files/test011.txt b/input_files/test011.txt new file mode 100644 index 0000000..76691e7 --- /dev/null +++ b/input_files/test011.txt @@ -0,0 +1,3 @@ +12 +34 +56 diff --git a/py_src/problem011.py b/py_src/problem011.py index f8faf85..24725af 100644 --- a/py_src/problem011.py +++ b/py_src/problem011.py @@ -17,7 +17,7 @@ import time -def parseMatrix(path): +def parse_matrix(path): """ Doc string. """ @@ -31,21 +31,19 @@ def parseMatrix(path): return matrix -def greatestProduct(matrix): +def greatest_product(matrix): """ Doc string. """ nums = [] # temp stores data - max_nums = [] # temp stores max triplet max_product = 0 # temp stores maximum product max_adjacent = 4 # number of adjacent ints to multiply # left/right for arr in matrix: for i in range(len(arr)-max_adjacent+1): - prod = multOverList(arr[i:(i+max_adjacent)]) + prod = mult_over_list(arr[i:(i+max_adjacent)]) if prod > max_product: - max_nums = arr[i:(i+max_adjacent)] max_product = prod # up/down @@ -53,9 +51,8 @@ def greatestProduct(matrix): for j in range(len(matrix[0])): # col for k in range(i, (i+max_adjacent)): nums.append(matrix[k][j]) - prod = multOverList(nums) + prod = mult_over_list(nums) if prod > max_product: - max_nums = nums max_product = prod nums = [] # reset for next iteration @@ -64,9 +61,8 @@ def greatestProduct(matrix): for j in range(len(matrix[0])-max_adjacent+1): # col for idx, k in enumerate(range(i, (i+max_adjacent))): nums.append(matrix[k][j+idx]) - prod = multOverList(nums) + prod = mult_over_list(nums) if prod > max_product: - max_nums = nums max_product = prod nums = [] # reset for next iteration @@ -75,17 +71,16 @@ def greatestProduct(matrix): for j in range(len(matrix[0])-1, -1, -1): # col right to left! for idx, k in enumerate(range(i, (i+max_adjacent))): nums.append(matrix[k][j-idx]) - prod = multOverList(nums) + prod = mult_over_list(nums) if prod > max_product: - max_nums = nums max_product = prod nums = [] # reset for next iteration + # return result - print(max_nums) return max_product -def multOverList(l): +def mult_over_list(l): """ Doc string. """ @@ -98,8 +93,8 @@ def multOverList(l): if __name__ == "__main__": # calculate solution and time it start = time.time() - data = parseMatrix("../input_files/problem011.txt") - solution = greatestProduct(data) + data = parse_matrix("../input_files/problem011.txt") + solution = greatest_product(data) end = time.time() # print out results diff --git a/py_src/problem019.py b/py_src/problem019.py index b43aa9a..6c07fce 100644 --- a/py_src/problem019.py +++ b/py_src/problem019.py @@ -1,7 +1,8 @@ # Project Euler Problem 19 Solution # # Problem statement: -# You are given the following information, but you may prefer to do some research for yourself. +# You are given the following information, but you may prefer to +# do some research for yourself. # 1 Jan 1900 was a Monday. # Thirty days has September, @@ -10,47 +11,51 @@ # Saving February alone, # Which has twenty-eight, rain or shine. # And on leap years, twenty-nine. -# A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400. -# How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)? +# A leap year occurs on any year evenly divisible by 4, but not on +# a century unless it is divisible by 400. How many Sundays fell on +# the first of the month during the twentieth century (1 Jan 1901 to +# 31 Dec 2000)? # # Solution description: -# Bruteforce solution: Implements a simple calendar, iterates over -# all the days and counts the number of Sundays that fell on the -# first of a month -# Fast solution: Iterates only over the relevant dates and -# uses Zeller's congruence -# (https://en.wikipedia.org/wiki/Zeller%27s_congruence) to figure -# out the weekday of each first day of a month +# Bruteforce solution: Implements a simple calendar, iterates over +# all the days and counts the number of Sundays that fell on the +# first of a month +# +# Fast solution: Iterates only over the relevant dates and +# uses Zeller's congruence +# (https://en.wikipedia.org/wiki/Zeller%27s_congruence) to figure +# out the weekday of each first day of a month # # Author: Tom Praschan # Date: 2019/02/17 # License: MIT (see ../LICENSE.md) - -from math import floor import time + def is_leapyear(year): - """ + """ Returns True if year is a leap year and false otherwise """ return year % 4 == 0 and not (year % 100 == 0 and year % 400 != 0) + def days_per_month(month, year): """ Given a month (1=january, 2=february, etc.) this function - returns the number of days in that month (leap years are) + returns the number of days in that month (leap years are) taken into account """ if month in [1, 3, 5, 7, 8, 10, 12]: - return 31 + return 31 elif month in [4, 6, 9, 11]: - return 30 + return 30 elif month == 2: return 29 if is_leapyear(year) else 28 raise ValueError("The provided month m must fullfill 1 <= m <= 12!") + def bruteforce_solution(): - weekday = 1 # 1 = Monday, 2 = Tueday, ..., 7 = Sunday + weekday = 1 # 1 = Monday, 2 = Tueday, ..., 7 = Sunday day = 1 month = 1 year = 1900 @@ -69,7 +74,7 @@ def bruteforce_solution(): weekday = weekday % 7 + 1 # Increment month - if day == 1: + if day == 1: month = month % 12 + 1 # Increment year @@ -77,9 +82,10 @@ def bruteforce_solution(): year += 1 return num_sundays + def zellers_congruence(day, month, year): """ - For a given date year/month/day this algorithm returns + For a given date year/month/day this algorithm returns the weekday of that date (1 = Monday, 2 = Tuesday, etc.) For details see https://en.wikipedia.org/wiki/Zeller%27s_congruence """ @@ -87,18 +93,19 @@ def zellers_congruence(day, month, year): # Consistent variable names with the formula on on Wikipedia q = day if month >= 3: - m = month + m = month # pragma: no cover else: m = month + 12 year -= 1 K = year % 100 J = year // 100 - - h = (q + (13 * (m + 1)) // 5 + K + K // 4 + J // 4 + 5*J) % 7 - # Convert to ISO + h = (q + (13 * (m + 1)) // 5 + K + K // 4 + J // 4 + 5*J) % 7 + + # Convert to ISO return ((h + 5) % 7) + 1 + def fast_solution(): num_sundays = 0 for year in range(1901, 2001): @@ -122,5 +129,3 @@ def fast_solution(): print(f"Fast Solution (Zeller's congruence): {solution}") print(f"Elapsed time: {end - start:.6}s") - - diff --git a/py_src/test.py b/py_src/test.py index 38bd2bc..8782fc0 100644 --- a/py_src/test.py +++ b/py_src/test.py @@ -113,6 +113,21 @@ def test_sum_primes(self): self.assertEqual(problem010.sum_primes(10), 17) +class TestProblem011Solution(unittest.TestCase): + def test_parse_matrix(self): + self.assertListEqual( + problem011.parse_matrix("../input_files/test011.txt"), + [["12"], ["34"], ["56"]] + ) + + def test_greatest_product(self): + self.data = problem011.parse_matrix("../input_files/problem011.txt") + self.assertEqual(problem011.greatest_product(self.data), 70600674) + + def test_mult_over_list(self): + self.assertEqual(problem011.mult_over_list([1, 2, 3]), 6) + + class TestProblem013Solution(unittest.TestCase): def test_sum_numbers(self): self.assertEqual(problem013.sum_numbers([123, 100, 400]), 623) @@ -123,25 +138,49 @@ def test_digit_sum(self): self.assertEqual(problem016.digit_sum(123), 6) self.assertEqual(problem016.digit_sum('7356'), 21) + class TestProblem019Solution(unittest.TestCase): def test_is_leapyear(self): self.assertEqual(problem019.is_leapyear(1904), True) self.assertEqual(problem019.is_leapyear(1800), False) self.assertEqual(problem019.is_leapyear(2400), True) + def test_days_per_month(self): + self.assertEqual(problem019.days_per_month(1, 2019), 31) + self.assertEqual(problem019.days_per_month(2, 2019), 28) + self.assertEqual(problem019.days_per_month(2, 2012), 29) + self.assertEqual(problem019.days_per_month(4, 2019), 30) + self.assertRaises( + ValueError, + problem019.days_per_month, + -1, + 2019 + ) + def test_zeller(self): self.assertEqual(problem019.zellers_congruence(1, 1, 1900), 1) self.assertEqual(problem019.zellers_congruence(17, 2, 2019), 7) + def test_brute_force_solution(self): + # TODO + pass + + def test_fast_solution(self): + # TODO + pass + + class TestProblem022Solution(unittest.TestCase): def test_alphabetical_value(self): self.assertEqual(problem022.alphabetical_value('COLIN'), 53) self.assertEqual(problem022.alphabetical_value('ABC'), 6) + class TestProblem025Solution(unittest.TestCase): def test_num_digits(self): self.assertEqual(problem025.num_digits(123), 3) self.assertEqual(problem025.num_digits('25431'), 5) + if __name__ == "__main__": unittest.main() diff --git a/rust_src/src/main.rs b/rust_src/src/main.rs index 6b091e1..03e45f6 100644 --- a/rust_src/src/main.rs +++ b/rust_src/src/main.rs @@ -56,7 +56,8 @@ fn main() { opts_expanded.push(s); } } - } else { // #no_code + } else { + // #no_code opts_expanded.push(option.to_string()); } diff --git a/rust_src/src/tests/mod.rs b/rust_src/src/tests/mod.rs index 0681864..83d9dc2 100644 --- a/rust_src/src/tests/mod.rs +++ b/rust_src/src/tests/mod.rs @@ -41,7 +41,8 @@ mod tests { assert_eq!(lib::problem004::is_palindrome(9009), true); assert_eq!(lib::problem004::is_palindrome(9809), false); - assert_eq!( // #no_code + assert_eq!( + // #no_code lib::problem004::reverse_str(&"ab".to_string()), "ba".to_string() ); @@ -74,6 +75,12 @@ mod tests { assert_eq!(lib::problem007::nth_prime(6), 13); } + #[test] + #[should_panic] + fn test_invalid_path() { + lib::problem008::parse_data("invalid-path".to_string()); + } + #[test] fn test_problem008() { assert_eq!(