Created
May 5, 2015 12:57
-
-
Save tom-galvin/e8503e28bafcb67c6535 to your computer and use it in GitHub Desktop.
DailyProgrammer Challenge #213i Solution (The Lazy Typist)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Keyboard | |
def initialize(rows) | |
@keys, @spaces, @shifts = {}, [], [] | |
rows.each.with_index do |row, j| | |
row.each_char.with_index do |c, i| | |
unless c == '.' | |
@keys[c] = [] unless @keys[c] | |
@keys[c] << [i, j] | |
end | |
end | |
end | |
end | |
def closest(key, px, py) | |
@keys[key].sort_by {|(sx, sy)| (sx - px).abs + (sy - py).abs }.first | |
end | |
end | |
class Hand | |
attr_reader :effort, :keyboard, :name, :key | |
def initialize(keyboard, name, key) | |
@keyboard, @name = keyboard, name | |
@effort = 0 | |
@key, @px, @py = key, *@keyboard.closest(key, 0, 0) | |
end | |
def effort_for(key) | |
kx, ky = @keyboard.closest(key, @px, @py) | |
(kx - @px).abs + (ky - @py).abs | |
end | |
def move_to(key) | |
kx, ky = @keyboard.closest(key, @px, @py) | |
de = (kx - @px).abs + (ky - @py).abs | |
@effort += de | |
@px, @py = kx, ky | |
@key = key | |
de | |
end | |
end | |
$kb = Keyboard.new(['qwertyuiop', 'asdfghjkl', '^zxcvbnm.^', '... ']) | |
input = gets.chomp | |
hands, $available_hands = [], ['left', 'right'] | |
def key_to_s(key) | |
{' ' => 'Space', '^' => 'Shift'}[key] || key.upcase | |
end | |
def move_to(hands, key, but_not=nil) | |
if $available_hands.empty? | |
possible_hands = but_not ? hands.reject {|hand| hand == but_not } : hands | |
possible_hands = hands if possible_hands.empty? | |
best_hand = possible_hands.min_by {|hand| hand.effort_for(key.downcase) } | |
if best_hand.key == key.downcase | |
puts "#{key_to_s(key)}: Use #{best_hand.name} hand again" | |
else | |
msg = "#{key_to_s(key)}: Move #{best_hand.name} hand from #{key_to_s(best_hand.key)}" | |
de = best_hand.move_to(key.downcase) | |
msg += " (effort: #{de})" | |
puts msg | |
best_hand | |
end | |
else | |
name = $available_hands.shift | |
puts "#{key_to_s(key)}: Use #{name} hand" | |
hands << Hand.new($kb, name, key.downcase) | |
end | |
end | |
input.each_char do |char| | |
(puts "Invalid character in input."; exit) unless char =~ /[A-Za-z ]/ | |
end | |
while c = input.slice!(0) | |
if c =~ /[A-Z]/ | |
used_hand = move_to(hands, '^') | |
else | |
used_hand = nil | |
end | |
used_hand = move_to(hands, c, used_hand) | |
end | |
puts "Total effort: #{hands.map {|hand| hand.effort }.reduce(0, :+)}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment