I have created a brainteaser, which I called the impossible problem (see this video I made).  The aim is to create a valid 3-digit subtraction which uses every digit from 1 to 9 once. Here is an example of one of the solutions: 873-254=619.After finding it hard to come up with answers I created this program. What it basically does is iterate through every possible 3-digit subtraction and if it finds one which fits the criteria, it prints it.from math import truncdef solver(number,number2, numberofdigits):    seq = str(number),str(number2), str(number - number2)    digits = .join(seq)    goodChecks = 0    count= numberofdigits/3    for i in range(1,10):        if digits.count(str(i)) == count:            goodChecks += 1    if goodChecks == 9:        return digits    else:        return Falsemiddlenumber =[]successes = 0num_of_digits = int(input(please enter a number of digits, which is a multiple of 3))if num_of_digits == 3:    minY = 381    maxY = 987if num_of_digits == 6:    minY =246912    maxY = 998877if num_of_digits == 3:    minX = 123if num_of_digits == 6:    minX =123123for y in range(minY, maxY+1):    numberlist = []    if y%100 == 0:        print(y)    for x in range(minX,trunc(y/2)):        digits = solver(y,x,num_of_digits)        if digits is not False:            successes += 2            print(digits)            numberlist.extend([x,y-x])            middlenumber.extend([x, y-x])print()print(I found: , successes,  successful solution to your brainteaser)if successes < 20:    print(there were almost no solutions)elif successes < 100:    print(there were not many solutions)elif successes < 1000:    print(there were more than a hundred solutions it is definitely not impossible :))else:    print(that's a lot of successes)print(There were , len(middlenumber) - len(set(middlenumber)) ,  duplicates, by the way :))My program worked quite well but then I decided could you do the same for 6 digits? For the 3 digit problem the program had 96 possiblities to iterate over. Which is a measly 531,441 iterations. However for the 6 digit there is 912 possiblities, which is a colossal 282,429,536,481 iterations. This is going to take my computer days to solve.I have already tried optimizing my program but I can't figure out how to do it any faster.
Compose valid subtractions using all digits from a set
python;beginner;time limit exceeded
In solver:A function name should usually be either a verb describing what the function does, or a noun describing its result. You have a noun describing what it does, and then not very well - it doesn't actually solve anything, it just checks a solution. Call it check_digits. A docstring also wouldn't hurt.number and number2 aren't the best argument names, although it is hard to come up with better ones here - you could use minuend and subtrahend, although those are slightly obscure and the difference between them probably doesn't matter here (whether the solution is positive or negative, it will have the same digits). Distinct one-letter names are probably best here, as long as you explain them in your docstring.Your return values are either a string of all the digits in the equation, or False. Stick with bools and just return either True or False.I think you can remove numberofdigits here. You already restrict the search space to numbers with the appropriate length, and so it should be sufficient to check that all of 1-9 appear the same number of times as each other. Instead of searching the whole string with str.count multiple times, use a Counter. You can also collapse the loop into a single generator expression; you could get goodChecks by calling sum, but since you only care about whether they all check out, all is a better fit.So we would get:from collections import Counterdef check_digits(a, b):    '''    Check if the equation a - b = c uses all the digits 1 through 9    an equal number of times    '''    count = Counter(str(a) + str(b) + str(a-b))    return all(count[str(i)] == count['1'] for i in range(1, 10))Going down, middlenumber is a .. very strange name for a list. It seems to contain solutions, although you put two numbers in it each success, which seems odd; but I'll assume that that makes sense, and say call it solutions. You don't need the number successes at all - the way you use it, it will always just be len(solutions). The two if statements could be combined, as in:if num_of_digits == 3:    minX = 123    minY = 381In your loop, you have a list called numberlist which gets the same things as solutions except its cleared for every y. You don't actually use it, so you could just drop it completely. If you do want to keep track of which solutions go with which y, you could change solutions into a defaultdict(list), and then do:solutions[y].extend([x, y-z])That would mean the total number of solutions would be sum(len(v) for v in solutions.values()), and the unique solutions would be set().union(*solutions.values()) (which is slightly unfortunate, but not too bad).In the x loop, comparing against False is always odd, and with these changes you don't need to anymore - you can now do:if check_digits(y, x):    solutions.extend([x, y-x])    print(y, x, y-x, sep='')To get the same effect as returning the digits, but it might make more sense to print the equation, eg:print(y, '-', x, '=', y-x)To optimise this type of problem, the best way is usually to rethink your strategy. You currently generate most of the possible pairs of numbers of the appropriate length, calculate their difference, and then check if the equation satisfies your constraints. As you note, that is a massive search space. Consider the following type of strategy instead:Generate all the sets of three three-digit numbers from the digits 1 through 9 (itertools.permutations will help you here)For each triple x,y,z , check if x-y = z.This will reduce your search space, and also allow you to use ints everywhere, and not parse them into strings.