LoginSignup
0
0

More than 5 years have passed since last update.

第9回オフラインリアルタイムどう書くの問題をF#で

Last updated at Posted at 2013-04-23

参考問題を解くつもりが実問題を解いてしまったようだ。

bus.fs
type Age = Infant | Child | Adult
type Rate = Normal | Commuter | Welfare
type Fare = Age * Rate * int

let UNIT = 10
let roundup u f = (f / u * u) + (if f % u = 0 then 0 else u)
let applyAge (a,r,i) =
  match a with
  | Adult -> (a,r,i)
  | _     -> (a,r,roundup UNIT (i/2))
let applyRate (a,r,i) =
  match r with
  | Normal   -> (a,r,i)
  | Commuter -> (a,r,0)
  | Welfare  -> (a,r,roundup UNIT (i/2))
let rec free n ps =
  match (n, ps) with
  | (0, _)           -> ps
  | (_, [])          -> []
  | (_, (a,r,_)::xs) -> (a,r,0)::free (n-1) xs
let partitionByAge ps =
  let folder p (al,cl,il) =
    match p with
    | (Adult, _,_) -> (p::al,   cl,   il)
    | (Child, _,_) -> (   al,p::cl,   il)
    | (Infant,_,_) -> (   al,   cl,p::il)
  List.foldBack folder ps ([],[],[])
let fare ps =
  let (al,cl,il) =
    ps
    |> List.map (applyAge >> applyRate)
    |> partitionByAge
  let il2 =
    il
    |> List.sortWith (fun (_,_,x) (_,_,y) -> compare y x)
    |> free (2 * List.length al)
  List.append al << List.append cl <| il2
let parse (str:string) =
  let toA c =
    match c with
    | 'A' -> Adult
    | 'C' -> Child
    | 'I' -> Infant
    | _   -> failwith "invalid input"
  let toR c =
    match c with
    | 'n' -> Normal
    | 'p' -> Commuter
    | 'w' -> Welfare
    | _   -> failwith "invalid input"
  let colon = str.IndexOf(':')
  let f = System.Int32.Parse(str.Substring(0, colon))
  str.Substring(colon+1).Split([|','|])
  |> Array.map (fun s -> (toA (s.Chars 0), toR (s.Chars 1), f))
  |> Array.toList
let calc = parse >> fare >> List.sumBy (fun (_,_,f) -> f)

(* for test *)

type TestResult = Success | Failure

let test target expected =
  let actual = calc target
  printfn "%A" (if expected = actual then Success else Failure)

[<EntryPoint>]
let main args =
  test "210:Cn,In,Iw,Ap,Iw" 170
  test "220:Cp,In" 110
  test "230:Cw,In,Iw" 240
  test "240:In,An,In" 240
  test "250:In,In,Aw,In" 260
  test "260:In,In,In,In,Ap" 260
  test "270:In,An,In,In,Ip" 410
  test "280:Aw,In,Iw,In" 210
  test "200:An" 200
  test "210:Iw" 60
  test "220:Ap" 0
  test "230:Cp" 0
  test "240:Cw" 60
  test "250:In" 130
  test "260:Cn" 130
  test "270:Ip" 0
  test "280:Aw" 140
  test "1480:In,An,In,In,In,Iw,Cp,Cw,In,Aw,In,In,Iw,Cn,Aw,Iw" 5920
  test "630:Aw,Cw,Iw,An,An" 1740
  test "340:Cn,Cn,Ip,Ap" 340
  test "240:Iw,Ap,In,Iw,Aw" 120
  test "800:Cw,An,Cn,Aw,Ap" 1800
  test "1210:An,Ip,In,Iw,An,Iw,Iw,An,Iw,Iw" 3630
  test "530:An,Cw,Cw" 810
  test "170:Aw,Iw,Ip" 90
  test "150:In,Ip,Ip,Iw,In,Iw,Iw,In,An,Iw,Aw,Cw,Iw,Cw,An,Cp,Iw" 580
  test "420:Cn,Cw,Cp" 320
  test "690:Cw,In,An,Cp,Cn,In" 1220
  test "590:Iw,Iw,Cn,Iw,Aw,In,In,Ip,Iw,Ip,Aw" 1200
  test "790:Cw,Cn,Cn" 1000
  test "1220:In,In,An,An,In,Iw,Iw,In,In,Ip,In,An,Iw" 4590
  test "570:Cw,Cn,Cp" 440
  test "310:Cn,Cw,An,An,Iw,Cp,Cw,Cn,Iw" 1100
  test "910:Aw,In,Iw,Iw,Iw,Iw,Iw,An,Cw,In" 2290
  test "460:Iw,Cw,Cw,Cn" 590
  test "240:Iw,Iw,In,Iw,In,In,Cn,In,An" 780
  test "1240:In,In,In,Ap,In,Cw,Iw,Iw,Iw,Aw,Cw" 2170
  test "1000:Iw,Ip,In,An,In,In,In,An,In,Iw,In,In,Iw,In,Iw,Iw,Iw,An" 5500
  test "180:In,Aw,Ip,Iw,In,Aw,In,Iw,Iw,In" 330
  test "440:In,Ip,Cp,Aw,Iw,In,An" 660
  test "1270:Ap,In,An,Ip,In,Ip,Ip" 1270
  0
0
0
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
0
0