第30回オフラインリアルタイムどう書くの答案


とある世界のタクシー料金 横へな 2015.4.18 問題の非リアルタイムの答案です。
最初Andoroidでポチポチと1文字ずつコードを打っていましたが、1時間程で限界が来てPCに環境を移しました。
トータル1時間半ぐらいでしょうか。

CITY = {
  'A' => :en,
  'B' => :en,
  'C' => :en,
  'D' => :tan,
  'E' => :tan,
  'F' => :tan,
  'G' => :tan,
}.freeze
ROOT = {
  'AB' => [:en,  1090],
  'AC' => [:en,   180],
  'AD' => [:tan,  540],
  'BC' => [:en,   960],
  'BG' => [:en,  1270],
  'CD' => [:tan,  400],
  'CF' => [:en,   200],
  'DE' => [:tan,  720],
  'DF' => [:tan,  510],
  'EG' => [:tan, 1050],
  'FG' => [:tan,  230],
}.freeze
PAY = {
  en:  [[995, 400], [200, 60]],
  tan: [[845, 350], [200, 50]],
}.freeze

def solve(prms)
  roots = prms[:root].chars.each_cons(2).to_a
  first_start, first_goal = roots.first
  rest_distance, pay = PAY[CITY[first_start]][0]

  roots.each do |root|
    root_region, root_distance = ROOT[root.sort.join]
    pay_distance, pay_cost = PAY[root_region][1]
    rest_distance -= root_distance
    if rest_distance < 0
      pay += (-rest_distance / pay_distance + 1) * pay_cost
      rest_distance %= pay_distance
    end
  end

  pay

end


prms_cfg = [[:root, :to_s], [:expect, :to_i]]

answers = DATA.each_with_object([]) do |line, memo|
  id, *prms_str = line.chomp.split("\t")
  prms_val = prms_cfg.zip(prms_str).map{|(name, convert), str| [name, str.send(convert)]}
  prms = Hash[*prms_val.flatten]

  prms[:estimate] = solve(prms)
  if prms[:estimate] == prms[:expect]
    puts "#{id}: Correct."
  else
    puts "#{id}: Wrong."
    puts "  #{prms}"
    memo << id
  end
end
puts
puts 'wrong answer:'
puts answers.join(',')

__END__
0   ADFC    510
1   CFDA    500
2   AB  460
3   BA  460
4   CD  400
5   DC  350
6   BG  520
7   GB  530
8   FDA 450
9   ADF 450
10  FDACB   750
11  BCADF   710
12  EDACB   800
13  BCADE   810
14  EGFCADE 920
15  EDACFGE 910
16  ABCDA   960
17  ADCBA   1000
18  BADCFGB 1180
19  BGFCDAB 1180
20  CDFC    460
21  CFDC    450
22  ABGEDA  1420
23  ADEGBA  1470
24  CFGB    640
25  BGFC    630
26  ABGEDFC 1480
27  CFDEGBA 1520
28  CDFGEDABG   1770
29  GBADEGFDC   1680