Weekly Challenge 281
Sorry for being MIA over the last few weeks. I've moved house and a new job, so haven't had a chance to partake in the challenges over this time.
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. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.
Task 1: Check Color
Task
You are given coordinates, a string that represents the coordinates of a square of the chessboard as shown below:
Write a script to return true
if the square is light, and false
if the square is dark.
My solution
This is relatively straight forward. The first thing I do is check that the provided position is valid (first character is a
h
and the second character is between 1 and 8).
I then check if the first letter is a
, c
, e
or g
and the number is even, or the first letter is b
, d
, f
or h
and the number is odd, return true
. Otherwise return false
.
def check_color(coords: str) > bool:
if not re.search('^[ah][18]$', coords):
raise ValueError('Not a valid chess coordinate!')
if coords[0] in ('a', 'c', 'e', 'g') and int(coords[1]) % 2 == 0:
return True
if coords[0] in ('b', 'd', 'f', 'h') and int(coords[1]) % 2 == 1:
return True
return False
Examples
$ ./ch1.py d3
true
$ ./ch1.py g5
false
$ ./ch1.py e6
true
Task 2: Knight’s Move
Task
A Knight in chess can move from its current position to any square two rows or columns plus one column or row away. So in the diagram below, if it starts a S, it can move to any of the squares marked E.
Write a script which takes a starting position and an ending position and calculates the least number of moves required.
My solution
This one is more detailed. I start with the follow variables:

deltas
is a tuples of lists (array of arrays in Perl) with the eight ways the knight can move from its current position. 
target
is the cell that we want to reach. For this I convert the first letter to a number from one to 8. It's stored as a tuple, the first value is the column and the second value is the row. 
moves
is the number of moves made and starts at one. 
seen
is a list of cells we have already visited. 
coords
is a list of current positions of a knight. It starts with the starting coordinate.
def knights_move(start_coord: str, end_coord: str) > int:
for coord in (start_coord, end_coord):
if not re.search('^[ah][18]$', coord):
raise ValueError(
f'The position {coord} is not a valid chess coordinate!')
deltas = ([2, 1], [2, 1], [2, 1], [2, 1],
[1, 2], [1, 2], [1, 2], [1, 2])
coords = [convert_coord_to_list(start_coord)]
target = convert_coord_to_list(end_coord)
moves = 1
seen = []
I then have a double loop of the current coords
list and the deltas
list. A set a variable new_pos
that represents the new coordinates for the knight. If this leads to a position outside the board or a coordinate we've already been to, I skip it. If it lands on the target, I return the moves
value.
After the loop, I reset the coords
list to the coordinates collected through the iterations, and increment the moves
value by one. This continues until we hit the target coordinate.
while True:
new_coords = []
for coord in coords:
for delta in deltas:
new_pos = (coord[0] + delta[0], coord[1] + delta[1])
if not 0 < new_pos[0] < 9 or not 0 < new_pos[1] < 9 or new_pos in seen:
continue
if new_pos == target:
return moves
new_coords.append(new_pos)
seen.append(new_pos)
coords = new_coords
moves += 1
Examples
$ ./ch2.py g2 a8
4
$ ./ch2.py g2 h2
3
Top comments (0)