横浜へなちょこプログラミング勉強会にて過去に出題されたとある世界のタクシー料金を解いてみた。
回答にかかった時間は40分程度。
[from,to].sort.join.to_sym
が非常に気に食わないが、sort
しなくてもよいようにROUTE
に逆順も持つのはおかしな話なので妥協した。
class Taxi
FIRSTRIDE = [[995, 400], [845, 350]]
ROUTE = {
AB: [1090, 0], AC: [180, 0], AD: [540, 1], BC: [960, 0], BG: [1270, 0],
CD: [400, 1], CF: [200, 0], DE: [720, 1], DF: [510, 1], EG: [1050, 1],
FG: [230, 1]
}
ADD_FARE = [60, 50]
def drive input
input.each_char.each_cons(2).inject(FIRSTRIDE[[?A, ?B, ?C].include?(input[0]) ? 0 : 1]){|(left, fare), (from, to)|
range, meter_type = ROUTE[[from,to].sort.join.to_sym]
c = range <= left ? 0 : ((range - left) / 200.0).ceil
[(left + 200 * c) - range, fare + ADD_FARE[meter_type] * c]
}[1]
end
end
test = <<_TEST
/*0*/ test( "ADFC", "510" );
/*1*/ test( "CFDA", "500" );
/*2*/ test( "AB", "460" );
/*3*/ test( "BA", "460" );
/*4*/ test( "CD", "400" );
/*5*/ test( "DC", "350" );
/*6*/ test( "BG", "520" );
/*7*/ test( "GB", "530" );
/*8*/ test( "FDA", "450" );
/*9*/ test( "ADF", "450" );
/*10*/ test( "FDACB", "750" );
/*11*/ test( "BCADF", "710" );
/*12*/ test( "EDACB", "800" );
/*13*/ test( "BCADE", "810" );
/*14*/ test( "EGFCADE", "920" );
/*15*/ test( "EDACFGE", "910" );
/*16*/ test( "ABCDA", "960" );
/*17*/ test( "ADCBA", "1000" );
/*18*/ test( "BADCFGB", "1180" );
/*19*/ test( "BGFCDAB", "1180" );
/*20*/ test( "CDFC", "460" );
/*21*/ test( "CFDC", "450" );
/*22*/ test( "ABGEDA", "1420" );
/*23*/ test( "ADEGBA", "1470" );
/*24*/ test( "CFGB", "640" );
/*25*/ test( "BGFC", "630" );
/*26*/ test( "ABGEDFC", "1480" );
/*27*/ test( "CFDEGBA", "1520" );
/*28*/ test( "CDFGEDABG", "1770" );
/*29*/ test( "GBADEGFDC", "1680" );
_TEST
require 'minitest/autorun'
describe 'Taxi' do
taxi = Taxi.new
test.split("\n").each do |line|
t, n, input, expect = line.match(/^\/\*(\d+)\*\/\s*test\(\s*"([^"]+)",\s*"([^"]+)"\s*\);*\s*$/).to_a
it input do
assert_equal expect, taxi.drive(input).to_s
end
end
end