-1

I'm trying to augment a lengthy string that can contain multiple number of digits (0,1,2,3,4,5,6,?) Consider a string "000000000004?0??100001??2?0?10000000". I'm trying to replace all the question marks (?) by the neighbouring largest digit. The comparison should be done from both left character and right character to the question mark (?).

Input String: "000000000004?0??100001??2?0?10000000" Output String: "000000000004401110000122220110000000"

I wrote a function that ends up replacing them during the first iteration of the loop itself which results in replacing the ? by the highest number i.e, 4 in this case. Check the code snippet below.

Wrong Output: "000000000004404410000144240410000000"

def method_augment(aug_str):
    global pos_of_sec_char, sec_char, preced_char
    flag_marks_string_end = 0
    list_predef = ['0', '1', '2', '3', '4', '5', '6']
    len_aug_str = len(aug_str)
    for m in range(0, (len_aug_str - 1)):
        if aug_str[m] == '?':
            pos_of_first_ques = m
            if m != 0:
                preced_char = aug_str[m - 1]
                # print("preced char:", preced_char)
                for n in range((pos_of_first_ques + 1), (len_aug_str - 1)): 
                    if aug_str[n] in list_predef:
                        pos_of_sec_char = n
                        sec_char = aug_str[n]
                        print(sec_char)
                        if preced_char > sec_char:
                            aug_str = aug_str.replace(aug_str[pos_of_first_ques], preced_char)
                            del preced_char, sec_char, pos_of_first_ques, m
                        else:
                            aug_str = aug_str.replace(aug_str[pos_of_first_ques], sec_char)
                            del preced_char, sec_char, pos_of_first_ques
                        break
                    else:
                        flag_marks_string_end += 1

            else:
                for q in range((pos_of_first_ques + 1), (len_aug_str - 1)):
                    if aug_str[q] in list_predef:
                        pos_of_sec_char = q
                        sec_char = aug_str[q]
                        aug_str = aug_str.replace(aug_str[pos_of_first_ques], sec_char)
                        break
            # if preced_char > sec_char:
            #     aug_str = aug_str.replace(aug_str[m], preced_char)
            # else:
            #     aug_str = aug_str.replace(aug_str[m], sec_char)

        else:
            continue

    return aug_str


Input String: "000000000004?0??100001??2?0?10000000"

Expected Output String: "000000000004401110000122220110000000"

Actual Output String: "000000000004404410000144240410000000"

There are multiple strings like this with different combinations of digit and ?. I hope I have explained it well. Please help. Thanks.

YusufUMS
  • 1,506
  • 1
  • 12
  • 24

3 Answers3

0

Your program sounds overly complicated. I didn't even try to understand. Can you read and understand this?

import re


def method_augment(text: str) -> str:
    while "?" in text:
        text = replacesingle("0" + text + "0")[1:-1]   # consider starting and ending question marks
    return text


def replacesingle(text: str) -> str:
    match = re.search("\\d\\?+\\d", text)
    span = match.span(0)
    partialtext = text[span[0]:span[1]]
    left = int(partialtext[0])
    right = int(partialtext[-1])
    larger = left if left > right else right
    number_of_question_marks = len(partialtext) - 2
    text = text[:span[0] + 1] + str(larger) * number_of_question_marks + text[span[1] - 1:]
    return text


assert(method_augment("000000000004?0??100001??2?0?10000000") == "000000000004401110000122220110000000")
assert (method_augment("??123??1??") == "1112333111")
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
0

Here is a way to do it, with some tests:

def replace_with_largest(s):
    out = []
    last_left = None
    next_right = None
    for i, c in enumerate(s):
        if c in '0123456789':
            out.append(c)
            last_left = c
            next_right = None # now the next digit to the right is unknown
            continue

        # Now we have a '?'.
        # We need the next digit to the right
        if next_right is None:
            for j in range(i+1, len(s)):
                if s[j] != '?':
                    next_right = s[j]
                    break
            else:
                # No more digit right of here, we'll use the last one on the left
                next_right = last_left

        out.append(max(last_left, next_right) if last_left is not None else next_right)    

    return ''.join(out)

The tests, some strings and the expected output:

tests = [("000000000004?0??100001??2?0?10000000", "000000000004401110000122220110000000"),
         ("??123??1", "11123331"),
         ("123???", "123333")]


for test in tests:
    print(test[0], replace_with_largest(test[0]), replace_with_largest(test[0]) == test[1])

000000000004?0??100001??2?0?10000000 000000000004401110000122220110000000 True
??123??1 11123331 True
123??? 123333 True
Thierry Lathuille
  • 23,663
  • 10
  • 44
  • 50
0

I'm not sure how efficient this is but you can split your list such you retain all consecutive values of ?s and together as separate elements, pad that list with leading and trailing characters that'll never pass as the max value test compared to digits or ?s (and also make accessing indices slightly more convenient), eg:

import re

def augment(text):    
    w = [' ', *[el for el in re.split(r'(\?+)', text) if el], ' ']
    for i in range(1, len(w) - 1):
        w[i] = w[i].replace('?', max(w[i - 1][-1], w[i + 1][0]))
    return ''.join(w[1:-1]).strip() or None

Then to use it, eg:

cases = [
    '000000000004?0??100001??2?0?10000000',
    '?????????9',
    '9????????0',
    '0????????9',
    '?0???????9',
    '123???????',
    '12?????321',
    '??????????',
]

for case in cases:
    print(case, '->', augment(case))

Which gives you:

000000000004?0??100001??2?0?10000000 -> 000000000004401110000122220110000000
?????????9 -> 9999999999
9????????0 -> 9999999990
0????????9 -> 0999999999
?0???????9 -> 0099999999
123??????? -> 1233333333
12?????321 -> 1233333321
?????????? -> None
Jon Clements
  • 138,671
  • 33
  • 247
  • 280