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

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 :)
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
and1, 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