patternrubyMinor
Breaking a chess coordinate string into 2D coordinates
Viewed 0 times
coordinatesintocoordinatebreakingchessstring
Problem
Given a chess coordinate as a string (e.g. "a1") I'd like to transform it into a 2-D array (so, for "a1" I'd like to get [1,1]).
Here's what I came up with:
Can anyone suggest a refactoring please to make it more idiomatic Ruby?
Here's what I came up with:
def safe_pawns(pawns)
pawns.inject([]){|res, pwn| res << [pwn.split('')[0].index(/[a-h]/) + 1, pwn.split('')[1].to_i]}
endCan anyone suggest a refactoring please to make it more idiomatic Ruby?
Solution
-
Give your code some breathing room. I.e.
-
That being said, strings support array-like access, so you don't need the
-
Judging from your code,
-
I'd probably use a regex to pull the string apart. It'll double as a way to check the coordinate strings for validity (e.g. so no "z9" coordinates will slip through).
-
It's a little low-level, but we can use the fact that "a" is 97 in ASCII. So to get the number for a letter, we can say
You get something like this:
Alternatively, if you're sure that all the input coordinates are valid, lowercase strings already, you don't need the regex or the downcasing:
As tokland points out in the comments, we can avoid the hardcoded
Give your code some breathing room. I.e.
) { |a, b| instead of ){|a, b|. And there's no need to put everything on one line. The way your block works right now, it'd be better to store the result of pwn.split in a variable, instead of calling split twice. (There's also no need to abbrevate "pawn" as "pwn".)-
That being said, strings support array-like access, so you don't need the
split at all.-
Judging from your code,
pawns is an array. Transforming an n-element array to a new n-element array is called "mapping". You're using inject which is also known as reduce (and fold in many other languages; see comments) - an operation most often used to take an n-element array and reduce it to a single value. So step 1: Use map instead of inject.-
I'd probably use a regex to pull the string apart. It'll double as a way to check the coordinate strings for validity (e.g. so no "z9" coordinates will slip through).
-
It's a little low-level, but we can use the fact that "a" is 97 in ASCII. So to get the number for a letter, we can say
letter.ord - 96. You get something like this:
def safe_pawns(squares)
squares.map do |square|
[$1.ord - 96, $2.to_i] if square.downcase =~ /^([a-h])([1-8])$/
end.compact
endAlternatively, if you're sure that all the input coordinates are valid, lowercase strings already, you don't need the regex or the downcasing:
def safe_pawns(squares)
squares.map { |square| [square[0].ord - 96, square[1].to_i] }
endAs tokland points out in the comments, we can avoid the hardcoded
96 (which isn't very self-explanatory) and instead get the letter-to-number translation by saying:square[0].ord - 'a'.ord + 1Code Snippets
def safe_pawns(squares)
squares.map do |square|
[$1.ord - 96, $2.to_i] if square.downcase =~ /^([a-h])([1-8])$/
end.compact
enddef safe_pawns(squares)
squares.map { |square| [square[0].ord - 96, square[1].to_i] }
endsquare[0].ord - 'a'.ord + 1Context
StackExchange Code Review Q#62616, answer score: 9
Revisions (0)
No revisions yet.