This article discusses and contains the Python code solution for the American Computer Science League (ACSL) Junior Division 2023-2024 Finals #1 Problem Run-Length Encoding.
Run-Length Encoding problem
Run-Length Encoding problem
The Run-Length Encoding problem was the first programming problem in the ACSL Junior Division 2023-2024 Finals.
First, please read the Run-Length Encoding problem. Make sure you understand the problem. Read it many times, if necessary. Then, write the algorithm on paper before coding anything. For your algorithm, you can write either pseudocode or a diagrammatical flowchart.
Programming Solution Logic
The input is a line of data containing a code from one of these values E, EV, D and DV, and the message to be encoded to decoded.
The output is a line with either the encoded or decoded messages.
Assuming you have read the problem, we find that this is quite straightforward. There are 4 types of possible codes and we can work on each part separately.
Let us refer to the code as code and the message as s.
1) code = E
We have to encode the message. For every repeating letter, the new encoded message will have 1 less than the number of occurrences, in hexadecimal.
- Create new variable
new_sthat will contain the encoded message. - Create new variable
letterthat will represent the current character. - Create new variable
countthat will contain the number of timesletterhas appeared in this sequence. - Now, loop through every character in message
s. - If the character is the same as
letter, increase the count by 1. - If the character is not the same as
letterand this is not the first iteration started by loop at (4), we will convert the value ofcount - 1to chunks of 16, and then to hexadecimal. - To convert the count to chunks of 16, subtract 16 repeatedly from the
count - 1value and write it aslettersuffixed withF. The last value will be directly converted to hexadecimal. - For each of these, we append the character value of
letterand hexadecimal uppercase value of the chunk tonew_s. - Continue with the loop started at (4) until all characters in
sare exhaused.
2) code = EV
We have to encode the message. This is similar to the previous Case 1 except that the new encoded message will contain the number of times, in hexadecimal. If the final count has 2 or more hexadecimal digits, this count is prefixed and suffixed by -.
- Create new variable
new_sthat will contain the encoded message. - Create new variable
letterthat will represent the current character. - Create new variable
countthat will contain the number of timesletterhas appeared in this sequence. - Now, loop through every character in message
s. - If the character is the same as
letter, increase the count by 1. - If the character is not the same as
letterand this is not the first iteration started by loop at (4), we will convert the value ofcountdirectly to hexadecimal. - If the value of
countis greater than 16, convertcountto hexadecimal, prefix and suffix it with-. - For each of these, we append the character value of
letterand hexadecimal uppercase value of the chunk tonew_s. - Continue with the loop started at (4) until all characters in
sare exhaused.
3) code = D
We have to decode the message. This is the opposite of Case 1.
- Create new variable
new_sthat will contain the decoded message. - Loop through message
stwo characters at a time; the first character is the current characterletterand the second character iscount, the number of times, in hexadecimal, the characterletteris repeating. - For every iteration, we append
countoccurrences of the characterletter. For example,dAwill printddddddddddbecausedis to be printedA16, which is 10 times. - Append the string created in (3) to
new_s. - Continue with the loop started at (2) until all characters in
sare exhaused.
4) code = DV
We have to decode the message. This is the opposite of Case 2.
- Create new variable
new_sthat will contain the decoded message. - Loop through message
stwo characters at a time. - If the second character
countis a hyphen-, jump to step (9). Or else, go to step (4). - The first character is the current character
letterand the second character iscount, the number of times, in hexadecimal, the characterletteris repeating. - For every iteration, we append
countoccurrences of the characterletter. For example,dAwill printddddddddddbecausedis to be printedA16, which is 10 times. - Append the string created in (4) to
new_s. - Continue with the loop started at (2) until all characters in
sare exhaused. - Jump to step (12).
- At this point,
counthas a-instead of a hexadecimal number. We start another loop and capture the hexadecimal numbers from the first-to the next-. - For every hexadecimal digit found in (9), convert it to integer and append
countoccurrences ofletter. For example,f-2F-will printf2 * 16 + 15times = 47 times. So this line will append 47 occurrences offtonew_s. - Continue with the loop started at (2) until all characters in
sare exhaused. - End
My Python solution
I created the main function using the provided test cases with their output and function encode_decode(code, s).
This is my Python solution:
# Function to encode or decode the string
def encode_decode(code, s):
new_s = ''
if code.startswith('E'):
letter = s[0]
count = 0
for i, x in enumerate(s):
if i > 0 and letter != x:
if code == 'E':
count -= 1
if count > 16:
while count > 16:
new_s += letter + 'F'
count -= 16
count = hex(count)[2:].upper()
else:
if count > 16:
count = '-' + hex(count)[2:].upper() + '-'
new_s += letter + str(count)
letter = x
count = 1
else:
count += 1
# For the last letter count
if code == 'E':
count -= 1
if count > 16:
while count > 16:
new_s += letter + 'F'
count -= 16
count = hex(count)[2:].upper()
else:
if count > 16:
count = '-' + hex(count)[2:].upper() + '-'
new_s += letter + str(count)
elif code == 'D':
letter = None
count = 0
s_len = len(s)
for i in range(s_len // 2):
letter = s[i * 2]
count = int(s[i * 2 + 1], 16) + 1
new_s = new_s + letter * count
elif code == 'DV':
i = 0
while i < len(s) - 1:
letter = s[i]
count = s[i + 1]
if count in '1234567890':
new_s += letter * int(count)
elif count in 'abcdefABCDEF':
count = int(s[i + 1], 16)
new_s = new_s + letter * count
elif count == '-':
i += 2
hex_num = ''
while s[i] != '-':
hex_num += s[i]
i += 1
if hex_num != '':
i -= 1
count = int(hex_num, 16)
new_s += letter * count
i += 2
return new_s
# Main function
if __name__ == '__main__':
input_data = '''
E ABBCEEEEAAAAAADDDAAACCCCCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAA
EV ABBCEEEEAAAAAADDDAAACCCCCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAA
D a0b1a2dAfFfFfEE2
DV a1b2a3dBf-2F-E3
'''
output_data = '''
A0B1C0E3A5D2A2C4BFBDA1
A1B2C1E4A6D3A3C5B-1E-A2
abbaaadddddddddddfffffffffffffffffffffffffffffffffffffffffffffffEEE
abbaaadddddddddddfffffffffffffffffffffffffffffffffffffffffffffffEEE
'''
sample_input = [x.split() for x in input_data.strip().split('\n')]
expected_output = output_data.strip().split('\n')
for i, (c, s) in enumerate(sample_input):
print(expected_output[i] == encode_decode(c, s))
Decoding the program
In the main function, I created a string input_data with the test input, one test case per line.
Using list comprehension, I split it into a 2D list.
A second string output_data contains the expected output, one test case output per line.
The function encode_decode() is called and passes the code and message as parameters.
Useful Python code snippets
There are many code snippets that can be used in competitive programming contests. These are a few.
Use for loop with enumerate
While iterating through the string s, we need the index as well as the current character. So, we use enumerate().
Convert from integer to hexadecimal
Let us do this with an example. The number 123 is 7B16 in hexadecimal. We will use hex(123) followed by string slicing from third character onwards using [2:] followed by.upper()` method. Try this on your Python shell.
>>> hex(123)
'0x7b'
>>> hex(123)[2:]
'7b'
>>> hex(123)[2:].upper()
'7B'
Convert from hexadecimal to integer
The number A1016 in hexadecimal equals 2576 in decimal. We will use int('A10', 16) to convert to hexadecimal A10 to decimal.
>>> int('A10', 16)
2576
Check if a string with a single-digit contains a valid number
There are many ways of doing this. I prefer this block of code expression:
count in '1234567890'
Example:
>>> count = '5'
>>> count in '1234567890'
True
Check if a string with a single-digit contains a valid hexadecimal number from A through F
You can use this block of code expression:
count in 'abcdefABCDEF'
Example:
>>> count = 'e'
>>> count in 'abcdefABCDEF'
True
>>> count = 'E'
>>> count in 'abcdefABCDEF'
True
You can also use:
count.upper() in 'ABCDEF'
Print a repeated string using *
If you want to print the letter f 47 times, then this will work:
>>> print('f' * 47)
fffffffffffffffffffffffffffffffffffffffffffffff
Use the Python shell
We have already used the Python shell quite a few times here. When lost, just open up the Python shell and try random code there to see what options you have with the code you plan to use.
Do not be afraid to try different code styles.
Combine common code and DRY
Wherever possible, see if you can combine common code that repeats itself. DRY stands for don't repeat yourself. You can either use repeating code in a function with appropriate parameters. If you don't have time, or it's too late to make a clean fix, just leave it as it is, as long as it is working properly.
Running the Python code
Run the Python code from your Terminal. You do not need to use any input file because I added the input as a string in the main function.
When the program runs, this will be the output:
$ python run_length_encoding_decoding.py
True
True
True
True
Conclusion
If there is anything you would like me to add to this article, feel free to comment below or contact me. Thanks.
Related Posts
If you have any questions, please contact me at arulbOsutkNiqlzziyties@gNqmaizl.bkcom. You can also post questions in our Facebook group. Thank you.