Edited at

オフラインリアルタイムどう書くE04 の yancya の解答

More than 3 years have passed since last update.

Ruby で解きました


問題


方針


  • 全体の横道の数だけステップがある

  • 各ステップで、どの横道に入るかという情報のリストが石側、登山家側の両方で作れる

  • いずれかのステップで石の通る横道と被ってしまう登山家はアウト(意味深)

  • 石が全く横道に入らない場合、最初に石が落ち始めた方角にいる登山家はアウト(意味深)


コード

# coding: utf-8

LABELS = ("A".."H").to_a

def hoge(code)
# code #=> "2512:C"

sideways, start = code.split(":").tap { |a, b|
break [
a.chars.map(&:to_i).
map { |n| [LABELS[n-1], LABELS[n % 8]].join },
b
]
}

# sideways #=> ["BC", "EF", "AB", "BC"]
# start #=> "C"

router = -> ((d, log), way) {
if way.match(d)
[way.gsub(d, ""), log + [way]]
else
[d, log + [nil]]
end
}

routes = LABELS.map { |l| sideways.reverse.reduce([l, []], &router) }.to_h

# 麓から登ったときのゴールが key、経路が value
# routes #=> {
# "C" => [ nil, "AB", nil, "BC"],
# "B" => ["BC", nil, nil, "BC"],
# "A" => ["BC", "AB", nil, nil],
# "D" => [ nil, nil, nil, nil],
# "F" => [ nil, nil, "EF", nil],
# "E" => [ nil, nil, "EF", nil],
# "G" => [ nil, nil, nil, nil],
# "H" => [ nil, nil, nil, nil]
# }

# 石のスタート方向がゴールになっている経路の逆順が石の経路
danger_route = routes[start].reverse

# danger_route #=> ["BC", nil, "AB", nil]

routes.values.map { |route|
route.
zip(danger_route.reverse).
map { |(a, b)| a && a == b ? "死" : "セーフ" }.
index("死") ? "死" : "生"
}.map.with_index { |judge, i| #=> ["死", "死", "死", "生", "生", "生", "生", "生"]
LABELS[i] if judge == "生"
}. #=> [nil, nil, nil, "D", "E", "F", "G", "H"]
compact. #=> ["D", "E", "F", "G", "H"]
join. #=> "DEFGH"
gsub(danger_route.none? ? start : "", "") #=> "DEFGH"
end

require 'test-unit'
class MainTest < Test::Unit::TestCase
data(
"/*00*/" => ["2512:C", "DEFGH"],
"/*01*/" => ["1:A", "CDEFGH"],
"/*02*/" => [":C", "ABDEFGH"],
"/*03*/" => ["2345:B", "AGH"],
"/*04*/" => ["1256:E", "ABCDH"],
"/*05*/" => ["1228:A", "ADEFG"],
"/*06*/" => ["5623:B", "AEFGH"],
"/*07*/" => ["8157:C", "ABDEFGH"],
"/*08*/" => ["74767:E", "ABCFGH"],
"/*09*/" => ["88717:D", "ABCEFGH"],
"/*10*/" => ["148647:A", "ACDEFH"],
"/*11*/" => ["374258:H", "BCDEFH"],
"/*12*/" => ["6647768:F", "ABCDEH"],
"/*13*/" => ["4786317:E", "ABFGH"],
"/*14*/" => ["3456781:C", ""],
"/*15*/" => ["225721686547123:C", "CEF"],
"/*16*/" => ["2765356148824666:F", "ABCDEH"],
"/*17*/" => ["42318287535641783:F", "BDE"],
"/*18*/" => ["584423584751745261:D", "FGH"],
"/*19*/" => ["8811873415472513884:D", "CFG"],
"/*20*/" => ["74817442725737422451:H", "BCDEF"],
"/*21*/" => ["223188865746766511566:C", "ABGH"],
"/*22*/" => ["2763666483242552567747:F", "ABCG"],
"/*23*/" => ["76724442325377753577138:E", "EG"],
"/*24*/" => ["327328486656448784712618:B", ""],
"/*25*/" => ["4884637666662548114774288:D", "DGH"],
"/*26*/" => ["84226765313786654637511248:H", "DEF"],
"/*27*/" => ["486142154163288126476238756:A", "CDF"],
"/*28*/" => ["1836275732415226326155464567:F", "BCD"],
"/*29*/" => ["62544434452376661746517374245:G", "G"],
"/*30*/" => ["381352782758218463842725673473:B", "A"],
)
test "hoge" do |(actual, expected)|
assert { hoge(actual) == expected }
end
end