Last active
September 9, 2017 11:46
-
-
Save yammesicka/9100317d62089247ed77738f12e7f0a3 to your computer and use it in GitHub Desktop.
A solution for "use the following digits and basic operators to get the result X"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import itertools | |
from typing import (Sequence, Iterable, Iterator, | |
Union, Optional, | |
List, NamedTuple) | |
ALLOWED_OPERATORS = ('*', '/', '+', '-') # , '**) | |
REPEAT_NUMBERS = False | |
DigitsSequence = Union[str, Sequence[Union[str, int]]] | |
class Answer(NamedTuple): | |
solution: Optional[int] | |
expression: str | |
def normalize_input(digits: DigitsSequence) -> List[str]: | |
if not all(map(str.isdecimal, digits)): | |
print("'Digits' must be consisted of decimal numbers.") | |
return [] | |
return list(map(str, digits)) | |
def any_order(items: Sequence, length: Optional[int]=None, | |
allow_repeats: bool=True) -> Iterable: | |
if length is None: | |
length = len(items) | |
if allow_repeats: | |
yield from itertools.product(items, repeat=length) | |
else: | |
yield from itertools.permutations(items, r=length) | |
def zip_to_str(expression: Iterable) -> str: | |
return ''.join(''.join(i) for i in expression) | |
def get_answer(digits: List[str], operators: Sequence) -> Answer: | |
zipped_expression = itertools.zip_longest(digits, operators, fillvalue='') | |
expression = zip_to_str(zipped_expression) | |
try: | |
return Answer(solution=eval(expression), expression=expression) | |
except ZeroDivisionError: | |
return Answer(solution=None, expression=expression) | |
def solver(allowed_digits: DigitsSequence, solution: int) -> Iterator[str]: | |
assert isinstance(solution, int), "Solution must be a number." | |
digits = normalize_input(allowed_digits) | |
for operators in any_order(ALLOWED_OPERATORS, length=len(digits)-1): | |
for digits_option in any_order(digits, allow_repeats=REPEAT_NUMBERS): | |
answer = get_answer(digits_option, operators) | |
if answer.solution == solution: | |
yield answer.expression | |
if __name__ == '__main__': | |
for solution in solver('1679', solution=10): | |
print(solution) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment