1 2 3 4 5 6 7
keys = { "a" => %w(q w s z), "b" => %w(v n g h), "c" => %w(x d f v) ... } p keys["b"]
Refactorings
No refactoring yet !
Joran Jessurun
October 23, 2007, October 23, 2007 14:28, permalink
This is my attempt. Not really ruby like but more a general solution.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
@keyboard_layout = [ "1234567890-=", "qwertyuiop[]", "asdfghjkl;'", "zxcvbnm,./", ] def key_coordinates(key) @keyboard_layout.each_with_index do |line, i| return [line.index(key), i] if line.include?(key) end [nil, nil] end def get_key(x, y) return nil if y < 0 || y >= @keyboard_layout.size line = @keyboard_layout[y] return nil if x < 0 || x > line.size line[x..x] end def keys_around(key) x, y = key_coordinates(key) if x && y [ get_key(x - 1, y), get_key(x - 1, y + 1), get_key(x, y - 1), get_key(x, y + 1), get_key(x + 1, y - 1), get_key(x + 1, y) ].compact end end p keys_around('b')
Scott Patten
October 23, 2007, October 23, 2007 17:14, permalink
Here it is. That would make a good Ruby Quiz. You should submit it.
You may disagree with my definition of neighbours, I didn't include punctuation as neighbours, and this will only work on a North American keyboard as is, but it seems to work.
To use it, require this file, and then call something like
Keyboard.neighbours('f')
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
#!/usr/bin/env ruby class Keyboard QWERTY = [ "qwertyuiop".split(''), "asdfghjkl".split(''), "zxcvbnm".split('')] def initialize(char) @char = char end def neighbours (row_neighbours + row_above_neighbours + row_below_neighbours).sort.join end def Keyboard.neighbours(char) Keyboard.new(char).neighbours end private def row QWERTY.detect {|row| row.include?(@char)} end def row_above QWERTY[row_num - 1] if row_num() -1 >= 0 end def row_below QWERTY[row_num + 1] if row_num() + 1 < QWERTY.length end def row_num QWERTY.index(row) end def in_row_index row.index(@char) end def select_from_row(row_string, indices) return [] unless row_string indices.collect {|n| row_string[n .. n] if n >= 0 and n < row_string.length}.compact.sort end def row_neighbours select_from_row(row, [in_row_index() - 1, in_row_index() + 1]) end def row_above_neighbours select_from_row(row_above, [in_row_index() , in_row_index() + 1 ]) end def row_below_neighbours select_from_row(row_below, [in_row_index() -1, in_row_index() ]) end end require 'test/unit' class KeyboardNeighboursTest < Test::Unit::TestCase def test_neighbours expected_neighbours = {'q'=> 'aw', 't' => 'fgry', 'i' => 'jkou', 'p' => 'lo', 'a' => 'qswz', 'f' => 'cdgrtv', 'j' => 'hikmnu', 'l' => 'kop', 'z' => 'asx', 'v' => 'bcfg', 'n' => 'bhjm', 'm' => 'jkn'} expected_neighbours.each do |key, neighbours| assert_equal neighbours, Keyboard.neighbours(key) end end end
Marco Valtas
October 24, 2007, October 24, 2007 02:45, permalink
Hi, I don't how to write a Ruby solution but you can have some idea looking at this Perl module.
http://search.cpan.org/~krburton/String-KeyboardDistance-1.01/KeyboardDistance.pm
This is not really a refactoring as much as a request of solution for my problem.
The problem is: I'd like some ruby-ish way of returning an array of keys-next-to-character. For instance: passing "b" would return v,n,h,g (the keys next to b on a keyboard)
The solution i have on my mind needs to create some kind of big hash with all the keys, but there must a better way?