This function takes a string of digits and a target integer and prints all possible ways to insert operators to reach the desired target. The output must in all cases contain all the digits in order; none may be omitted.

```
#!/usr/bin/env python3

def find_expressions(digits, target):
    if not (isinstance(digits, str) or isinstance(digits, list)) or not isinstance(target, int):
        raise TypeError
    if len(digits) != 5:
        raise TypeError('digits must be of length 5')
    solutions = []
    operators = ('', ' + ', ' - ', ' * ', ' / ')
    for i in operators:
        for j in operators:
            for k in operators:
                for l in operators:
                    s = digits[0] + i + digits[1] + j + digits[2] + k + digits[3] + l + digits[4]
                    try:
                        if eval(s) == target:
                            solutions.append(s + ' == {}'.format(target))
                    except (ZeroDivisionError, SyntaxError):
                        pass
    print('\n'.join(solutions))

```

It isn't pretty, but it works. The problem is that it only takes strings of length 5. How can I make it take strings of arbitrary length? (E.g., calling `find_expressions('12345678', 2)` should be valid.) I'm thinking I need to replace the `for` loops with recursion, but I'm at a loss as to how to accomplish this.

Example Output
==============

Calling `find_expressions('75228', 5)` prints:

```
7 + 5 + 2 / 2 - 8 == 5
7 * 5 - 22 - 8 == 5
7 * 5 - 2 - 28 == 5

```

Caveat
======

I'm not satisfied with the whole brute-force approach I'm taking by looping over every possibility. If there's a better algorithm overall, I'd like to hear about it. *However,* this question is about making this function take arbitrary-length input while making the smallest possible changes.