LoginSignup
1
1

More than 5 years have passed since last update.

"第30回オフラインリアルタイムどう書くの問題" 解いてみた

Last updated at Posted at 2015-04-21

概要

Nabetaniさんの「とある世界のタクシー料金」問題をRubyで解いてみました。
元記事はこちらから
http://qiita.com/Nabetani/items/c70417d384720a3339d6

実装

Rubyで解いてますが、解き方自体はどの言語でも良さそうな感じの実装です。
(どちらの都市でも200m毎に料金加算なので使ってない定数は放置)

taxi_fee.rb

# encoding: sjis
# 
# とある世界のタクシー料金を計算する
# Author:: lithtle
# Created_At:: 2015-04-21
# Link:: http://nabetani.sakura.ne.jp/hena/ord30taxi/

# 都市の地点と経路
CITY = {
    enlightened: [:A, :B, :C, :AB, :AC, :BG, :CF, :BC],
    registance: [:D, :E, :F, :G, :AD, :CD, :DE, :DF, :EG, :FG]
}.freeze

# 各地点間の距離
DISTANTCE = {
    AB: 1090,
    AC: 180,
    AD: 540,
    BC: 960,
    BG: 1270,
    CD: 400,
    CF: 200,
    DE: 720,
    DF: 510,
    EG: 1050,
    FG: 230
}.freeze

# 各都市でのタクシー設定
TAXI_SETTING = {
    enlightened: {min_dist: 995, min_fee: 400, per_meter: 200, per_fee: 60},
    registance: {min_dist: 845, min_fee: 350, per_meter: 200, per_fee: 50}
}.freeze

# 経路から都市を判定する
# == Args
# _route_: 経路または地点、文字列
# == Returns
# 覚醒派か開放派か
def get_city(route)
    if CITY[:enlightened].any?{ |e| e == route.to_sym || e == route.reverse.to_sym }
        :enlightened
    elsif CITY[:registance].any?{ |e| e == route.to_sym || e == route.reverse.to_sym }
        :registance
    else
        raise "未定義の経路指定"
    end
end

# とある世界のタクシー料金を求める
# == Args
# _route_: 料金を計算したいルート
# == Returns
# 料金
def get_taxi_fee(route)
    n = 2
    start_point = route[0]

    # 各地点の累積距離を求める
    route = route.scan(/\w/).each_cons(n).map(&:join) # => ["AB", "BC", "CD"]
    each_dist = route.map{ |e| DISTANTCE[e.to_sym] || DISTANTCE[e.reverse.to_sym] } # => [100, 200, 300]
    integrated_distantce =  each_dist.collect.with_index{ |e, i| each_dist[0..i].reduce(:+) } # => [100, 300, 600]

    # 初期設定(初乗り運賃、初乗り料金)を求める
    running_disatnce, total_fee = [
        TAXI_SETTING[get_city(start_point)][:min_dist],
        TAXI_SETTING[get_city(start_point)][:min_fee]
    ]

    # タクシー⊂(^ω^)⊃ブーン
    total_distance = integrated_distantce[-1]
    while running_disatnce < total_distance
        # 到着したら終了
        if running_disatnce > total_distance
            break
        end

        # 現在位置からどちらの都市かを判定し運賃を加算
        current_pos = route[integrated_distantce.find_index{ |e| e > running_disatnce }]
        total_fee += TAXI_SETTING[get_city(current_pos)][:per_fee]

        # 200m すすむ
        running_disatnce += 200
    end

    total_fee
end

# てすと
def test
    DATA.read.split("\n").map{ |e|
        e.gsub(/\s+/, ",").split(",")
    }.each do |item|
        i, route, expect = item
        actual = get_taxi_fee(route)
        ok = actual == expect.to_i ? "ok" : "ng"
        puts "%2d: %-10s => res: %5s == %-5s : exp => %s" % [i.to_i, route, actual, expect, ok]
    end
end

if $0 == __FILE__
    test
end

__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

その他

都市名がingress由来ということにさっぱり気づきませんでした。書いてる途中にふと気になって調べてみたらingressのページがでてきたため、いそいでコードに修正を加えました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1