0

Suppose I have a string containing the following:

'*as**4fgdfgd*vv**6fdfd5***5'

String contains numbers, letters, and a special symbol such as an asterisk.

  • I need to find the sum of numbers (4,6) (5,5) separated by asterisk.
  • The number of asterisks between two numbers must be equal to 3.
  • Return True if sum of every pair is equal to 10.

Examples:

  • *as**4fgdfgd*vv**6fdfd5***5 returns True.
  • ssss*0***10jkj* **0***10 returns True.
  • 5***5***5 returns True because there 3 asterisks between the numbers and sum equals 10.
  • 8**‍‍‍‌‍‌‌‌‌‌‌‍‌‍‍‌‍‍2 returns False

My Code So far:

my_str = "*as**4fgdfgd*vv**6fdfd5***5"

my_digits = [int(x) for x in my_str if x.isnumeric()]

print(sum(my_digits))
meallhour
  • 13,921
  • 21
  • 60
  • 117
  • The first condition (three symbols between a number pair) can be checked via a regex. You can then iterate over the matches, calculate the pair's sum and check if it equals 10. – Jan Wilamowski Sep 16 '22 at 02:44
  • So for `5***5***4` would you return true or false? because 5+5 = 10, but 5+4 = 9 – Nick Sep 16 '22 at 02:44
  • `5***5***4` will return `false` – meallhour Sep 16 '22 at 02:45
  • How does 5+5+5 = 10? I'm confused about the rules in this problem. In fact, most of the examples you give don't seem to follow a logical consistency. – Chowlett2 Sep 16 '22 at 02:52
  • @Chowlett2 it's the sum of every *pair* of digits that are separated by 3 asterisks, so `5+5` and `5+5`, which are both `10` – Nick Sep 16 '22 at 02:56
  • @Nick I see now, they kind of worded it in a way that made it seem like it's an overall sum, and they also made it seem like we must return True if the sum is 10, not if every sum of every pair is 10. And they also said that every number MUST be separated by 3 asterisks, which further obfuscates things. – Chowlett2 Sep 16 '22 at 03:02
  • @Chowlett2 hmmm... when you put it like that... I guess my brain must just work in the same twisted way :) – Nick Sep 16 '22 at 03:03

1 Answers1

3

You can use a regex to find pairs of numbers that are separated by 3 asterisks, then convert the found numbers to int and add them, returning true if all pairs add to 10. Note that because you want overlapping matches, we need to use a lookahead as described in this question.

def all_tens(my_str):
    pairs = re.findall(r'(?=(?<!\d)(\d+)(?:[^*\d]*\*){3}[^*\d]*(\d+))', my_str)
    return len(pairs) > 0 and all(sum(map(int, pair)) == 10 for pair in pairs)

strs = [
 '*as**4fgdfgd*vv**6fdfd5***5', 'ssss*0***10jkj* **0***10', '5***5***5', '8**‍‍‍‌‍‌‌‌‌‌‌‍‌‍‍‌‍‍2', '5***5***4'
]
for s in strs:
    print(f'{s} : {all_tens(s)}')

Output:

*as**4fgdfgd*vv**6fdfd5***5 : True
ssss*0***10jkj* **0***10 : True
5***5***5 : True
8**2 : False
5***5***4 : False

Regex explanation:

(?=(?<!\d)(\d+)(?:[^*\d]*\*){3}[^*\d]*(\d+)(?!\d))
  • (?= a lookahead (we use this to allow overlapping matches)
  • (?<!\d) the preceding character must not be a digit
  • (\d+) some digits, captured in group 1
  • (?:[^*\d]*\*){3} 3 sets of an asterisk, which may be preceded by some number of characters which are neither asterisks or digits
  • [^*\d]* some number of characters which are not asterisk or digits
  • (\d+) some digits, captured in group 2
Nick
  • 138,499
  • 22
  • 57
  • 95
  • can you please help understand what is the need for lookahead and lookbehind `(?!\d)` and `(?<!\d)` conditions? – meallhour Sep 21 '22 at 04:47
  • 1
    @meallhour the lookbehind is so that you don't match `4***56***4` as `4***56` and `6***4` instead of 4***56` and `56***4`. Strictly speaking you don't need the lookahead (and in fact it's not present in the python code) – Nick Sep 21 '22 at 04:53
  • can you please help understand what do you mean by overlapping matches? `(?= a lookahead (we use this to allow overlapping matches)` ? – meallhour Sep 21 '22 at 05:17
  • @meallhour In `5***5***5` you wanted to match `5***5` and `5***5` right? In that case the two matches are overlapping because they share the middle `5` in the string. – Nick Sep 21 '22 at 05:20
  • Yeah correct. But, I am getting same `pairs` even without using `(?=` . I am getting `[('5', '5')]` – meallhour Sep 21 '22 at 05:23
  • 1
    @meallhour without lookahead you will only get `[('5', '5')]`, with lookahead you will get `[('5', '5'),('5', '5')]`. For this value it doesn't really matter, but with `5***5***4` without lookahead you will get `[('5', '5')]` which passes, but with lookahead you will get `[('5', '5'),('5', '4')]` which fails – Nick Sep 21 '22 at 05:26
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/248214/discussion-between-meallhour-and-nick). – meallhour Sep 21 '22 at 05:30