mirror of
https://github.com/jlengrand/project_euler.git
synced 2026-03-10 08:41:20 +00:00
Solves Problem 32. Opens the path to pandigital problems !
Signed-off-by: Julien Lengrand-Lambert <julien@lengrand.fr>
This commit is contained in:
121
e_32.py
Normal file
121
e_32.py
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Created on 10 feb. 2012
|
||||
|
||||
@author: Julien Lengrand-Lambert
|
||||
|
||||
DESCRIPTION: Solves problem 32 of Project Euler
|
||||
We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once; for example, the 5-digit number, 15234, is 1 through 5 pandigital.
|
||||
|
||||
The product 7254 is unusual, as the identity, 39 * 186 = 7254, containing multiplicand, multiplier, and product is 1 through 9 pandigital.
|
||||
|
||||
Find the sum of all products whose multiplicand/multiplier/product identity can be written as a 1 through 9 pandigital.
|
||||
|
||||
HINT: Some products can be obtained in more than one way so be sure to only include it once in your sum.
|
||||
'''
|
||||
|
||||
def all_permutations(seq):
|
||||
"""permutates a sequence and return a list of the permutations"""
|
||||
if not seq:
|
||||
return [seq] # is an empty sequence
|
||||
else:
|
||||
temp = []
|
||||
for k in range(len(seq)):
|
||||
part = seq[:k] + seq[k+1:]
|
||||
for m in all_permutations(part):
|
||||
temp.append(seq[k:k+1] + m)
|
||||
return temp
|
||||
|
||||
def combinations(iterable, r):
|
||||
"""
|
||||
Return r length subsequences of elements from the input iterable
|
||||
# combinations('ABCD', 2) --> AB AC AD BC BD CD
|
||||
# combinations(range(4), 3) --> 012 013 023 123
|
||||
"""
|
||||
pool = tuple(iterable)
|
||||
n = len(pool)
|
||||
if r > n:
|
||||
return
|
||||
indices = range(r)
|
||||
yield tuple(pool[i] for i in indices)
|
||||
while True:
|
||||
for i in reversed(range(r)):
|
||||
if indices[i] != i + n - r:
|
||||
break
|
||||
else:
|
||||
return
|
||||
indices[i] += 1
|
||||
for j in range(i+1, r):
|
||||
indices[j] = indices[j-1] + 1
|
||||
yield tuple(pool[i] for i in indices)
|
||||
|
||||
def all_combinations(iterable, r):
|
||||
"""
|
||||
Overlays combinations functions in order to get a list of integers including all permutations
|
||||
should be kept as a generator!
|
||||
"""
|
||||
out_list = []
|
||||
|
||||
combs = combinations(iterable, r)
|
||||
for comb in combs:
|
||||
numLists = all_permutations(comb)
|
||||
[out_list.append(to_nums(numList)) for numList in numLists]
|
||||
|
||||
return out_list
|
||||
|
||||
|
||||
def to_nums(list_num):
|
||||
"""Returns an integer given a list of numbers"""
|
||||
return int(''.join(map(str,list_num)))
|
||||
|
||||
|
||||
def is_pandigital(plier, plicand, product):
|
||||
"""
|
||||
Well, it works this way ^^
|
||||
Returns True if the multiplicand/multiplier/product identity can be written as a 1 through 9 pandigital
|
||||
"""
|
||||
ref_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
my_list = [str(product), str(plier), str(plicand)]
|
||||
|
||||
if ref_list == sorted([int(item) for sublist in my_list for item in sublist]):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def test_combinations():
|
||||
"""
|
||||
Tests all possible combinations of multipliers and multiplicands
|
||||
"""
|
||||
res_list = []
|
||||
|
||||
len_a = 1
|
||||
up_ref_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
while len_a < 4 : # 4 + 4 = 1 impossible
|
||||
combs_a = all_combinations(up_ref_list, len_a) # lists all possibilities
|
||||
max_b = (9 - len_a) / 2
|
||||
for comb_a in combs_a:
|
||||
up_ref_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
remove_list_els(up_ref_list, comb_a)
|
||||
for len_b in range(len_a, max_b + 1):
|
||||
combs_b = all_combinations(up_ref_list, len_b) # lists all possibilities
|
||||
for comb_b in combs_b:
|
||||
prod = comb_a * comb_b
|
||||
if is_pandigital(comb_a, comb_b, prod):
|
||||
res_list.append(prod)
|
||||
|
||||
up_ref_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
len_a += 1
|
||||
|
||||
return sum(remove_duplicates(res_list)) # removes duplicates
|
||||
|
||||
def remove_list_els(my_list, my_int):
|
||||
"""Remove all elements of my_int from my_list"""
|
||||
[my_list.remove(int(val)) for val in str(my_int)]
|
||||
# no need to return anything
|
||||
|
||||
def remove_duplicates(my_list):
|
||||
"""Removes duplicates in a list"""
|
||||
return list(set(my_list))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "Answer : %d " % (test_combinations())
|
||||
50
e_79.data
Normal file
50
e_79.data
Normal file
@@ -0,0 +1,50 @@
|
||||
319
|
||||
680
|
||||
180
|
||||
690
|
||||
129
|
||||
620
|
||||
762
|
||||
689
|
||||
762
|
||||
318
|
||||
368
|
||||
710
|
||||
720
|
||||
710
|
||||
629
|
||||
168
|
||||
160
|
||||
689
|
||||
716
|
||||
731
|
||||
736
|
||||
729
|
||||
316
|
||||
729
|
||||
729
|
||||
710
|
||||
769
|
||||
290
|
||||
719
|
||||
680
|
||||
318
|
||||
389
|
||||
162
|
||||
289
|
||||
162
|
||||
718
|
||||
729
|
||||
319
|
||||
790
|
||||
680
|
||||
890
|
||||
362
|
||||
319
|
||||
760
|
||||
316
|
||||
729
|
||||
380
|
||||
319
|
||||
728
|
||||
716
|
||||
21
e_79.py
Normal file
21
e_79.py
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Created on 20 feb. 2012
|
||||
|
||||
@author: Julien Lengrand-Lambert
|
||||
|
||||
DESCRIPTION: Solves problem 79 of Project Euler
|
||||
A common security method used for online banking is to ask the user for three random characters from a passcode. For example, if the passcode was 531278, they may ask for the 2nd, 3rd, and 5th characters; the expected reply would be: 317.
|
||||
|
||||
The text file, e_79.data, contains fifty successful login attempts.
|
||||
|
||||
Given that the three characters are always asked for in order, analyse the file so as to determine the shortest possible secret passcode of unknown length.
|
||||
'''
|
||||
def shortest():
|
||||
"""
|
||||
Returns the shortest possible secret passcode of unknown length
|
||||
"""
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "Answer : %d " % (1)
|
||||
Reference in New Issue
Block a user