简体   繁体   中英

Write a function that determines the maximum number of consecutive BA, CA character pairs per line

My respects, colleagues. I need to write a function that determines the maximum number of consecutive BA, CA character pairs per line.

print(f("BABABA125"))  # -> 3
print(f("234CA4BACA"))  # -> 2
print(f("BABACABACA56"))  # -> 5
print(f("1BABA24CA"))  # -> 2

Actually, I've written a function, but, to my mind, it's not very good.

def f(s: str) -> int:

    res = 0

    if not s:
        return res

    cur = 0
    i = len(s) - 1

    while i >= 0:
        if s[i] == "A" and (s[i-1] == "B" or s[i-1] == "C"):
            cur += 1
            i -= 2
        else:
            if cur > res:
                res = cur
                cur = 0
            i -= 1
    else:
        if cur > res:
            res = cur

    return res

In addition, I'm not allowed to use libraries and regular expressions (only string and list methods) . Could you please help me or rate my code in this context. I'll be very grateful.

Here's a function f2 that performs this operation.

  1. if not re.search('(BA|CA)', s): return 0
    First check if the string actually contains any BA or CA (to prevent ValueError: max() arg is an empty sequence on step 3), and return 0 if there aren't any.
  2. matches = re.finditer(r'(?:CA|BA)+', s)
    Find all consecutive sequences of CA or BA , using non-capturing groups to ensure re.finditer outputs only full matches instead of partial matches.
  3. res = max(matches, key=lambda m: len(m.group(0)))
    Then, among the matches ( re.Match objects), fetch the matched substring using m.group(0) and compare their lengths to find the longest one.
  4. return len(res.group(0))//2
    Divide the length of the longest result by 2 to get the number of BA or CA s in this substring. Here we use floor division // to coerce the output into an int , since division would normally convert the answer to float .
import re

strings = [
    "BABABA125",  # 3
    "234CA4BACA",  # 2
    "BABACABACA56",  # 5
    "1BABA24CA",  # 2
    "NO_MATCH_TO_BE_FOUND",  # 0
]

def f2(s: str):
    if not re.search('(BA|CA)', s): return 0
    matches = re.finditer(r'(?:CA|BA)+', s)
    res = max(matches, key=lambda m: len(m.group(0)))
    return len(res.group(0))//2

for s in strings:
    print(f2(s))

UPDATE: Thanks to @StevenRumbalski for providing a simpler version of the above answer. (I split it into multiple lines for readability)

def f3(s):
    if not re.search('(BA|CA)', s): return 0
    matches = re.findall(r'(?:CA|BA)+', s)
    max_length = max(map(len, matches))
    return max_length // 2
  1. if not re.search('(BA|CA)', s): return 0
    Same as above
  2. matches = re.findall(r'(?:CA|BA)+', s)
    Find all consecutive sequences of CA or BA , but each value in matches is a str instead of a re.Match , which is easier to handle.
  3. max_length = max(map(len, matches))
    Map each matched substring to its length and find the maximum length among them.
  4. return max_length // 2
    Floor divide the length of the longest matching substring by the length of BA , CA to get the number of consecutive occurrences of BA or CA in this string.

Here's an alternative implementation without any imports. Do note however that it's quite slow compared to your C-style implementation.

The idea is simple: Transform the input string into a string consisting of only two types of characters c1 and c2 , with c1 representing CA or BA , and c2 representing anything else. Then find the longest substring of consecutive c1 s.

The implementation is as follows:

  1. Pick a char that is guaranteed not to appear in the input string; here we use + as an example. Then pick a char different from the previous one; here we use - .
  2. Replace each occurrence of CA and BA with a + .
  3. Replace everything else in the string (that is not a + ) with a - (this is why + cannot be present in the original input string). Now we have a string consisting purely of + s and - s.
  4. Split the string with - as delimiter, and map each resulting substring to their length.
  5. Return the maximum of these substring lengths.
strings = [
    "BABABA125",  # 3
    "234CA4BACA",  # 2
    "BABACABACA56",  # 5
    "1BABA24CA",  # 2
    "NO_MATCH_TO_BE_FOUND",  # 0
]

def f4(string: str):
    string = string.replace("CA", "+")
    string = string.replace("BA", "+")
    string = "".join([(c if c == "+" else "-") for c in string])
    str_list = string.split("-")
    str_lengths = map(len, str_list)
    return max(str_lengths)

for s in strings:
    print(f4(s))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM