Algorithm OCaml中的倒计时游戏
这是一个非常典型的游戏 您将获得一个整数列表和一个值 您可以使用括号,Algorithm OCaml中的倒计时游戏,algorithm,functional-programming,ocaml,Algorithm,Functional Programming,Ocaml,这是一个非常典型的游戏 您将获得一个整数列表和一个值 您可以使用括号,+,-,*,/来接近给定值 不必使用列表中的所有整数。如果不能计算出一个相同的值,那么您正在寻找最接近的值 例如,您将给出[1;3;7;10;25;50]和831。你能做的最接近的就是 7+(1+10)*(25+50)=832 如何在FP或ocaml中编写程序来解决这个问题 如何使用括号 如何生成所有可能的表达式 有关说明,请参见。您的示例不遵循规则:-)圆括号只是控制求值顺序的表面特征。我会考虑使用更稠密的符号(如RPN
+
,-
,*
,/
来接近给定值
不必使用列表中的所有整数。如果不能计算出一个相同的值,那么您正在寻找最接近的值
例如,您将给出
[1;3;7;10;25;50]
和831
。你能做的最接近的就是
7+(1+10)*(25+50)=832
如何在FP或ocaml中编写程序来解决这个问题
有关说明,请参见。您的示例不遵循规则:-)圆括号只是控制求值顺序的表面特征。我会考虑使用更稠密的符号(如RPN)来解决,然后转换成中缀符号。“JeffryyScFieldFrime。这是一个有趣的问题,但它如何具体OcAML?@ MartinJambon,不,它不是具体的OCAML。我可以用一种语言问一个特定的解决方案吗?我的意思是这个问题是关于解决这个问题的算法。即使是蛮力也不是微不足道的,但从伪代码表示的算法到有效的OCaml程序,回答起来会更快,也会为更多人提供价值。在OCaml中的
函数编程中,我可以找到解释?@JacksonTale slides 33-43,它也有优化版本。
let (|->) l f = List.concat (List.map f l)
type op = Add | Sub | Mul | Div
let apply op x y =
match op with
| Add -> x + y
| Sub -> x - y
| Mul -> x * y
| Div -> x / y
let valid op x y =
match op with
| Add -> true
| Sub -> x > y
| Mul -> true
| Div -> x mod y = 0
type expr = Val of int | App of op * expr * expr
let rec eval = function
| Val n -> if n > 0 then Some n else None
| App (o,l,r) ->
eval l |> map_option (fun x ->
eval r |> map_option (fun y ->
if valid o x y then Some (apply o x y)
else None))
let list_diff a b = List.filter (fun e -> not (List.mem e b)) a
let is_unique xs =
let rec aux = function
| [] -> true
| x :: xs when List.mem x xs -> false
| x :: xs -> aux xs in
aux xs
let rec values = function
| Val n -> [n]
| App (_,l,r) -> values l @ values r
let solution e ns n =
list_diff (values e) ns = [] && is_unique (values e) &&
eval e = Some n
(* Brute force solution. *)
let split l =
let rec aux lhs acc = function
| [] | [_] -> []
| [y; z] -> (List.rev (y::lhs), [z])::acc
| hd::rhs ->
let lhs = hd::lhs in
aux lhs ((List.rev lhs, rhs)::acc) rhs in
aux [] [] l
let combine l r =
List.map (fun o->App (o,l,r)) [Add; Sub; Mul; Div]
let rec exprs = function
| [] -> []
| [n] -> [Val n]
| ns ->
split ns |-> (fun (ls,rs) ->
exprs ls |-> (fun l ->
exprs rs |-> (fun r ->
combine l r)))
let rec choices = function _ -> failwith "choices: implement as homework"
let guard n =
List.filter (fun e -> eval e = Some n)
let solutions ns n =
choices ns |-> (fun ns' ->
exprs ns' |> guard n)
(* Alternative implementation *)
let guard p e =
if p e then [e] else []
let solutions ns n =
choices ns |-> (fun ns' ->
exprs ns' |->
guard (fun e -> eval e = Some n))