Commit c5eb97d2 by Nayuki

### P18, P19, P20, P21, P22, P24, P25, P29, P31, P67: Added explanatory comment to...

`P18, P19, P20, P21, P22, P24, P25, P29, P31, P67: Added explanatory comment to all language solutions.`
parent 65e3cd8b
 ... ... @@ -7,6 +7,13 @@ -} {- - If we start at a particular cell in the triangle, what is the maximum path total? - If the cell is in the bottom row, then it is simply the cell's value. Otherwise the answer - is the cell's value plus either {the maximum path total of the cell down and to the left} - or {the maximum path total of the cell down and to the right}, whichever is greater. -} main = putStrLn (show ans) ans = maxPath 0 0 ... ...
 ... ... @@ -7,6 +7,14 @@ -} {- - We use Zeller's congruence to compute the day of week when given the year, month, and day. - Then we simply check the first day of all the months in the given range by brute force. - - Zeller's congruence is well-known and a bit long to explain. - See: https://en.wikipedia.org/wiki/Zeller%27s_congruence -} main = putStrLn (show ans) ans = sum [1 | y <- [1901..2000], m <- [1..12], dayOfWeek y m 1 == 0] ... ...
 ... ... @@ -7,6 +7,10 @@ -} {- - We do a straightforward product thanks to Haskell's built-in arbitrary precision Integer type. -} main = putStrLn (show ans) ans = digitSum (factorial 100 :: Integer) ... ...
 ... ... @@ -7,6 +7,11 @@ -} {- - We find the sum of proper divisors of a number by brute force, - and apply the definition of an amicable number straightforwardly. -} main = putStrLn (show ans) ans = sum [n | n <- [1..10^4], amicable n] ... ...
 ... ... @@ -10,6 +10,10 @@ import Data.List (sort) import Data.Char (ord) {- - We apply straightforward algorithms to sort the names, sum the letter values, and multiply by the position. -} main = putStrLn (show ans) ans = sum (zipWith (*) [1..] (map strSum (sort names))) ... ...
 ... ... @@ -7,6 +7,15 @@ -} {- - We initialize an array as the lowest permutation of the given digits, which is the sequence - (0,1,2,3,4,5,6,7,8,9). Then we call the next permutation algorithm on it 999 999 times - (because the index in the problem is 1-based), and stringify the resulting sequence. - - The next permutation algorithm is well-known and a bit long to explain. - See: https://www.nayuki.io/page/next-lexicographical-permutation-algorithm -} main = putStrLn (show ans) ans = case (iterate (>>= nextPerm) (Just [0..9])) !! (10^6 - 1) of Just digits -> digitsToNum 0 digits -- Extract from Just wrapper ... ...
 ... ... @@ -7,6 +7,13 @@ -} {- - Because the target number is relatively small, we simply compute each Fibonacci number starting - from the beginning until we encounter one with exactly 1000 digits. The Fibonacci sequence grows - exponentially with a base of about 1.618, so the numbers in base 10 will lengthen by one digit - after every log10(1.618) ~= 4.78 steps on average. This means the answer is at index around 4780. -} digits = 1000 main = putStrLn (show ans) ans = length (takeWhile (< 10 ^ (digits - 1)) fibonacci) ... ...
 ... ... @@ -9,5 +9,9 @@ import Data.List (nub) {- - We generate all possible powers in the given range, put the values in a flat list, - delete the duplicates of any value, and count the length of the remaining list. -} main = putStrLn (show ans) ans = length (nub [a^b | a <- [2..100], b <- [2..100]])
 ... ... @@ -7,6 +7,11 @@ -} {- - We use the standard recursive algorithm to solve the subset sum problem, with memoization. - The order of the coin values does not matter, but the values need to be unique. -} main = putStrLn (show ans) ans = ways coins 200 ... ...
 ... ... @@ -7,6 +7,15 @@ -} {- - If we start at a particular cell in the triangle, what is the maximum path total? - If the cell is in the bottom row, then it is simply the cell's value. Otherwise the answer - is the cell's value plus either {the maximum path total of the cell down and to the left} - or {the maximum path total of the cell down and to the right}, whichever is greater. - To ensure that the running time is polynomial rather than exponential, - we memoize the sub-result at each cell to avoid needless recomputation. -} main = putStrLn (show ans) ans = maxPath 0 0 ... ...
 ... ... @@ -14,6 +14,20 @@ public final class p018 implements EulerSolution { } /* * We create a new blank triangle with the same dimensions as the original big triangle. * For each cell of the big triangle, we consider the sub-triangle whose top is at this cell, * calculate the maximum path sum when starting from this cell, and store the result * in the corresponding cell of the blank triangle. * * If we start at a particular cell, what is the maximum path total? If the cell is at the * bottom of the big triangle, then it is simply the cell's value. Otherwise the answer is * the cell's value plus either {the maximum path total of the cell down and to the left} * or {the maximum path total of the cell down and to the right}, whichever is greater. * By computing the blank triangle's values from bottom up, the dependent values are always * computed before they are utilized. This technique is known as dynamic programming. */ public String run() { for (int i = triangle.length - 2; i >= 0; i--) { for (int j = 0; j < triangle[i].length; j++) ... ...
 ... ... @@ -14,6 +14,14 @@ public final class p019 implements EulerSolution { } /* * We use Zeller's congruence to compute the day of week when given the year, month, and day. * Then we simply check the first day of all the months in the given range by brute force. * * Zeller's congruence is well-known and a bit long to explain. * See: https://en.wikipedia.org/wiki/Zeller%27s_congruence */ public String run() { int count = 0; for (int y = 1901; y <= 2000; y++) { ... ...
 ... ... @@ -14,6 +14,9 @@ public final class p020 implements EulerSolution { } /* * We do a straightforward product with help from Java's BigInteger type. */ public String run() { String temp = Library.factorial(100).toString(); int sum = 0; ... ...
 ... ... @@ -14,6 +14,11 @@ public final class p021 implements EulerSolution { } /* * We find the sum of proper divisors of a number by brute force, * and apply the definition of an amicable number straightforwardly. */ public String run() { int sum = 0; for (int i = 1; i < 10000; i++) { ... ...
 ... ... @@ -16,6 +16,10 @@ public final class p022 implements EulerSolution { } /* * We apply straightforward algorithms to sort the names, sum the letter values, and multiply by the position. */ public String run() { Arrays.sort(names); int sum = 0; ... ...
 ... ... @@ -14,6 +14,15 @@ public final class p024 implements EulerSolution { } /* * We initialize an array as the lowest permutation of the given digits, which is the sequence * (0,1,2,3,4,5,6,7,8,9). Then we call the next permutation algorithm on it 999 999 times * (because the index in the problem is 1-based), and stringify the resulting sequence. * * The next permutation algorithm is well-known and a bit long to explain. * See: https://www.nayuki.io/page/next-lexicographical-permutation-algorithm */ public String run() { // Initialize int[] array = new int[10]; ... ...
 ... ... @@ -16,6 +16,13 @@ public final class p025 implements EulerSolution { } /* * Because the target number is relatively small, we simply compute each Fibonacci number starting * from the beginning until we encounter one with exactly 1000 digits. The Fibonacci sequence grows * exponentially with a base of about 1.618, so the numbers in base 10 will lengthen by one digit * after every log10(1.618) ~= 4.78 steps on average. This means the answer is at index around 4780. */ private static final int DIGITS = 1000; public String run() { ... ...
 ... ... @@ -18,6 +18,11 @@ public final class p029 implements EulerSolution { } /* * We generate all the possible powers in the given range, put each value * into a set, and let the set count the number of unique values present. */ public String run() { Set generated = new HashSet<>(); for (int a = 2; a <= 100; a++) { ... ...
 ... ... @@ -14,6 +14,11 @@ public final class p031 implements EulerSolution { } /* * We use the standard dynamic programming algorithm to solve the subset sum problem over integers. * The order of the coin values does not matter, but the values need to be unique. */ private static final int TOTAL = 200; private static int[] COINS = {1, 2, 5, 10, 20, 50, 100, 200}; ... ...
 ... ... @@ -14,6 +14,20 @@ public final class p067 implements EulerSolution { } /* * We create a new blank triangle with the same dimensions as the original big triangle. * For each cell of the big triangle, we consider the sub-triangle whose top is at this cell, * calculate the maximum path sum when starting from this cell, and store the result * in the corresponding cell of the blank triangle. * * If we start at a particular cell, what is the maximum path total? If the cell is at the * bottom of the big triangle, then it is simply the cell's value. Otherwise the answer is * the cell's value plus either {the maximum path total of the cell down and to the left} * or {the maximum path total of the cell down and to the right}, whichever is greater. * By computing the blank triangle's values from bottom up, the dependent values are always * computed before they are utilized. This technique is known as dynamic programming. */ public String run() { for (int i = triangle.length - 2; i >= 0; i--) { for (int j = 0; j < triangle[i].length; j++) ... ...
 ... ... @@ -7,6 +7,13 @@ *) (* * If we start at a particular cell in the triangle, what is the maximum path total? * If the cell is in the bottom row, then it is simply the cell's value. Otherwise the answer * is the cell's value plus either {the maximum path total of the cell down and to the left} * or {the maximum path total of the cell down and to the right}, whichever is greater. *) triangle = { {75}, {95,64}, ... ...
 ... ... @@ -7,5 +7,8 @@ *) (* * We simply use Mathematica's built-in date library to compute the answer by brute force. *) << Miscellaneous`Calendar` Sum[Boole[DayOfWeek[{y, m, 1}] === Sunday], {y, 1901, 2000}, {m, 1, 12}]
 ... ... @@ -7,4 +7,7 @@ *) (* * We do a straightforward computation thanks to Mathematica's built-in arbitrary precision integer type. *) Total[IntegerDigits[100!]]
 ... ... @@ -7,6 +7,10 @@ *) (* * We modify a built-in function to find the sum of proper divisors of a number. * Then we apply the definition of an amicable number straightforwardly. *) DivisorSum[n_] := DivisorSigma[1, n] - n AmicableQ[n_] := DivisorSum[n] != n && DivisorSum[DivisorSum[n]] == n Total[Select[Range[9999], AmicableQ]]
 ... ... @@ -7,6 +7,10 @@ *) (* * We apply straightforward algorithms to sort the names, sum the letter values, and multiply by the position. *) peoplenames = { (* 10 strings per line, except final line *) "MARY", "PATRICIA", "LINDA", "BARBARA", "ELIZABETH", "JENNIFER", "MARIA", "SUSAN", "MARGARET", "DOROTHY", "LISA", "NANCY", "KAREN", "BETTY", "HELEN", "SANDRA", "DONNA", "CAROL", "RUTH", "SHARON", ... ...
 ... ... @@ -7,4 +7,8 @@ *) (* * We generate all 10! permutations of the sequence (0,1,2,3,4,5,6,7,8,9) * into memory, and select the 1 000 000th element (1-based indexing). *) FromDigits[Permutations[Range[0, 9]][[1000000]]]
 ... ... @@ -7,6 +7,12 @@ *) (* * Because the target number is relatively small, we simply compute each Fibonacci number starting * from the beginning until we encounter one with exactly 1000 digits. The Fibonacci sequence grows * exponentially with a base of about 1.618, so the numbers in base 10 will lengthen by one digit * after every log10(1.618) ~= 4.78 steps on average. This means the answer is at index around 4780. *) i = 0; While[Fibonacci[i] < 10^999, i++] i
 ... ... @@ -7,4 +7,8 @@ *) (* * We generate all possible powers in the given range, put the values in a flat list, * delete the duplicates of any value, and count the length of the remaining list. *) Length[Union[Flatten[Table[a^b, {a, 2, 100}, {b, 2, 100}]]]]
 ... ... @@ -7,6 +7,10 @@ *) (* * We use the standard recursive algorithm to solve the subset sum problem, with memoization. * The order of the coin values does not matter, but the values need to be unique. *) Coins = {1, 2, 5, 10, 20, 50, 100, 200}; Ways[coinIndex_, total_] := Ways[coinIndex, total] = (* Memoization *) If[coinIndex == 0, Boole[total == 0], ... ...
 ... ... @@ -7,6 +7,15 @@ *) (* * If we start at a particular cell in the triangle, what is the maximum path total? * If the cell is in the bottom row, then it is simply the cell's value. Otherwise the answer * is the cell's value plus either {the maximum path total of the cell down and to the left} * or {the maximum path total of the cell down and to the right}, whichever is greater. * To ensure that the running time is polynomial rather than exponential, * we memoize the sub-result at each cell to avoid needless recomputation. *) triangle = { {59}, {73,41}, ... ...
 ... ... @@ -7,6 +7,17 @@ # # We create a new blank triangle with the same dimensions as the original big triangle. # For each cell of the big triangle, we consider the sub-triangle whose top is at this cell, # calculate the maximum path sum when starting from this cell, and store the result # in the corresponding cell of the blank triangle. # # If we start at a particular cell, what is the maximum path total? If the cell is at the # bottom of the big triangle, then it is simply the cell's value. Otherwise the answer is # the cell's value plus either {the maximum path total of the cell down and to the left} # or {the maximum path total of the cell down and to the right}, whichever is greater. # By computing the blank triangle's values from bottom up, the dependent values are always # computed before they are utilized. This technique is known as dynamic programming. def compute(): for i in reversed(range(len(triangle) - 1)): for j in range(len(triangle[i])): ... ...
 ... ... @@ -9,6 +9,7 @@ import datetime # We simply use Python's built-in date library to compute the answer by brute force. def compute(): ans = sum(1 for y in range(1901, 2001) ... ...
 ... ... @@ -9,6 +9,7 @@ import math # We do a straightforward computation thanks to Python's built-in arbitrary precision integer type. def compute(): n = math.factorial(100) ans = sum(int(c) for c in str(n)) ... ...
 ... ... @@ -7,6 +7,9 @@ # # We first compute a table of sum-of-proper-divisors, then we use it to test which numbers are amicable. # This approach differs from the Java implementation because trying to directly compute # the proper-divisor-sum of each number by brute force is unacceptably slow in Python. def compute(): # Compute sum of proper divisors for each number divisorsum = [0] * 10000 ... ...
 ... ... @@ -7,6 +7,7 @@ # # We apply straightforward algorithms to sort the names, sum the letter values, and multiply by the position. def compute(): ans = sum((i + 1) * (ord(c) - ord('A') + 1) for (i, name) in enumerate(sorted(NAMES)) ... ...
 ... ... @@ -11,6 +11,9 @@ if sys.version_info.major == 2: range = xrange # We initialize a list as the lowest permutation of the given digits, which is the sequence # (0,1,2,3,4,5,6,7,8,9). Then we call a Python library function that generates a stream of # all permutations of the values, seek to the 999 999th element (0-based indexing), and stringify it. def compute(): arr = list(range(10)) temp = itertools.islice(itertools.permutations(arr), 999999, None) ... ...
 ... ... @@ -7,6 +7,10 @@ # # Because the target number is relatively small, we simply compute each Fibonacci number starting # from the beginning until we encounter one with exactly 1000 digits. The Fibonacci sequence grows # exponentially with a base of about 1.618, so the numbers in base 10 will lengthen by one digit # after every log10(1.618) ~= 4.78 steps on average. This means the answer is at index around 4780. def compute(): a = 1 b = 1 ... ...
 ... ... @@ -7,6 +7,8 @@ # # We generate all the possible powers in the given range, put each value # into a set, and let the set count the number of unique values present. def compute(): seen = set(a**b for a in range(2, 101) for b in range(2, 101)) return str(len(seen)) ... ...
 ... ... @@ -7,6 +7,8 @@ # # We use the standard dynamic programming algorithm to solve the subset sum problem over integers. # The order of the coin values does not matter, but the values need to be unique. def compute(): ways = [1] + [0] * 200 for coin in [1, 2, 5, 10, 20, 50, 100, 200]: ... ...
 ... ... @@ -7,6 +7,17 @@ # # We create a new blank triangle with the same dimensions as the original big triangle. # For each cell of the big triangle, we consider the sub-triangle whose top is at this cell, # calculate the maximum path sum when starting from this cell, and store the result # in the corresponding cell of the blank triangle. # # If we start at a particular cell, what is the maximum path total? If the cell is at the # bottom of the big triangle, then it is simply the cell's value. Otherwise the answer is # the cell's value plus either {the maximum path total of the cell down and to the left} # or {the maximum path total of the cell down and to the right}, whichever is greater. # By computing the blank triangle's values from bottom up, the dependent values are always # computed before they are utilized. This technique is known as dynamic programming. def compute(): for i in reversed(range(len(triangle) - 1)): for j in range(len(triangle[i])): ... ...
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!