Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This question already has an answer here:

For example, you are given the source 1234 and the target 24. The task is to use the standard arithmetic operators +-/* placed within source, without changing the order of the digits of source to create target. In this example the solutions are:

1 * 2 * 3 * 4 = 24 = target
12 + 3 * 4 = 24 = target

Another example:

target=346
source=8675309
# solution
867 - 530 + 9 = 346

My question is what data structures and algorithms should I be thinking about for this problem? I've written a solution to this using Python, but it is terribly naive and brute forces the problem. It creates all possible splits in source, and then creates all possible expressions by interleaving every combination of +-\* within the split of source.

It takes a LONG time to find this solution:

source=314159265358 
target=27182    
# solution
3141 * 5 / 9 * 26 / 5 * 3 - 5 * 8

I believe the complexity is O(2^n), where n is the number of digits in source. After each digit you can split or not.

Code below (note it errors if source has a 0):

#!/usr/bin/env python

from __future__ import print_function
from itertools import combinations
from itertools import product
from sys import argv

def split_number(s):
    """ takes input string number and splits it into strings of separate digits """
    return [_ for _ in s]

def partition_list(aList, indices):
    """ split a list into parts, splitting at the indices """
    indices = list(indices)
    return [aList[a:b] for a, b in zip([0] + indices, indices+[None])]

def create_index_splits(list_len, n):
    """ returns a list of all places to create splits to create n splits in a
    list of len list_len """
    return list(combinations(range(1, list_len), n))

def generate_expression(l, operators):
    """ takes a list of list l and a sequence of operators and creates an
    expression of the intreleaved list and operators """
    expression = [item for pair in zip(l, operators) for item in pair]

    # interleave operands and operators
    return ' '.join(expression + [l[-1]])


def generate_expressions(l):
    """generate all possible combinations of digits splits and operators """
    l = convert_list_ints_to_list_str(l)
    operators = '+/*-'

    # cartesian product of operators
    operator_combinations = product(operators, repeat=len(l) - 1)
    return [generate_expression(l, _) for _ in operator_combinations]


def convert_list_ints_to_list_str(l):
    """converst list of lists of digits to list of numbers """
    return [''.join(map(str, _)) for _ in l]


def find_solutions(a, b):
    l = split_number(a)
    index_splits = [create_index_splits(len(l), _) for _ in range(1, len(l))]
    index_splits = [i for j in index_splits for i in j]
    m = [partition_list(l, _) for _ in index_splits]
    b = int(b)
    expressions = list([generate_expressions(_) for _ in m])
    expressions = [i for j in expressions for i in j]

    return [_ for _ in expressions if eval(_) == b]


def main():
    try:
        a = argv[1]
        b = argv[2]
    except (ValueError, IndexError):
        print("invalid args")

    [print(_) for _ in find_solutions(a, b)]

if __name__ == '__main__':
    main()

To run it do python thisfile.py [source] [target]

share|improve this question

marked as duplicate by MichaelT, gnat, Jules, Ixrec, Snowman Feb 9 at 5:02

This question was marked as an exact duplicate of an existing question.

I doubt that there is a solution that is not exponential in the number of digits. It seems similar to The subset sum problem, but with an even larger search space. In other words, you can't do much better than an exhaustive search.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.