1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?