# Finding the number of moves a knight can perform while standing on a given square

This is a problem from CodeSignal which can be founded over here

Here is an image on what we have to do: ## Code

def map(cell):
new_cell1 = ''

for i in cell:
if i == 'a':
new_cell1 += '1'
if i == 'b':
new_cell1 += '2'
if i == 'c':
new_cell1 += '3'
if i == 'd':
new_cell1 += '4'
if i == 'e':
new_cell1 += '5'
if i == 'f':
new_cell1 += '6'
if i == 'g':
new_cell1 += '7'
if i == 'h':
new_cell1 += '8'

new_cell1 += cell[-1]
return new_cell1

def chessKnight(cell):
cell = map(cell)
num_of_moves = 0

if (int(cell)+1 <= 8 and int(cell)+1 > 0) and (int(cell)+2 <= 8 and int(cell)+2 > 0):
num_of_moves += 1

if (int(cell)-1 <= 8 and int(cell)-1 > 0) and (int(cell)+2 <= 8 and int(cell)+2 > 0):
num_of_moves += 1

if (int(cell)+1 <= 8 and int(cell)+1 > 0) and (int(cell)-2 <= 8 and int(cell)-2 > 0):
num_of_moves += 1

if (int(cell)-1 <= 8 and int(cell)-1 > 0) and (int(cell)-2 <= 8 and int(cell)-2 > 0):
num_of_moves += 1

if (int(cell)+2 <= 8 and int(cell)+2 > 0) and (int(cell)+1 <= 8 and int(cell)+1 > 0):
num_of_moves += 1

if (int(cell)-2 <= 8 and int(cell)-2 > 0) and (int(cell)+1 <= 8 and int(cell)+1 > 0):
num_of_moves += 1

if (int(cell)+2 <= 8 and int(cell)+2 > 0) and (int(cell)-1 <= 8 and int(cell)-1 > 0):
num_of_moves += 1

if (int(cell)-2 <= 8 and int(cell)-2 > 0) and (int(cell)-1 <= 8 and int(cell)-1 > 0):
num_of_moves += 1

return num_of_moves



## Question

The Code works as expected and returns the right answer, but I have just put a bunch of if conditions which doesn't look nice to me. Is there any way to implement the problem but without so much if blocks?

• Please note that when you link a question from code signal, the question is locked for all of those who haven't solved the first problems, due to which the higher-level questions are locked – Parekh Oct 25 '20 at 19:10

# Never use existing function names for new functions

Python already has a function called map()
Defining your new map() function can cause a lot of confusion, and undefined behaviour in your program.

# By cheating

Since you have asked for an alternate solution, here it is

Being a chess engine developer, I would never calculate something trivial like the number of knight attacks since a simple array of size 64 with the pre-calculated ones can easily work. All you need is a simple function that converts a square like a1 to 0 and h8 to 63.

Here is the implementation,

def str_sq_to_int(sq):
return (ord(sq)-97) + ((ord(sq)-49) * 8);

def knightAttacks(cell):
attacks = [
2, 3, 4, 4, 4, 4, 3, 2,
3, 4, 6, 6, 6, 6, 4, 3,
4, 6, 8, 8, 8, 8, 6, 4,
4, 6, 8, 8, 8, 8, 6, 4,
4, 6, 8, 8, 8, 8, 6, 4,
4, 6, 8, 8, 8, 8, 6, 4,
3, 4, 6, 6, 6, 6, 4, 3,
2, 3, 4, 4, 4, 4, 3, 2
]
return attacks[str_sq_int(cell)]


The explanation is simple, the function str_sq_to_int() takes a square like 'a1' and returns an index using the ASCII value of the character to calculate the index. You can also use a simple dictionary to map each square to an index, but this one is easy

Then, it uses a pre-calculated set of values, to return the correct answer.

• Lol. This answer is very cool, – fartgeek Oct 25 '20 at 20:32
• @fartgeek yeah 😁, I kind of copy pasted the str_to_int function from my chess engine though xD. I would recommend bit manipulation but since it's python, doesn't make sense – Parekh Oct 25 '20 at 20:49
• To improve this answer, I would suggest making str_sq_to_int, ord and sq more explicit and making the casing consistent. Also the magic numbers (97, 49, 8) could use some names. – Raimund Krämer Oct 26 '20 at 9:20
• @RaimundKrämer Is that why you downvoted? It is good advice, I will remove the magic numbers but I'm not sure what name I could get for them since they are based on the ascii values – Parekh Oct 26 '20 at 11:12
• @RaimundKrämer I'm a little unsure as to what you expect more in this answer, may i suggest you edit it yourself? I would like to see what I missed that deserved a downvote – Parekh Oct 26 '20 at 11:18

Alright. This is an interesting question. If you think about it, the moves of a knight have a few conditions (excluding checks and whether a friendly piece is on the destination square):

• The move has to be on the board (this is one is obvious)

• The absolute value of the distance moved to the side subtracted from the absolute value of the distanced moved up must either equal one or -1.

• The absolute value of the distance moved to the side must be one or two.

• The absolute value of the distance moved up or down must be either one or two.

The code is as follows :

def knight_move_counter(position_on_board):
possibleMoves = 0
# here we could use ASCII values to convert the letters to numbers, but a dict is easier to visualize
letterToNumbers = {
"a" : 0,
"b" : 1,
"c" : 2,
"d" : 3,
"e" : 4,
"f" : 5,
"g" : 6,
"h" : 7
}
start_letter = letterToNumbers[position_on_board]
start_number = int(position_on_board) - 1 # note that this line and the preceding one will only work if they are valid algebraic notation.
for iterator in range(8):
for second_iterator in range(8): # these two for loops assure our answers will be on the board.
if abs( abs(start_letter - iterator) - abs(start_number - second_iterator)) == 1: # point #2
if abs(start_letter - iterator) == 1 or abs(start_letter - iterator) == 2: # point #3
if abs(start_number - second_iterator) == 1 or abs(start_number - second_iterator) == 2: # point #4
possibleMoves += 1
return possibleMoves

print(knight_move_counter("a1")) # you can replace the "a1" with whatever you would like, as long as it is valid algebraic notation.

• this article on knight patterns is really cool – Parekh Oct 26 '20 at 5:44