Weekly Challenge: Reverse Positions

Weekly Challenge 318 Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. It's a great way for us all to practice some coding. I only have Python solutions this week. Like most of Australia (and New Zealand), I'm on holiday enjoy two long weekends :) Challenge, My solutions Task 1: Group Position Task You are given a string of lowercase letters. Write a script to find the position of all groups in the given string. Three or more consecutive letters form a group. Return "" if none found. My solution For this task, I use regular expressions to find the groups within a string. The Python code is def group_position(letters: str) -> list[str]: matches = re.findall(r"((.)\2{2,})", letters) return [m[0] for m in matches] In the regular expression: (.) matches any single character \2 matches that character again, and {2,} matches it two or more times. The outer () matches the sequence of letters. The findall function returns a tuple of each match. For the first example it returns ("ccc", "c"). As we only want the whole match the last line in my solution achieves this. Examples ./ch-1.py abccccd "cccc" $ ./ch-1.py aaabcddddeefff "aaa", "dddd", "fff" $ ./ch-1.py abcdd "" Task 2: Reverse Equals Task You are given two arrays of integers, each containing the same elements as the other. Write a script to return true if one array can be made to equal the other by reversing exactly one contiguous subarray. My solution For the command line input I take an array of integers. I then split the list by two to send to the function as described below. I start out my solution by checking if the lists are equal. If they are, reversing any single digit ensures that the arrays remain equal. def reverse_equal(list1: list[int], list2: list[int]) -> bool: if list1 == list2: return True I then perform some checks to see that the criteria is matched. The lists are of equal length. There are no values in one list that are not in the other. For this I turn the lists into sets and compare them. The sum of the two lists are equal. This would catch issues like 1, 1, 2, 4 and 1, 2, 2, 4. if len(list1) != len(list2): raise ValueError('Lists must be of the same length') if u := set(list1) ^ set(list2): raise ValueError( f"These items don't appear in both lists: {', '.join(u)}") if sum(list1) != sum(list2): raise ValueError("The list does not container the same values") If we reached this point, I can start to see if a solution is possible. I have two loops. The outer loop is called start and is from 0 to two less than the length of the array. The inner loop uses a variable stop and is from one more than start to the length of the string. For each iteration, I reverse the integers in the second list from start to one less than stop (it's a Python thing that the range feature excludes the last value). If this matches the first list, I return True. for start in range(len(list1)-1): for stop in range(start+2, len(list1)+1): new_list = list2.copy() new_list[start:stop] = list(reversed(new_list[start:stop])) if new_list == list1: return True Finally, I return False if no solution is possible. return False Examples $ ./ch-2.py 3 2 1 4 1 2 3 4 True $ ./ch-2.py 1 3 4 4 1 3 False $ ./ch-2.py 2 2 True

Apr 27, 2025 - 13:48
 0
Weekly Challenge: Reverse Positions

Weekly Challenge 318

Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. It's a great way for us all to practice some coding.

I only have Python solutions this week. Like most of Australia (and New Zealand), I'm on holiday enjoy two long weekends :)

Challenge, My solutions

Task 1: Group Position

Task

You are given a string of lowercase letters.

Write a script to find the position of all groups in the given string. Three or more consecutive letters form a group. Return "" if none found.

My solution

For this task, I use regular expressions to find the groups within a string. The Python code is

def group_position(letters: str) -> list[str]:
    matches = re.findall(r"((.)\2{2,})", letters)
    return [m[0] for m in matches]

In the regular expression:

  1. (.) matches any single character
  2. \2 matches that character again, and
  3. {2,} matches it two or more times.
  4. The outer () matches the sequence of letters.

The findall function returns a tuple of each match. For the first example it returns ("ccc", "c"). As we only want the whole match the last line in my solution achieves this.

Examples

 ./ch-1.py abccccd
"cccc"

$ ./ch-1.py aaabcddddeefff
"aaa", "dddd", "fff"

$ ./ch-1.py abcdd
""

Task 2: Reverse Equals

Task

You are given two arrays of integers, each containing the same elements as the other.

Write a script to return true if one array can be made to equal the other by reversing exactly one contiguous subarray.

My solution

For the command line input I take an array of integers. I then split the list by two to send to the function as described below.

I start out my solution by checking if the lists are equal. If they are, reversing any single digit ensures that the arrays remain equal.

def reverse_equal(list1: list[int], list2: list[int]) -> bool:
    if list1 == list2:
        return True

I then perform some checks to see that the criteria is matched.

  1. The lists are of equal length.
  2. There are no values in one list that are not in the other. For this I turn the lists into sets and compare them.
  3. The sum of the two lists are equal. This would catch issues like 1, 1, 2, 4 and 1, 2, 2, 4.
    if len(list1) != len(list2):
        raise ValueError('Lists must be of the same length')

    if u := set(list1) ^ set(list2):
        raise ValueError(
            f"These items don't appear in both lists: {', '.join(u)}")

    if sum(list1) != sum(list2):
        raise ValueError("The list does not container the same values")

If we reached this point, I can start to see if a solution is possible. I have two loops. The outer loop is called start and is from 0 to two less than the length of the array. The inner loop uses a variable stop and is from one more than start to the length of the string.

For each iteration, I reverse the integers in the second list from start to one less than stop (it's a Python thing that the range feature excludes the last value). If this matches the first list, I return True.

    for start in range(len(list1)-1):
        for stop in range(start+2, len(list1)+1):
            new_list = list2.copy()
            new_list[start:stop] = list(reversed(new_list[start:stop]))

            if new_list == list1:
                return True

Finally, I return False if no solution is possible.

    return False

Examples

$ ./ch-2.py 3 2 1 4 1 2 3 4
True

$ ./ch-2.py 1 3 4 4 1 3
False

$ ./ch-2.py 2 2
True