3

so i need to code a program which, for example if given the input 3[a]2[b], prints "aaabb" or when given 3[ab]2[c],prints "abababcc"(basicly prints that amount of that letter in the given order). i tried to use a for loop to iterate the first given input and then detect "[" letters in it so it'll know that to repeatedly print but i don't know how i can make it also understand where that string ends also this is where i could get it to,which probably isnt too useful:

string=input()
string=string[::-1]
bulundu=6
for i in string:
    if i!="]":
        if i!="[":
            lst.append(i)
        if i=="[":
            break
2
  • 2
    Are you allowed to use regex? for cnt, letters in re.findall(r"(\d+)\[([^\]]+)\]", "3[ab]2[c]"): print(letters * int(cnt), end='') ?? Commented Dec 6, 2021 at 14:15
  • Is '5[23]' something you need to be able to do? Is '22[a]' something you need to be able to do? Commented Dec 6, 2021 at 15:30

5 Answers 5

0

The approach I took is to remove the brackets, split the items into a list, then walk the list, and if the item is a number, add that many repeats of the next item to the result for output:

import re

data = "3[a]2[b]"
# Remove brackets and convert to a list
data = re.sub(r'[\[\]]', ' ', data).split()

result = []
for i, item in enumerate(data):
  # If item is a number, print that many of the next item
  if item.isdigit():
    result.append(data[i+1] * int(item))

print(''.join(result))
# aaabb
Sign up to request clarification or add additional context in comments.

Comments

0

A different approach, inspired by Subbu's use of re.findall. This approach finds all 'pairs' of numbers and letters using match groups, then multiplies them to produce the required text:

import re

data = "3[a]2[b]"

matches = re.findall('(\d+)\[([a-zA-Z]+)\]',data)
# [(3, 'a'), (2, 'b')]
for x in matches:
    print(x[1] * int(x[0]), end='')
    #aaabb

Comments

0

Lenghty and documented version using NO regex but simple string and list manipulation:

  • first split the input into parts that are numbers and texts
  • then recombinate them again
  • I opted to document with inline comments

This could be done like so:

# testcases are tuples of input and correct result
testcases = [ ("3[a]2[b]","aaabb"), 
              ("3[ab]2[c]","abababcc"), 
              ("5[12]6[c]","1212121212cccccc"), 
              ("22[a]","a"*22)]

# now we use our algo for all those testcases
for inp,res in testcases:

    split_inp = []   # list that takes the splitted values of the input
    num = 0          # accumulator variable for more-then-1-digit numbers
    in_text = False  # bool that tells us if we are currently collecting letters

    # go over all letters : O(n)
    for c in inp:

        # when a [ is reached our num is complete and we need to store it
        # we collect all further letters until next ] in a list that we
        # add at the end of your split_inp
        if c == "[":
            split_inp.append(num)    # add the completed number 
            num = 0                  # and reset it to 0
            in_text = True           # now in text
            split_inp.append([])     # add a list to collect letters

        # done collecting letters 
        elif c == "]":
            in_text = False          # no longer collecting, convert letters
            split_inp[-1] = ''.join(split_inp[-1]) # to text


        # between [ and ] ... simply add letter to list at end
        elif in_text:
            split_inp[-1].append(c) # add letter

        # currently collecting numbers
        else:
            num *= 10      # increase current number by factor 10
            num += int(c)  # add newest number
    
    print(repr(inp), split_inp, sep="\n")  # debugging output for parsing part

    # now we need to build the string from our parsed data
    amount = 0
    result = []  # intermediate list to join ['aaa','bb']

    # iterate the list, if int remember it, it text, build composite
    for part in split_inp:
        if isinstance(part, int):
            amount = part
        else:
            result.append(part*amount)

    # join the parts 
    result = ''.join(result)


    # check if all worked out
    if result == res:
        print("CORRECT:  ", result + "\n")
    else:
        print (f"INCORRECT:  should be '{res}' but is '{result}'\n")
        

Result:

'3[a]2[b]'
[3, 'a', 2, 'b']
CORRECT:   aaabb

'3[ab]2[c]'
[3, 'ab', 2, 'c']
CORRECT:   abababcc

'5[12]6[c]'
[5, '12', 6, 'c']
CORRECT:   1212121212cccccc

'22[a]'
[22, 'a']
CORRECT:   aaaaaaaaaaaaaaaaaaaaaa

This will also handle cases of '5[12]' wich some of the other solutions wont.

Comments

0

You can capture both the number of repetitions n and the pattern to repeat v in one go using the described pattern. This essentially matches any sequence of digits - which is the first group we need to capture, reason why \d+ is between brackets (..) - followed by a [, followed by anything - this anything is the second pattern of interest, hence it is between backets (...) - which is then followed by a ]. findall will find all these matches in the passed line, then the first match - the number - will be cast to an int and used as a multiplier for the string pattern. The list of int(n) * v is then joined with an empty space. Malformed patterns may throw exceptions or return nothing.

Anyway, in code:

import re

pattern = re.compile("(\d+)\[(.*?)\]")

def func(x): return "".join([v*int(n) for n,v in pattern.findall(x)])

print(func("3[a]2[b]"))
print(func("3[ab]2[c]"))

OUTPUT

aaabb
abababcc

FOLLOW UP

Another solution which achieves the same result, without using regular expression (ok, not nice at all, I get it...):

def func(s): return "".join([int(x[0])*x[1] for x in map(lambda x:x.split("["), s.split("]")) if len(x) == 2])

Comments

0

I am not much more than a beginner and looking at the other answers, I thought understanding regex might be a challenge for a new contributor such as yourself since I myself haven't really dealt with regex.

The beginner friendly way to do this might be to loop through the input string and use string functions like isnumeric() and isalpha()

data = "3[a]2[b]"
chars = []
nums = []
substrings = []

for i, char in enumerate(data):
    if char.isnumeric():
        nums.append(char)
    if char.isalpha():
        chars.append(char)

for i, char in enumerate(chars):
    substrings.append(char * int(nums[i]))
string = "".join(substrings)
print(string)

OUTPUT:

aaabb

And on trying different values for data:

data = "0[a]2[b]3[p]"
OUTPUT bbppp


data = "1[a]1[a]2[a]"
OUTPUT aaaa

NOTE: In case you're not familiar with the above functions, they are string functions, which are fairly self-explanatory. They are used as <your_string_here>.isalpha() which returns true if and only if the string is an alphabet (whitespace, numerics, and symbols return false And, similarly for isnumeric()

For example,

  • "]".isnumeric() and "]".isalpha() return False
  • "a".isalpha() returns True

IF YOU NEED ANY CLARIFICATION ON A FUNCTION USED, PLEASE DO NOT HESITATE TO LEAVE A COMMENT

Comments

Your Answer

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.