Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import itertools as it
- import operator
- import random
- from more_itertools import distinct_permutations
- class FalseOperation(ValueError):
- pass
- def is_valid(sequence):
- count_nums = 0
- for token in sequence:
- if not token:
- count_nums -= 1
- if count_nums < 1:
- return False
- else:
- count_nums += 1
- return True
- def valid_sequences(num_count):
- base = (True,) * num_count + (False,) * (num_count - 1)
- # print(base)
- perms = distinct_permutations(base)
- # perms = list(perms)
- # print(f'possible permutations: {len(perms)}')
- for sequence in perms:
- # print(sequence)
- if is_valid(sequence):
- yield sequence
- def distinct_ordered_combinations(iterable, r):
- seen = set()
- for combination in it.combinations_with_replacement(iterable, r):
- for permutation in it.permutations(combination):
- if permutation not in seen:
- yield permutation
- seen.add(permutation)
- def generate_sequences(numbers, operators):
- l = len(numbers)
- for sequence in valid_sequences(l):
- for nums, ops in it.product(
- distinct_permutations(numbers),
- distinct_ordered_combinations(operators, l - 1),
- ):
- nums = iter(nums)
- ops = iter(ops)
- yield tuple(next(nums) if token else next(ops) for token in sequence)
- def calculate_sequence(sequence, operators):
- # Implement postfix algorithm
- stack = list(sequence[:2])
- for idx, token in enumerate(sequence[2:], start=3):
- if token not in operators:
- stack.append(token)
- continue
- operand1 = stack.pop()
- operand2 = stack.pop()
- try:
- result = operators[token](operand1, operand2)
- except ZeroDivisionError:
- raise FalseOperation('Division by zero')
- if int(result) != result:
- raise FalseOperation('non-int value')
- if result < 0:
- raise FalseOperation('negative value')
- yield result, sequence[:idx]
- stack.append(result)
- def test_sequences(target, numbers, operators):
- for sequence in generate_sequences(numbers, operators):
- try:
- for result, seq in calculate_sequence(sequence, operators):
- if result == target:
- yield result, seq
- except FalseOperation:
- pass
- def main():
- # Generate the set of possible numbers allowed by Countdown rules
- large_numbers = [25, 50, 75, 100]
- small_numbers = list(range(1, 11)) * 2
- # Generate six number tiles according to user input for large numbers
- while True:
- try:
- usr_large_num = int(input("How many LARGE numbers do you want (0-4)? "))
- except ValueError:
- pass
- else:
- if 0 <= usr_large_num <= 4:
- break
- six_tiles = random.sample(large_numbers, usr_large_num) + \
- random.sample(small_numbers, 6 - usr_large_num)
- # Generate random target output: any three-digit number
- target = random.randint(100, 999)
- print(six_tiles)
- print(f"Target: {target}")
- ops_tiles = {"+": operator.add,
- "-": operator.sub,
- "*": operator.mul,
- "/": operator.truediv}
- for operators in it.combinations_with_replacement(ops_tiles, 4):
- generate_sequences(six_tiles, operators)
- test_sequences(target, six_tiles, operators)
- print('hi')
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement