Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm OCaml中的倒计时游戏_Algorithm_Functional Programming_Ocaml - Fatal编程技术网

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))