P86, P93, P95, P98, P206, P425: Added Python solutions.

parent afd595b6
 ... ... @@ -107,15 +107,19 @@ ANSWERS = { 82: "260324", 83: "425185", 85: "2772", 86: "1818", 87: "1097343", 88: "7587457", 89: "743", 90: "1217", 91: "14234", 92: "8581146", 93: "1258", 94: "518408346", 95: "14316", 96: "24702", 97: "8739992577", 98: "18769", 99: "709", 100: "756872327473", 101: "37076114526", ... ... @@ -172,6 +176,7 @@ ANSWERS = { 203: "34029210557338", 204: "2944730", 205: "0.5731441", 206: "1389019170", 214: "1677366278943", 215: "806844323190414", 216: "5437849", ... ... @@ -194,6 +199,7 @@ ANSWERS = { 381: "139602943319822", 387: "696067597313468", 401: "281632621", 425: "46479497324", 429: "98792821", 493: "6.818741802", 518: "100315739184392", ... ...
python/p086.py 0 → 100644
 # # Solution to Project Euler problem 86 # by Project Nayuki # # https://www.nayuki.io/page/project-euler-solutions # https://github.com/nayuki/Project-Euler-solutions # import fractions, itertools def compute(): # solutions[k] is the set of all solutions where the largest side has length k. # A solution is a triple (x, y, z) such that 0 < x <= y <= z, and in the rectangular prism with dimensions x * y * z, # the shortest surface path from one vertex to the opposite vertex has an integral length. solutions = [] # Generates all solutions where the largest side has length less than 'limit'. def generate_solutions(): # Pythagorean triples theorem: # Every primitive Pythagorean triple with a odd and b even can be expressed as # a = st, b = (s^2-t^2)/2, c = (s^2+t^2)/2, where s > t > 0 are coprime odd integers. # Now generate all Pythagorean triples, including non-primitive ones. for s in itertools.count(3, 2): for t in range(s - 2, 0, -2): if s * s // 2 >= limit * 3: return if fractions.gcd(s, t) == 1: for k in itertools.count(1): a = s * t * k b = (s * s - t * t) // 2 * k c = (s * s + t * t) // 2 * k if a >= limit and b >= limit: break find_splits(a, b, c) find_splits(b, a, c) # Assumes that a^2 + b^2 = c^2. def find_splits(a, b, c): z = b for x in range(1, a): y = a - x if y < x: break if c * c == min( (x + y) * (x + y) + z * z, (y + z) * (y + z) + x * x, (z + x) * (z + x) + y * y): temp = max(x, y, z) if temp < limit: # Add canonical solution item = tuple(sorted((x, y, z))) solutions[temp].add(item) # cumulativesolutions[m] = len(solutions) + len(solutions) + ... + len(solutions[m]). cumulativesolutions =  limit = 1 while True: # Extend the solutions list with blank sets while len(solutions) < limit: solutions.append(set()) generate_solutions() # Compute the number of cumulative solutions up to and including a certain maximum size for i in range(len(cumulativesolutions), limit): sum = cumulativesolutions[i - 1] + len(solutions[i]) cumulativesolutions.append(sum) if sum > 1000000: return str(i) # Raise the limit and keep searching limit *= 2 if __name__ == "__main__": print(compute())
python/p093.py 0 → 100644
 # # Solution to Project Euler problem 93 # by Project Nayuki # # https://www.nayuki.io/page/project-euler-solutions # https://github.com/nayuki/Project-Euler-solutions # import fractions, itertools def compute(): ans = max(((a, b, c, d) for a in range(1, 10) for b in range(a + 1, 10) for c in range(b + 1, 10) for d in range(c + 1, 10)), key=longest_consecutive) return "".join(str(x) for x in ans) def longest_consecutive(abcd): a, b, c, d = abcd expressible = set() # Try all possible orderings of operands and operators ops = [0, 0, 0, a, b, c, d] # 0 = operator slot, 1 to 9 = literal operand while True: # Try all possibilities for the 3 operators for i in range(64): stack = [] j = 0 # Operator index stackunderflow = False divbyzero = False for op in ops: if 1 <= op <= 9: # Operand stack.append(fractions.Fraction(op)) elif op == 0: # Operator if len(stack) < 2: stackunderflow = True break right = stack.pop() left = stack.pop() oper = (i >> (j * 2)) & 3 if oper == 0: stack.append(left + right) elif oper == 1: stack.append(left - right) elif oper == 2: stack.append(left * right) elif oper == 3: if right.numerator == 0: divbyzero = True break stack.append(left / right) else: raise AssertionError() j += 1 # Consume an operator else: raise AssertionError() if stackunderflow: break if divbyzero: continue if len(stack) != 1: raise AssertionError() result = stack.pop() if result.denominator == 1: expressible.add(result.numerator) if not next_permutation(ops): break # Find largest set of consecutive expressible integers starting from 1 return next(i for i in itertools.count(1) if (i not in expressible)) - 1 def next_permutation(arr): # Find non-increasing suffix i = len(arr) - 1 while i > 0 and arr[i - 1] >= arr[i]: i -= 1 if i <= 0: return False # Find successor to pivot j = len(arr) - 1 while arr[j] <= arr[i - 1]: j -= 1 arr[i - 1], arr[j] = arr[j], arr[i - 1] # Reverse suffix arr[i : ] = arr[len(arr) - 1 : i - 1 : -1] return True if __name__ == "__main__": print(compute())
python/p095.py 0 → 100644
 # # Solution to Project Euler problem 95 # by Project Nayuki # # https://www.nayuki.io/page/project-euler-solutions # https://github.com/nayuki/Project-Euler-solutions # import itertools def compute(): LIMIT = 10**6 # divisorsum[n] is the sum of all the proper divisors of n divisorsum =  * (LIMIT + 1) for i in range(1, LIMIT + 1): for j in range(i * 2, LIMIT + 1, i): divisorsum[j] += i # Analyze the amicable chain length for each number in ascending order maxchainlen = 0 ans = -1 for i in range(LIMIT + 1): visited = set() cur = i for count in itertools.count(1): # 'count' is the length of the this amicable chain visited.add(cur) next = divisorsum[cur] if next == i: if count > maxchainlen: ans = i maxchainlen = count break # Exceeds limit or not a chain (a rho shape instead) elif next > LIMIT or next in visited: break else: cur = next return str(ans) if __name__ == "__main__": print(compute())
python/p098.py 0 → 100644
This diff is collapsed.
python/p206.py 0 → 100644
 # # Solution to Project Euler problem 206 # by Project Nayuki # # https://www.nayuki.io/page/project-euler-solutions # https://github.com/nayuki/Project-Euler-solutions # # The major optimization is to do arithmetic in base 10 in the main loop, avoiding division and modulo def compute(): # Initialize n = 1000000000 # The pattern is greater than 10^18, so start searching at 10^9 ndigits =  * 10 # In base 10, little-endian temp = n for i in range(len(ndigits)): ndigits[i] = temp % 10 temp //= 10 n2digits =  * 19 # Based on length of pattern temp = n * n for i in range(len(n2digits)): n2digits[i] = temp % 10 temp //= 10 # Increment and search while not is_concealed_square(n2digits): # Add 20n + 100 so that n2digits = (n + 10)^2 add_20n(ndigits, n2digits) add_10pow(n2digits, 2) # Since n^2 ends with 0, n must end with 0 n += 10 add_10pow(ndigits, 1) # Now n2digits = n^2 return str(n) def is_concealed_square(n): for i in range(1, 10): # Scan for 1 to 9 if n[20 - i * 2] != i: return False return n == 0 # Special case for 0 def add_10pow(n, i): while n[i] == 9: n[i] = 0 i += 1 n[i] += 1 def add_20n(n, n2): carry = 0 i = 0 while i < len(n): sum = n[i] * 2 + n2[i + 1] + carry n2[i + 1] = sum % 10 carry = sum // 10 i += 1 i += 1 while carry > 0: sum = n2[i] + carry n2[i] = sum % 10 carry = sum // 10 i += 1 if __name__ == "__main__": print(compute())
python/p425.py 0 → 100644
 # # Solution to Project Euler problem 425 # by Project Nayuki # # https://www.nayuki.io/page/project-euler-solutions # https://github.com/nayuki/Project-Euler-solutions # import eulerlib, heapq # Finding all the relatives of 2 can be seen as a single-source shortest path problem, # which we solve here using Dijkstra's algorithm. The key insight is that at each node (prime number), # we consider the connection path from 2 to it, and store the maximum path number at the node. # It is amenable to dynamic programming because it's always best to minimize the maximum path number. # # For example, 2 is connected to 103 because 2 <-> 3 <-> 13 <-> 113 <-> 103. # The maximum number along this path is 113, and among all paths # this is the minimum possible maximum, so 103 is not a relative of 2. def compute(): LIMIT = 10**7 isprime = eulerlib.list_primality(LIMIT) # pathmax[i] = None if i is not prime or i is not connected to 2. # Otherwise, considering all connection paths from 2 to i and for each path computing # the maximum number, pathmax[i] is the minimum number among all these maxima. pathmax = [None] * len(isprime) # Process paths in increasing order of maximum number queue = [(2, 2)] while len(queue) > 0: pmax, n = heapq.heappop(queue) if pathmax[n] is not None and pmax >= pathmax[n]: # This happens if at the time this update was queued, a better # or equally good update was queued ahead but not processed yet continue # Update the target node and explore neighbors pathmax[n] = pmax # Try all replacements of a single digit, including the leading zero. # This generates exactly all (no more, no less) the ways that a number m is connected to n. digits = to_digits(n) tempdigits = list(digits) for i in range(len(tempdigits)): # For each digit position for j in range(10): # For each digit value tempdigits[i] = j m = to_number(tempdigits) nextpmax = max(m, pmax) if m < len(isprime) and isprime[m] and (pathmax[m] is None or nextpmax < pathmax[m]): heapq.heappush(queue, (nextpmax, m)) tempdigits[i] = digits[i] # Restore the digit ans = sum(i for i in range(len(isprime)) if (isprime[i] and (pathmax[i] is None or pathmax[i] > i))) return str(ans) # Returns the given non-negative integer as an array of digits, in big endian, with an extra leading zero. # e.g. 0 -> [0,0]; 1 -> [0,1]; 8 -> [0,8]; 42 -> [0,4,2]; 596 -> [0,5,9,6]. def to_digits(n): if n < 0: raise ValueError() # Extract base-10 digits in little endian temp = [] while True: temp.append(n % 10) n //= 10 if n == 0: break temp.append(0) temp.reverse() return temp def to_number(digits): result = 0; for x in digits: result = result * 10 + x return result if __name__ == "__main__": print(compute())
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!