Skip to main content
Code Review

Return to Question

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

Related to another answer of mine another answer of mine on Project Euler 35, I found the need to calculate all combinations of certain digits, i.e. 1, 3, 7 and 9, below a given n. I looked around, and didn't find any really good premade solutions, but found some bits and pieces related to Cartesian products, and collated my findings into the following code:

import itertools
def all_digit_combinations(allowed_digits, maximum):
 """Yield all combinations of allowed_digits below maximum.
 
 For allowed_digits being a list of single digits, i.e. [1, 3, 7, 9],
 combine all variants of these digits until we pass the maximum value.
 """
 no_of_digits = 1
 
 while True:
 for digit_tuple in itertools.product(allowed_digits, repeat=no_of_digits):
 new_number = reduce(lambda rst, d: rst * 10 + d, digit_tuple)
 if new_number < maximum:
 yield new_number
 else:
 raise StopIteration
 
 no_of_digits += 1
if __name__ == '__main__':
 print ', '.join(map(str, all_digit_combinations([1, 3, 7, 9], 100)))
 print ', '.join(map(str, all_digit_combinations([3, 5], 1000)))

Which indeed prints the expected output of:

1, 3, 7, 9, 11, 13, 17, 19, 31, 33, 37, 39, 71, 73, 77, 79, 91, 93, 97, 99
3, 5, 33, 35, 53, 55, 333, 335, 353, 355, 533, 535, 553, 555

I first tried using itertools.combinations_with_replacement() and other variations from itertools, but some of those versions failed to include numbers like 31 and 73. But it I could very well simply not use the correct parameters.

Can you review this code, suggesting any optimalisations or improvements?

Related to another answer of mine on Project Euler 35, I found the need to calculate all combinations of certain digits, i.e. 1, 3, 7 and 9, below a given n. I looked around, and didn't find any really good premade solutions, but found some bits and pieces related to Cartesian products, and collated my findings into the following code:

import itertools
def all_digit_combinations(allowed_digits, maximum):
 """Yield all combinations of allowed_digits below maximum.
 
 For allowed_digits being a list of single digits, i.e. [1, 3, 7, 9],
 combine all variants of these digits until we pass the maximum value.
 """
 no_of_digits = 1
 
 while True:
 for digit_tuple in itertools.product(allowed_digits, repeat=no_of_digits):
 new_number = reduce(lambda rst, d: rst * 10 + d, digit_tuple)
 if new_number < maximum:
 yield new_number
 else:
 raise StopIteration
 
 no_of_digits += 1
if __name__ == '__main__':
 print ', '.join(map(str, all_digit_combinations([1, 3, 7, 9], 100)))
 print ', '.join(map(str, all_digit_combinations([3, 5], 1000)))

Which indeed prints the expected output of:

1, 3, 7, 9, 11, 13, 17, 19, 31, 33, 37, 39, 71, 73, 77, 79, 91, 93, 97, 99
3, 5, 33, 35, 53, 55, 333, 335, 353, 355, 533, 535, 553, 555

I first tried using itertools.combinations_with_replacement() and other variations from itertools, but some of those versions failed to include numbers like 31 and 73. But it I could very well simply not use the correct parameters.

Can you review this code, suggesting any optimalisations or improvements?

Related to another answer of mine on Project Euler 35, I found the need to calculate all combinations of certain digits, i.e. 1, 3, 7 and 9, below a given n. I looked around, and didn't find any really good premade solutions, but found some bits and pieces related to Cartesian products, and collated my findings into the following code:

import itertools
def all_digit_combinations(allowed_digits, maximum):
 """Yield all combinations of allowed_digits below maximum.
 
 For allowed_digits being a list of single digits, i.e. [1, 3, 7, 9],
 combine all variants of these digits until we pass the maximum value.
 """
 no_of_digits = 1
 
 while True:
 for digit_tuple in itertools.product(allowed_digits, repeat=no_of_digits):
 new_number = reduce(lambda rst, d: rst * 10 + d, digit_tuple)
 if new_number < maximum:
 yield new_number
 else:
 raise StopIteration
 
 no_of_digits += 1
if __name__ == '__main__':
 print ', '.join(map(str, all_digit_combinations([1, 3, 7, 9], 100)))
 print ', '.join(map(str, all_digit_combinations([3, 5], 1000)))

Which indeed prints the expected output of:

1, 3, 7, 9, 11, 13, 17, 19, 31, 33, 37, 39, 71, 73, 77, 79, 91, 93, 97, 99
3, 5, 33, 35, 53, 55, 333, 335, 353, 355, 533, 535, 553, 555

I first tried using itertools.combinations_with_replacement() and other variations from itertools, but some of those versions failed to include numbers like 31 and 73. But it I could very well simply not use the correct parameters.

Can you review this code, suggesting any optimalisations or improvements?

edited tags
Link
200_success
  • 145.5k
  • 22
  • 190
  • 478
Apparent copy-paste error fixed
Source Link
Janne Karila
  • 10.6k
  • 21
  • 34

Related to another answer of mine on Project Euler 35, I found the need to calculate all combinations of certain digits, i.e. 1, 3, 7 and 9, below a given n. I looked around, and didn't find any really good premade solutions, but found some bits and pieces related to Cartesian products, and collated my findings into the following code:

import itertools
def all_digit_combinations(allowed_digits, maximum):
 """Yield all combinations of allowed_digits below maximum.
 
 For allowed_digits being a list of single digits, i.e. [1, 3, 7, 9],
 combine all variants of these digits until we pass the maximum value.
 """
 no_of_digits = 1
 
 while True:
 for digit_tuple in itertools.product(allowed_digits, repeat=no_of_digits):
 new_number = reduce(lambda rst, d: rst * 10 + d, digit_tuple)
 if new_number < maximum:
 yield new_number
 else:
 raise StopIteration
 
 no_of_digits += 1
if __name__ == '__main__':
 print ', '.join(map(str, all_digit_combinations([1, 3, 7, 9], 100)))
 print ', '.join(map(str, all_digit_combinations([3, 5], 1000)))

Which indeed prints the expected output of:

1, 3, 7, 9, 11, 13, 17, 19, 31, 33, 37, 39, 71, 73, 77, 79, 91, 93, 97, 99
3, 5, 33, 35, 53, 55, 333, 335, 353, 355, 533, 535, 553, 55555

I first tried using itertools.combinations_with_replacement() and other variations from itertools, but some of those versions failed to include numbers like 31 and 73. But it I could very well simply not use the correct parameters.

Can you review this code, suggesting any optimalisations or improvements?

Related to another answer of mine on Project Euler 35, I found the need to calculate all combinations of certain digits, i.e. 1, 3, 7 and 9, below a given n. I looked around, and didn't find any really good premade solutions, but found some bits and pieces related to Cartesian products, and collated my findings into the following code:

import itertools
def all_digit_combinations(allowed_digits, maximum):
 """Yield all combinations of allowed_digits below maximum.
 
 For allowed_digits being a list of single digits, i.e. [1, 3, 7, 9],
 combine all variants of these digits until we pass the maximum value.
 """
 no_of_digits = 1
 
 while True:
 for digit_tuple in itertools.product(allowed_digits, repeat=no_of_digits):
 new_number = reduce(lambda rst, d: rst * 10 + d, digit_tuple)
 if new_number < maximum:
 yield new_number
 else:
 raise StopIteration
 
 no_of_digits += 1
if __name__ == '__main__':
 print ', '.join(map(str, all_digit_combinations([1, 3, 7, 9], 100)))
 print ', '.join(map(str, all_digit_combinations([3, 5], 1000)))

Which indeed prints the expected output of:

1, 3, 7, 9, 11, 13, 17, 19, 31, 33, 37, 39, 71, 73, 77, 79, 91, 93, 97, 99
3, 5, 33, 35, 53, 55, 333, 335, 353, 355, 533, 535, 553, 55

I first tried using itertools.combinations_with_replacement() and other variations from itertools, but some of those versions failed to include numbers like 31 and 73. But it I could very well simply not use the correct parameters.

Can you review this code, suggesting any optimalisations or improvements?

Related to another answer of mine on Project Euler 35, I found the need to calculate all combinations of certain digits, i.e. 1, 3, 7 and 9, below a given n. I looked around, and didn't find any really good premade solutions, but found some bits and pieces related to Cartesian products, and collated my findings into the following code:

import itertools
def all_digit_combinations(allowed_digits, maximum):
 """Yield all combinations of allowed_digits below maximum.
 
 For allowed_digits being a list of single digits, i.e. [1, 3, 7, 9],
 combine all variants of these digits until we pass the maximum value.
 """
 no_of_digits = 1
 
 while True:
 for digit_tuple in itertools.product(allowed_digits, repeat=no_of_digits):
 new_number = reduce(lambda rst, d: rst * 10 + d, digit_tuple)
 if new_number < maximum:
 yield new_number
 else:
 raise StopIteration
 
 no_of_digits += 1
if __name__ == '__main__':
 print ', '.join(map(str, all_digit_combinations([1, 3, 7, 9], 100)))
 print ', '.join(map(str, all_digit_combinations([3, 5], 1000)))

Which indeed prints the expected output of:

1, 3, 7, 9, 11, 13, 17, 19, 31, 33, 37, 39, 71, 73, 77, 79, 91, 93, 97, 99
3, 5, 33, 35, 53, 55, 333, 335, 353, 355, 533, 535, 553, 555

I first tried using itertools.combinations_with_replacement() and other variations from itertools, but some of those versions failed to include numbers like 31 and 73. But it I could very well simply not use the correct parameters.

Can you review this code, suggesting any optimalisations or improvements?

Source Link
holroy
  • 11.7k
  • 1
  • 27
  • 59
Loading
lang-py

AltStyle によって変換されたページ (->オリジナル) /