The previous Python coding challenges for beginners seem to be wellreceived so I decided to create another post for intermediate coding challenges. Have fun solving & don't hesistate to share your feedback or solutions in the comment section :)
1. Caesar Cipher
Background:
Caesar's cipher is a simple encryption technique, in which the plaintext character is replaced by a letter some fixed number of positions down the alphabet.
For example, with a right shift of 3, A would be replaced by D, B would become E, and so on.
Task:
Write a Python program to decode the following secret message: N qtaj uwtlwfrrnsl zxnsl Udymts
, given that the key is 5.
Starter code:
ciphertext = "N qtaj uwtlwfrrnsl zxnsl Udymts"
def decrypt(ciphertext, key):
# complete code here
decrypt(ciphertext, 5)
Sample solution:
def decrypt(ciphertext, key):
letters = "abcdefghijklmnopqrstuvwxyz"
letters_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
message = ""
for char in ciphertext:
if char in letters:
position = letters.find(char)
new_pos = (position  key) % 26
new_char = letters[new_pos]
message += new_char
elif char in letters_upper:
position = letters_upper.find(char)
new_pos = (position  key) % 26
new_char = letters_upper[new_pos]
message += new_char
else:
message += char
return message
print(decrypt(cipher, 5))
2. Simple Mastermind Game
Task:
Write a program that randomly generates a 4 digit number. The user has maximum 10 tries to guess the number.
If any of the digit guessed is wrong, print "A" to indicate wrong guess.
If the digit is guessed correctly but in the wrong position, print "B".
If the digit guessed is both the correct value and position, print "C".
Starter code:
import random
def generate_number():
# complete code here
def input_guess():
guess = input("Enter your guess: ")
return guess
def start_game():
# complete code here
start_game()
Sample solution:
import random
def generate_number():
num = random.randint(1000,9999)
num = [int(x) for x in str(num)]
return num
def input_guess():
guess = input("Enter your guess: ")
return guess
def start_game():
tries = 0
number = generate_number()
while tries < 10:
result = ""
guess = [int(i) for i in input_guess()]
if len(guess) != 4:
print("Enter only 4 digit number")
continue
if guess == number:
print("You won with ", tries, " attempts.")
break
for element in guess:
if element in number:
if guess.index(element) == number.index(element):
result+="C"
else:
result+="B"
else:
result+="A"
print(result)
tries += 1
else:
print("You ran out of attempts. The answer is: " , "".join(map(str, number)))
start_game()
3. Roman Numerals & Integer Converter
Background:
The Roman numeral system consists of the following symbols:
Symbol  Value 

I  1 
V  5 
X  10 
L  50 
C  100 
D  500 
M  1000 
Numbers are constructed by combining these symbols. For instance, the number 12
can be represented by XII
, since X + I + I = 10 + 1 + 1
.
The following list is set of rules for Roman numerals:
Zero is not represented.
A symbol can be repeated only for three times.
Roman numerals are repeated to add value:
III
is equivalent to 1 +1 +1 = 3. However, only powers of 10 may be repeated in this way. Thus,VV
is invalid; 5 + 5 would instead be expressed asX
.When a Roman numeral is placed after another Roman numeral of greater value, the result is the sum of the numerals. When a Roman numeral is placed before another Roman numeral of greater value, the result is the difference between the numerals.

Only
I
,X
, andC
can be used as subtractive numerals as shown:
I
can be used beforeV(5)
andX(10)
to make itIV(4)
andXV(9)
respectively. 
X
cab be used beforeL(50)
andC(100)
to make itXL(40)
andXC(90)
respectively 
C
can be used beforeD(500)
andM(1000)
to make themCD(400)
andCM(900)
respectively.

Task:
Write a program that allows users to either convert integers to roman numerals, or convert roman numerals to integers.
Starter code:
def roman_to_int(roman):
# complete code here
def int_to_roman(int):
# complete code here
print("  Roman Numberals Conversion ")
print(" > 1  Convert an integer to a roman numerals,")
print(" > 2  Convert a roman numerals to an integer.")
option = input("Choose an option (1 or 2):")
# complete code here
Sample solution:
def roman_to_int(s):
roman_values = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000}
result = 0
for i in range(len(s)):
if i + 1 < len(s) and roman_values[s[i]] < roman_values[s[i + 1]]:
result = roman_values[s[i]]
else:
result += roman_values[s[i]]
return result
def int_to_roman(x):
roman_map = { 1: 'I', 4: 'IV', 5: 'V', 9: 'IX', 10: 'X', 40: 'XL', 50: 'L', 90: 'XC', 100: 'C', 400: 'XD', 500: 'D', 900: 'CM', 1000: 'M'}
integers = list(roman_map)
symbols = list(roman_map.values())
i = 12
result = ""
while x != 0:
if integers[i] <= x:
result += symbols[i]
x = integers[i]
else:
i = 1
return result
print("  Roman Numberals Conversion ")
print(" > 1  Convert an integer to a roman numerals,")
print(" > 2  Convert a roman numerals to an integer.")
option = input("Choose an option (1 or 2):")
if option == "1":
num = int(input("Enter an integer: "))
print(int_to_roman(num))
elif option == "2":
roman = input("Enter a Roman numeral: ")
print(roman_to_int(roman))
else:
print("Invalid input.")
Top comments (4)
Hello, I think your mastermind game code has a mistake. For exaple when the number is 9950 and the guess is 9955, it prints out "CCCC" even tho the guess is not correct.
The problem is in the for cycle when comparing indexes. I tried to rewrite the code so it works better. Here is the part of my code:
What do you think about it?
Yes, you are right. In my original code, the index() method returns the index of the first occurrence of the element in the list, resulting in only comparing the initial index of the elements rather than the actual index. Your code works correctly, I will also include an alternate method below:
Thank you for your comment!
Cypher breaks the first covenant: DRY.
A better, shorter and more functional solution is here:
It's just a case of determining the character code of each character, adjusting for SPC, case and alphabetical wrap around and subtracting the key.
Thank you for the insight! I wrote this in the beginning of my coding journey and reflecting now, I must say that it is not the optimal solution. Your code is more succint and effiecient. By using the ord() approach, it eliminates the need of predefining the letter strings. It also handles wraparound cases more elegantly, as it directly calculates the new ASCII value based on the shift.