3

I need to punch() out specific characters out of a string based on an index template (mask?).

For example, I need to punch out all the characters where there is a 1

str = abcdefg
mask = 0011001

// len(str) = len(mask) always

print(punch(str, mask)) //Ouput: cdg 

Essentially I need to print all the non empty subsequences of a given string:

Input: abcd
Output: a, b, c, d, ab, ac, ad, bc, bd, cd, abc, abd, acd, bcd, abcd

I am trying to implement this using brute force so I would generate all the templates for the length of input string and using the punch() to "punch" out those subsequences.

PS: This may be a bad way to solve this prob, but I think punch() a nifty method to have.

enemetch
  • 492
  • 2
  • 8
  • 21
  • Possible dupe [What's a good way to get all subsets of a set? (powerset)](https://stackoverflow.com/q/1482308/674039) – wim Oct 22 '18 at 01:19
  • If `mask` is a string: `"".join(ch for ch, msk in zip(string, mask) if msk == "1")` – jasonharper Oct 22 '18 at 01:19

2 Answers2

3

You could potentially use ‘compress()’ from Itertools to create a binary filter.

Compress takes two arguments

  1. The iterable that you want to go over and ‘punch’ out characters

  2. The data which defines which elements from the first iterable are removed. Any ‘True’ element will enable compress to remove the element from the first iterable

    Screenshot from the Itertools Docs

James
  • 56
  • 3
  • 1
    This is beautiful. The only reason itertools wasn't renamed to solveeverysingleproblemeverwithnoeffort is because the latter name would be unreadable. – Purple Ice Oct 22 '18 at 07:57
2

If I'm reading what you want to do correctly, a function like this could work.

def punch(str, mask):
   if (len(str) == len(mask)):
       new_list = []
       for i in range(len(str)):
           if mask[i] == "1":
             new_list.append(str[i])
       return new_list
   else:
       return -1