fork(1) download
  1. let binary = function '*' -> (*) | '+' -> (+) | _ -> (-)
  2. let appendOp ((ll, lrs), rs) v = function
  3. | '*' as op -> (v, (binary op, ll)::lrs), rs
  4. | op -> (v, []), (binary op, (ll, lrs))::rs
  5.  
  6. let evalOp eval (x, xs) = List.foldBack (fun ((@), l) r -> eval l @ r) xs (eval x)
  7. let eval = evalOp <| evalOp id
  8. let literal x = (x, []), []
  9. let replaceHead v ((_, lrs), rs) = (v, lrs), rs
  10.  
  11. let step (expr, view, op) = function
  12. | '=' -> let view = eval expr in literal view, view, Some '='
  13. | c when '0' <= c && c <= '9' ->
  14. let d = int c - int '0'
  15. match op with
  16. | Some '=' -> literal d, d, None
  17. | Some op -> appendOp expr d op, d, None
  18. | None ->
  19. let view = view * 10 + d
  20. replaceHead view expr, view, None
  21.  
  22. | op -> expr, (eval expr), Some op
  23.  
  24. let calc = Seq.fold step (literal 0, 0, None) >> fun (_,v,_) -> string v
  25.  
  26. let (=>) src exp =
  27. let act = calc src
  28. let msg = if act = exp then "ok" else "error"
  29. printfn "%s { src = %A, exp = %A, act = %A }" msg src exp act
  30.  
  31. // お題:電卓を実装する
  32. // 引数はボタン入力履歴で、戻り値は現在の表示
  33. // ボタンは 0123456789-+*= のみ
  34. "5" => "5"
  35. "5+" => "5"
  36. "5+3" => "3"
  37. "5+3=" => "8"
  38.  
  39. "5*-3=" => "2" // 最後に入力した演算子が有効
  40. "5-3+" => "2" // 途中結果を表示する
  41. "5-3*2=" => "-1" // -+ よりも * が優先される
  42.  
  43. // 初期値は 0
  44. "" => "0"
  45. "-10=" => "-10"
  46. "*10=" => "0"
  47.  
  48. "4+3=2=" => "2" // = の次に数値が入力された場合、途中結果は捨てる
  49. "4+3=*2=" => "14" // * よりも = が優先される
Success #stdin #stdout 0.22s 25488KB
stdin
Standard input is empty
stdout
ok { src = "5", exp = "5", act = "5" }
ok { src = "5+", exp = "5", act = "5" }
ok { src = "5+3", exp = "3", act = "3" }
ok { src = "5+3=", exp = "8", act = "8" }
ok { src = "5*-3=", exp = "2", act = "2" }
ok { src = "5-3+", exp = "2", act = "2" }
ok { src = "5-3*2=", exp = "-1", act = "-1" }
ok { src = "", exp = "0", act = "0" }
ok { src = "-10=", exp = "-10", act = "-10" }
ok { src = "*10=", exp = "0", act = "0" }
ok { src = "4+3=2=", exp = "2", act = "2" }
ok { src = "4+3=*2=", exp = "14", act = "14" }