2

I would like to convert a few Python lines on Ruby, from this excellent article signed by Thomas Guest at: http://wordaligned.org/articles/drawing-chess-positions

(note: I'm a really bigger Python noob)

Here is a copy of the original Python version:

def expand_blanks(fen):
    '''Expand the digits in an FEN string into spaces

    >>> expand_blanks("rk4q3")
    'rk    q   '
    '''
    def expand(match):
        return ' ' * int(match.group(0))
    return re.compile(r'\d').sub(expand, fen)

def outer_join(sep, ss):
    '''Like string.join, but encloses the result with outer separators.

    Example:
    >>> outer_join('|', ['1', '2', '3'])
    '|1|2|3|'
    '''
    return '%s%s%s' % (sep, sep.join(ss), sep)

def ascii_draw_chess_position(fen):
    '''Returns an ASCII picture of pieces on a chessboard.'''
    pieces = expand_blanks(fen).replace('/', '')
    divider = '+-+-+-+-+-+-+-+-+\n'
    rows = ((outer_join('|', pieces[r: r + 8]) + '\n')
            for r in range(0, 8 * 8, 8))
    return outer_join(divider, rows)

Usage example:

>>> fen = "r2q1rk1/pp2ppbp/1np2np1/2Q3B1/3PP1b1/2N2N2/PP3PPP/3RKB1R"
>>> print ascii_draw_chess_position(fen)
+-+-+-+-+-+-+-+-+
|r| | |q| |r|k| |
+-+-+-+-+-+-+-+-+
|p|p| | |p|p|b|p|
+-+-+-+-+-+-+-+-+
| |n|p| | |n|p| |
+-+-+-+-+-+-+-+-+
| | |Q| | | |B| |
+-+-+-+-+-+-+-+-+
| | | |P|P| |b| |
+-+-+-+-+-+-+-+-+
| | |N| | |N| | |
+-+-+-+-+-+-+-+-+
|P|P| | | |P|P|P|
+-+-+-+-+-+-+-+-+
| | | |R|K|B| |R|
+-+-+-+-+-+-+-+-+

I have trying to do some modifications to convert each line in Ruby... And I wonder if it's bad start :s But I publish it anyway:

def expand_blanks(fen)
  def expand(match)
    return ' ' * int(match.group(0))
  end

  # bugged:
  re.compile(r'\d').sub(expand, fen)
end

def outer_join(sep, ss)
  sep + sep.join(ss) + sep
end

def ascii_draw_chess_position(fen)
  pieces = expand_blanks(fen).replace('/', '')
  puts pieces.class
  divider = "+-+-+-+-+-+-+-+-+\n"

  # bugged lines:
  rows = ((outer_join('|', pieces[r, r + 8]) + '\n')
  for r in range(0, 8 * 8, 8))
    return outer_join(divider, rows)
  end
end

fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR"
puts ascii_draw_chess_position(fen)

If you see some lines that I can fix, I would be cool for me. Thank you all.

2 Answers 2

2

Looking at each method in turn, starting with outer_join.

In Python, join is a method on strings that takes a sequence and joins the elements delimited by the string. e.g. '|'.join(['p, 'p', 'p'])

In Ruby, join is a method on arrays that takes the delimiter as an argument e.g. ['p', 'p', 'p'].join('|')

so the Ruby version of outer_join would be:

def outer_join(sep, ss):
  sep + ss.join(sep) + sep
end

Next look at expand_blanks, the intention here is to replace a digit with the equivalent number of spaces. In Ruby this can be achieved using gsub to replace all occurrences of a pattern in a string. gsub can be called with a block that will be passed each match substring and returns the string that the match should be replaced with. So the Ruby code would be:

def expand_blanks(fen)
  fen.gsub(/\d/) { |match| ' ' * match.to_i }
end

Finally in ascii_draw_chess_position we can use gsub again as an equivalent to Python's replace method and use Ruby's map function in place of what was achieved using a list comprehension in Python as follows:

def ascii_draw_chess_position(fen)
  pieces = expand_blanks(fen).gsub('/', '')
  divider = "+-+-+-+-+-+-+-+-+\n"
  rows = (0...8).map do |i|
    row = pieces[i * 8...(i + 1) * 8].split('')
    outer_join("|",row) + "\n"
  end
  puts outer_join(divider, rows)
end

Let me know if you need any more details on the above.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you a lot Mikej, and Grifaton. Now I got every piece of what I search to do. Thanks again! Regards.
1

This will do what you want:

def expand(match)
  ' ' * match.to_i
end

def expand_blanks(fen)
  fen.gsub(/\d/) {|d| expand d}
end

def outer_join(sep, ss)
  sep + ss.join(sep) + sep
end

def ascii_draw_chess_position(fen)
  pieces = expand_blanks(fen).gsub('/', '')
  divider = "+-+-+-+-+-+-+-+-+\n"
  rows = (0...8).collect do |i|
    row = pieces[i*8...(i+1)*8].split('')
    outer_join("|",row) + "\n"
  end
  puts outer_join(divider, rows)
end

Let me know if there's any code here you don't understand - but make sure you've looked up the methods in the ruby docs

If you're interested in the differences between ruby and python, see here https://stackoverflow.com/questions/234721/what-are-the-biggest-differences-between-python-and-ruby-from-a-philosophical-per or http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/, and for some good examples, see http://ruby.brian-amberg.de/editierdistanz/.

1 Comment

Many Thanks, Grifaton! I will study and see the differences.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.