This article discusses and contains the Python code solution for the American Computer Science League (ACSL) Intermediate Division 2001-2002 Contest 1 Programming Problem Wrap Around Code.
ACSL Intermediate 2001-2002 Contest 1 Wrap Around Code problem
Wrap Around Code
The ACSL Intermediate 2001-2002 Contest 1 Wrap Around Code problem was the programming problem in ACSL Intermediate Division 2001-2002 Contest 1.
First, read the Wrap Around Code problem. Make sure you understand the problem description. Read it many times, if necessary. Then, write your algorithm on paper before coding anything. For your algorithm, you can write either pseudocode or a flowchart.
If you have worked on the Junior division version of Wrap Around Code, this is different in that the counting process starts where the last letter ends. That makes it a little more tricky.
Programming Solution Logic
First, find the numerical value of each letter
From the problem description, we have to find the numerical value for each letter. Let us refer to the letter with the variable letter.
For this, we can find the ASCII value of each letter. The ASCII value of the letter A is 65. We can use Python to find the ASCII values of A, B, and Z by running calling the ord() function on the Python shell.
>>> ord('A')
65
>>> ord('B')
66
>>> ord('Z')
90
So, to assign a numeric value of 1 to A, we find the ASCII value and subtract 64 from it. Let us represent it with variable lvalue.
lvalue = ord(letter) - 64
Next, let us review the five rules.
Five Rules
Rule 1: If letter is between A and E, we multiply its numerical value by 2.
Rule 2: If letter is between F and J, we find the mod of 3 with its numerical value and multiply the result with 5.
Rule 3: If letter is between K and O, we divide the numerical value by 4 and multiply the int value with 8.
Rule 4: If letter is between P and T, we find the sum of the digits of the numerical value and multiply the result with 10.
Rule 5: If letter is between U and Z, we find the largest factor of the numerical value < lvalue and multiply the result with 12.
We will write a separate function for each of the 5 rules.
Wrap around the alphabet
If the resulting number is greater than 26, then wrap around the alphabet. That is, we will subtract 26 from the number repeatedly until the number is less than 26.
As a boundary condition, if the value of the number is 0, return 26 (representing Z).
we will write a Python function to accept the updated number, and return the whittled number.
My Python solution #1
I have two Python programs for this.
This is my first Python solution:
'''
ACSL Intermediate 2001-2002 Contest 1 WRAP AROUND CODE
Blog Post: https://aruljohn.com/blog/acsl-intermediate-wrap-around-code/
'''
# Rule 1
def rule1(letter, current_letter):
lvalue = ord(letter) - 64
cvalue = ord(current_letter) - 64
lvalue *= 2
lvalue = wrap_around(cvalue + lvalue)
new_letter = chr(lvalue + 64)
return new_letter
# Rule 2
def rule2(letter, current_letter):
lvalue = ord(letter) - 64
cvalue = ord(current_letter) - 64
lvalue = (lvalue % 3) * 5
lvalue = wrap_around(cvalue + lvalue)
new_letter = chr(lvalue + 64)
return new_letter
# Rule 3
def rule3(letter, current_letter):
lvalue = ord(letter) - 64
cvalue = ord(current_letter) - 64
lvalue = lvalue // 4 * 8
lvalue = wrap_around(cvalue + lvalue)
new_letter = chr(lvalue + 64)
return new_letter
# Rule 4
def rule4(letter, current_letter):
lvalue = ord(letter) - 64
cvalue = ord(current_letter) - 64
lvalue = sum([int(x) for x in list(str(lvalue))]) * 10
lvalue = wrap_around(cvalue + lvalue)
new_letter = chr(lvalue + 64)
return new_letter
# Rule 5
def rule5(letter, current_letter):
lvalue = ord(letter) - 64
cvalue = ord(current_letter) - 64
largest_factor = 1
i = lvalue
while i > 1:
i -= 1
if lvalue % i == 0:
largest_factor = i
break
lvalue = largest_factor * 12 % 26
lvalue = wrap_around(cvalue + lvalue)
new_letter = chr(lvalue + 64)
return new_letter
# Wrap around
def wrap_around(n):
while n >= 26:
n -= 26
if n == 0:
return 26
return n
# Function to return encoded letters
def encoded_letters(line):
lines = line.split(',')
lines.remove('$')
eletters = []
current_letter = 'A'
for letter in lines:
if 'A' <= letter <= 'E':
current_letter = rule1(letter, current_letter)
elif 'F' <= letter <= 'J':
current_letter = rule2(letter, current_letter)
elif 'K' <= letter <= 'O':
current_letter = rule3(letter, current_letter)
elif 'P' <= letter <= 'T':
current_letter = rule4(letter, current_letter)
elif 'U' <= letter <= 'Z':
current_letter = rule5(letter, current_letter)
eletters.append(current_letter)
eletters = ' '.join(eletters)
return eletters
# Main function
if __name__ == '__main__':
input_data = '''
B,G,Z,$
A,R,J,$
A,C,S,L,$
A,B,C,$
L,U,C,K,$
A,E,I,O,U,$
C,O,N,T,E,S,T,$
M,O,N,T,R,E,A,L,$
'''
output_data = '''
E J J
C O T
C I E C
C G M
Y E K A
C M M K Q
G E C W G C W
Y W U O A K M K
'''
sample_input = input_data.strip().split('\n')
expected_output = output_data.strip().split('\n')
for i, line in enumerate(sample_input):
expected = expected_output[i]
actual = encoded_letters(line)
print(f'Test case {i}: {expected == actual}')
if expected != actual:
print('>> What you got :', actual)
print('>> What is expected :', expected)
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 list.
A second string output_data contains the expected output, one test case output per line.
The function encoded_letters(line) is called, and passes the string of comma-separated letters as parameter.
We write separate functions for each rule. In each of these rule functions, we find the ASCII number of that letter, subtract 64 from it, then find the new value and return the updated ASCII letter.
The function wrap_around(n) accepts a number n which may be greater than 26 and returns the wrapped around value. This is done by subtracting the highest multiple of 26 that is lower than n.
Review of first rule function
The encoded_letters() function calls the rule1() function and passes in the current letter from the input line and the current letter from where the counting starts for the next round. The initial value of the current_letter variable is A.
In the first function rule1(), we accept the input letter and current_letter.
We find the ascii values of both letters, lvalue and cvalue, perform operations to get the updated value of lvalue. In this case, we multiply the letter value by 2.
Next, we wrap around the value for the sum of lvalue and cvalue, store the result in lvalue. We then find the new letter by finding the character value of the updated value of lvalue.
The remaining four rule functions work the same way with the difference being the processing rules.
Useful Python code snippets
There are many code snippets that can be used in competitive programming contests. These are a few. We will use the Python shell to run these individual snippets.
If value is between two values
We use this code to check if letter is between A and E.
if 'A' <= letter <= 'E':
Finding ASCII numeric value of A using ord('A')
To find the ASCII number associated with any character or letter, we use the ord() function and pass in the letter as parameter.
To do the opposite, that is find the ASCII character corresponding to a number, we use the chr() function and pass in the number as parameter.
Find the sum of all digits in a number
Using list comprehension, we find the sum of all digits by (1) converting the number to a string, (2) then breaking it up into a list of ints and (3) applying the sum() function around the resulting list.
Use the Python shell
If you are not sure about the usage of chr() or ord(), just run help in the Python shell.
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 intermediate_wrap_around_code.py Test case 0: True Test case 1: True Test case 2: True Test case 3: True Test case 4: True Test case 5: True Test case 6: True Test case 7: True
My Python solution #2, more concise, works for all test cases
This is my second Python program for this problem. It is a more concise version and is preferred for competitive programming, but may be harder to handle if more constraints are introduced.
- I got rid of the 5 Python "rule" functions
- Most of the logic is in one function
encoded_letters() - No
chr()or ASCII related functions - This works with minimal amount of code
- This works with 100% of test cases
'''
ACSL Intermediate 2001-2002 Contest 1 WRAP AROUND CODE
Blog Post: https://aruljohn.com/blog/acsl-intermediate-wrap-around-code/
'''
# Wrap around
def wrap_around(n):
while n >= 26:
n -= 26
if n == 0:
return 26
return n
# Function to return encoded letters
def encoded_letters(line):
alphabet = '0ABCDEFGHIJKLMNOPQRSTUVWXYZ'
lines = line.split(',')
lines.remove('$')
eletters = []
current_letter = 'A'
cvalue = alphabet.index(current_letter)
for letter in lines:
lvalue = alphabet.index(letter)
if 1 <= lvalue <= 5:
lvalue *= 2
elif 6 <= lvalue <= 10:
lvalue = (lvalue % 3) * 5
elif 11 <= lvalue <= 15:
lvalue = lvalue // 4 * 8
elif 16 <= lvalue <= 20:
lvalue = sum([int(x) for x in list(str(lvalue))]) * 10
elif 21 <= lvalue <= 26:
largest_factor = 1
i = lvalue
while i > 1:
i -= 1
if lvalue % i == 0:
largest_factor = i
break
lvalue = largest_factor * 12 % 26
# Wrap around and append letter to eletters[]
lvalue = wrap_around(cvalue + lvalue)
cvalue = lvalue
eletters.append(alphabet[lvalue])
eletters = ' '.join(eletters)
return eletters
# Main function
if __name__ == '__main__':
input_data = '''
B,G,Z,$
A,R,J,$
A,C,S,L,$
A,B,C,$
L,U,C,K,$
A,E,I,O,U,$
C,O,N,T,E,S,T,$
M,O,N,T,R,E,A,L,$
'''
output_data = '''
E J J
C O T
C I E C
C G M
Y E K A
C M M K Q
G E C W G C W
Y W U O A K M K
'''
sample_input = input_data.strip().split('\n')
expected_output = output_data.strip().split('\n')
for i, line in enumerate(sample_input):
expected = expected_output[i]
actual = encoded_letters(line)
print(f'Test case {i}: {expected == actual}')
if expected != actual:
print('>> What you got :', actual)
print('>> What is expected :', expected)
Output:
$ python intermediate_wrap_around_code.py Test case 0: True Test case 1: True Test case 2: True Test case 3: True Test case 4: True Test case 5: True Test case 6: True Test case 7: 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.