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