4
\$\begingroup\$

Task

You are given a string S containing only decimal digits ('0' through '9') and a number N. Your task is to insert an arbitrary number (including zero) of plus signs '+' into S in order to form a valid expression whose value is equal to N.

Input

  • The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.

  • The first and only line of each test case contains a string S, followed by a space and an integer N.

Output

For each test case, print a single line containing one string — your solution, i.e. the expression obtained after inserting some plus signs into S. If there are multiple solutions, you may output any one. It is guaranteed that at least one solution exists.

My code is not very optimized but gives the correct answer. Help me find an optimized version.

import itertools
case=input("")
for i in range(case): 
 text,text2=str(raw_input("")).split()
 text=list(text)
 text1=""
 l=[]
 def break_down(text):
 words = text.split()
 ns = range(1, len(words)) # n = 1..(n-1)
 for n in ns: # split into 2, 3, 4, ..., n parts.
 for idxs in itertools.combinations(ns, n):
 yield [' '.join(words[i:j]) for i, j in zip((0,) + idxs, idxs + (None,))]
 for i in text:
 #to add whitespace in between so that split() functions separates it correctly 
 text1=text1+i
 text1=text1+" " 
 for x in break_down(text1):
 #this part calls the generator and sums every iteration
 sum=0
 answer=""
 for i in range(len(x)):
 #removing the whitespaces that were added before 
 x[i]=x[i].replace(" ","")
 #converts string to int so that it actually adds number not concatenates them
 x=[int(i) for i in x]
 for i in x:
 #calculating sum
 sum+=i
 if sum==int(text2):
 l=x 
 #if the sum is equal to given number then it prints it out in the asked manner
 for i in l:
 i=str(i) 
 answer+=i
 answer+="+"
 if int(text1.replace(" ",""))==int(text2):
 print int(text1.replace(" ",""))
 else:
 print answer[:len(answer)-1]

Example Input

4
15112 28
120012 33
123 123
15489001 10549

Example Output

15+11+2
1+20+012
123
1548+9001
Mast
13.8k12 gold badges57 silver badges127 bronze badges
asked Jun 9, 2018 at 19:33
\$\endgroup\$
1
  • \$\begingroup\$ I'm assuming Python 2.7.x here. If you're using an older version, please clarify. \$\endgroup\$ Commented Jun 10, 2018 at 6:40

1 Answer 1

7
\$\begingroup\$

Python 2

Python 2 is end-of-life, and Python 3 has a lot of advantages now:

  • f-strings
  • unicode support
  • ...

More info here, here and on many other places.

If you need python 2.7, try to make your code compatible with both.

Split it into functions

You do that to a limited extent with break_down, but you can do it in a lot more places:

  • parsing the input
  • breaking the input into parts
  • calculating the sum of the parts
  • output

    from __future__ import print_function
    

Parsing the input

you do input("") a lot. If you skip the "", you can test your input parsing with something like

input_str = '''4
15112 28
120012 33
123 123
15489001 10549'''
input = iter(input_str.split('\n')).__next__

In the parsing of the input, you iterate over the string, insert a space between characters and then split on the space, while all you need to do is list(text).

So I would go for:

def parse_input():
 cases = int(input())
 for _ in range(cases):
 question, answer = input().split()
 yield question, answer
list(parse_input())
[('15112', '28'), ('120012', '33'), ('123', '123'), ('15489001', '10549')]

Splitting the input

This is what your break_down does. But you format its answer as a str with spaces between the numbers. Why not just yield the ints immediately with int(''.join(words[i:j])) instead of ' '.join(words[i:j])

instead of words for the collection of digits, I would use digits as name. Same with ns and n, I don't find their purpose clear by their name, but I can't find a good, clear name instantly either.

For python 2 and 3 portability, you will need to do list(range(...)), because you iterate over ns twice

And your solution with zip((0,) + idxs, idxs + (None,)) is also well found, but not clear what exactly it does. The same idea can be made more clear using the pairwise itertools recipe.

def pairwise(iterable):
 '''
 s -> (s0,s1), (s1,s2), (s2, s3), ...
 https://docs.python.org/3/library/itertools.html#itertools-recipes
 '''
 a, b = itertools.tee(iterable)
 next(b, None)
 return zip(a, b)
def break_down(text):
 digits = list(text)
 ns = list(range(1, len(digits))) # n = 1..(n-1)
 for n in ns: # split into 2, 3, 4, ..., n parts.
 for idxs in itertools.combinations(ns, n):
 idxs = (0, *idxs, None)
 yield tuple(int(''.join(digits[i:j])) for i, j in pairwise(idxs))

Calculating the sum

instead of

 x=[int(i) for i in x]
 for i in x:
 #calculating sum
 sum+=i

you can use the builtin sum (if you don't overwrite the name with a variable like here) total = sum(map(int, x) does the same as these original 3 lines.

But since we already got ints from the previous part instead of strings, just sum will do:

def check_sum(question, target):
 for parts in breakdown(question):
 if sum(parts) == target:
 yield parts

formatting the answer can also be more efficient and clear than manually putting '+' between all parts.

def format_answer(answer):
 return '+'.join(map(str, answer))

Putting it together

def solve_query(query):
 question, target = query
 target = int(target)
 answer = next(find_sums(question, target))
 return format_answer(answer)

and then, behind a main guard:

if __name__ == '__main__':
 queries = parse_input()
 for query in queries:
 print(solve_query(answer))
Daniel
4,6122 gold badges18 silver badges40 bronze badges
answered Jun 10, 2018 at 12:19
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.