【发布时间】:2014-01-02 16:05:17
【问题描述】:
这是一个相当典型的make a century 问题。
我们有一个自然数列表[1;2;3;4;5;6;7;8;9]。
我们有一个可能的运营商列表[Some '+'; Some '*';None]。
现在我们根据上述可能性创建一个运算符列表,并将每个运算符插入到数字列表中的每个连续数字之间并计算值。
(注意a None b = a * 10 + b)
例如,如果运算符列表为[Some '+'; Some '*'; None; Some '+'; Some '+'; Some '+'; Some '+'; Some '+'],则值为1 + 2 * 34 + 5 + 6 + 7 + 8 + 9 = 104。
请找到所有可能的运算符列表,所以the value = 10。
我能想到的唯一方法是蛮力。
我生成所有可能的运算符列表。
计算所有可能的值。
然后过滤,我得到所有产生 100 的运算符列表。
exception Cannot_compute
let rec candidates n ops =
if n = 0 then [[]]
else
List.fold_left (fun acc op -> List.rev_append acc (List.map (fun x -> op::x) (candidates (n-1) ops))) [] ops
let glue l opl =
let rec aggr acc_l acc_opl = function
| hd::[], [] -> (List.rev (hd::acc_l), List.rev acc_opl)
| hd1::hd2::tl, None::optl -> aggr acc_l acc_opl (((hd1*10+hd2)::tl), optl)
| hd::tl, (Some c)::optl -> aggr (hd::acc_l) ((Some c)::acc_opl) (tl, optl)
| _ -> raise Cannot_glue
in
aggr [] [] (l, opl)
let compute l opl =
let new_l, new_opl = glue l opl in
let rec comp = function
| hd::[], [] -> hd
| hd::tl, (Some '+')::optl -> hd + (comp (tl, optl))
| hd1::hd2::tl, (Some '-')::optl -> hd1 + (comp ((-hd2)::tl, optl))
| hd1::hd2::tl, (Some '*')::optl -> comp (((hd1*hd2)::tl), optl)
| hd1::hd2::tl, (Some '/')::optl -> comp (((hd1/hd2)::tl), optl)
| _, _ -> raise Cannot_compute
in
comp (new_l, new_opl)
let make_century l ops =
List.filter (fun x -> fst x = 100) (
List.fold_left (fun acc x -> ((compute l x), x)::acc) [] (candidates ((List.length l)-1) ops))
let rec print_solution l opl =
match l, opl with
| hd::[], [] -> Printf.printf "%d\n" hd
| hd::tl, (Some op)::optl -> Printf.printf "%d %c " hd op; print_solution tl optl
| hd1::hd2::tl, None::optl -> print_solution ((hd1*10+hd2)::tl) optl
| _, _ -> ()
我相信我的代码很难看。所以我有以下问题
-
computer l opl是使用数字列表和运算符列表进行计算。基本上这是一个典型的数学评估。有没有更好的实现方式? - 我已阅读Pearls of Functional Algorithm Design 中的第 6 章。它使用了一些技术来提高性能。我发现它真的很晦涩难懂。 任何读过它的人都可以帮忙吗?
编辑
我改进了我的代码。基本上,我将首先扫描操作员列表,以将其操作员为None 的所有数字粘合起来。
然后在计算中,如果我遇到'-',我将简单地否定第二个数字。
【问题讨论】:
-
我不明白计算结果的规则。计算不遵循任何明显的优先级和关联性规则。例如,“1 - 2 + 3”的计算结果为 -4,但“8 / 2 * 4”的计算结果为 16。
-
作为第二条评论,你的代码不能处理像'1 + 23'这样的事情
-
@JeffreyScofield 你是对的。我的代码有这样的问题。
-
@JeffreyScofield 我更正了我的代码。请再看看。此外,欢迎任何更好的代码。
-
我编写的代码遵循通常的优先规则并找到了所有解决方案。