- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是 OCaml 新手。我在 OCaml 中编写了一个简单的程序来生成公平和平方数(一个数字是回文和另一个回文的平方,更多详情:https://code.google.com/codejam/contest/2270488/dashboard#s=p2 )如下:
更新 1:优化算法(在我的笔记本电脑上大约需要 20 秒):
open Printf;;
let rec _is_palindrome s i j =
i >= j ||
(s.[i] = s.[j] &&
_is_palindrome s (i + 1) (j - 1))
;;
let is_palindrome s =
let sl = String.length s in
sl > 0 && (_is_palindrome s 0 (sl - 1))
;;
let rec del_zeros s =
let sl = String.length s in
if (sl < 1) then
s
else
(if s.[0] = '0' then
del_zeros (String.sub s 1 (sl - 1))
else
s
)
;;
let c2i c =
Char.code c - Char.code '0'
;;
let i2c i =
Char.chr (i + Char.code '0')
;;
(* only for finding fair and square numbers *)
let square s =
let slen = String.length s in
if slen < 1 then
""
else
let reslen = 2 * slen in
let t = ref 0 in
t := 0;
(* fast check *)
(let i = reslen/2 in
for j = (slen - 1) downto 0 do
if (i - 1 - j) >= 0 && (i - 1 - j) < slen then
t := !t + (c2i s.[j]) * (c2i s.[i - 1 - j]);
done;
if !t > 9 then
(* jump out *)
raise (Invalid_argument "carry");
);
(let res = String.make reslen '0' in
(* do the square cal now *)
for i = (reslen - 1) downto 1 do
t := 0;
for j = (slen - 1) downto 0 do
if (i - 1 - j) >= 0 && (i - 1 - j) < slen then
t := !t + (c2i s.[j]) * (c2i s.[i - 1 - j]);
done;
if !t > 9 then
(* jump out *)
raise (Invalid_argument "carry");
res.[i] <- i2c !t;
done;
del_zeros res
);
;;
let rec check_fs fsns p =
try let sq = square p in
if (is_palindrome sq) then
sq :: fsns
else
fsns
with Invalid_argument "carry" ->
fsns
;;
(* build the fair and square number list *)
(* dfs *)
let rec create_fair_square_nums fsns p sum max_num_digs =
let l = String.length p in
if l > max_num_digs || sum > 9 then
fsns
else
let fsns = create_fair_square_nums fsns ("0" ^ p ^ "0") sum max_num_digs in
let fsns = create_fair_square_nums fsns ("1" ^ p ^ "1") (sum + 1) max_num_digs in
let fsns = create_fair_square_nums fsns ("2" ^ p ^ "2") (sum + 4) max_num_digs in
let fsns = create_fair_square_nums fsns ("3" ^ p ^ "3") (sum + 9) max_num_digs in
let fsns = check_fs fsns p in
fsns
;;
let rec print_fsns fsns =
List.iter (fun s -> printf "%s " s) fsns;
printf "\n"
;;
let num_str_cmp s1 s2 =
let len1 = String.length s1 in
let len2 = String.length s2 in
match (len1 - len2) with
| 0 ->
String.compare s1 s2
| cmp -> cmp
;;
(* works *)
let max_dig = 51;;
let fsns =
let fsns = create_fair_square_nums [] "" 0 max_dig in
let fsns = create_fair_square_nums fsns "0" 0 max_dig in
let fsns = create_fair_square_nums fsns "1" 1 max_dig in
let fsns = create_fair_square_nums fsns "2" 4 max_dig in
create_fair_square_nums fsns "3" 9 max_dig
;;
let fsns = List.sort num_str_cmp fsns;;
print_fsns fsns;;
我的原始代码(天真的解决方案,太慢了):
open Printf;;
let rec _is_palindrome s i j =
if i < j then
if s.[i] = s.[j] then
_is_palindrome s (i + 1) (j - 1)
else
false
else
true
;;
let is_palindrome s =
if (String.length s < 1) then
false
else
_is_palindrome s 0 ((String.length s) - 1)
;;
let rec del_zeros s =
let sl = String.length s in
if (sl < 1) then
s
else
(if s.[0] = '0' then
del_zeros (String.sub s 1 (sl - 1))
else
s
)
;;
let c2i c =
Char.code c - Char.code '0'
;;
let i2c i =
Char.chr (i + Char.code '0')
;;
(* only positive number *)
let square s =
(* including the carry dig *)
let slen = String.length s in
let res = (
if slen > 0 then
let reslen = 2 * slen in
let res = String.make reslen '0' in
let t = ref 0 in
for i = (reslen - 1) downto 1 do
t := c2i (res.[i]);
for j = (slen - 1) downto 0 do
if (i - 1 - j) >= 0 && (i - 1 - j) < slen then
(t := !t + (c2i s.[j]) * (c2i s.[i - 1 - j]);
(* printf "%d, %d: %d\n" j (i - 1 - j) !t; *) )
done;
(* printf "%d: %d\n" i !t; *)
if !t > 9 then
(res.[i - 1] <-
Char.chr (Char.code res.[i - 1] + (!t / 10));
t := !t mod 10
);
res.[i] <- i2c !t;
done;
res;
else
""
) in
(* printf "square %s -> %s\n" s res; *)
del_zeros res
;;
let extend_palindrome new_ps n =
("0" ^ n ^ "0") ::
("1" ^ n ^ "1") ::
("2" ^ n ^ "2") ::
("3" ^ n ^ "3") ::
new_ps
;;
let rec extend_palindromes new_ps ps =
match ps with
| [] -> new_ps
| h :: t ->
let new_ps = extend_palindrome new_ps h in
extend_palindromes new_ps t
;;
let rec check_fs fsns ps =
match ps with
| [] -> fsns
| h :: t ->
let sq = square h in
if (is_palindrome sq) then
check_fs (sq :: fsns) t
else
check_fs fsns t
;;
(* build the fair and square number list *)
let rec create_fair_square_nums fsns ps max_num_digs =
match ps with
| h :: t ->
if String.length h > max_num_digs then
fsns
else
let ps = extend_palindromes [] ps in
let fsns = check_fs fsns ps in
create_fair_square_nums fsns ps max_num_digs
| [] ->
raise (Invalid_argument "fsn should not be []")
;;
let rec print_fsns fsns =
List.iter (fun s -> printf "%s " s) fsns;
printf "\n"
;;
let num_str_cmp s1 s2 =
let len1 = String.length s1 in
let len2 = String.length s2 in
match (len1 - len2) with
| 0 ->
String.compare s1 s2
| cmp -> cmp
;;
(* works *)
let max_dig = 50;;
let fsns =
let fsns0 = create_fair_square_nums [] [""] max_dig in
let fsns1 = create_fair_square_nums [] ["0"; "1"; "2"; "3"] max_dig in
(* print_fsns fsns0;
print_fsns fsns1; *)
["0"; "1"; "4"; "9"] @ fsns0 @ fsns1
;;
(* print_fsns fsns;; *)
let fsns = List.sort num_str_cmp fsns;;
print_fsns fsns;;
此代码生成 10^100 以内的公平和平方数。
此代码在性能方面应该存在一些(或许多)问题。在我杀死它之前它运行了 30 多分钟。当 max_dig = 14 时,它很快完成(< 1 分钟)。
欢迎任何改进此代码的建议或批评。
最佳答案
这可能是许多其他问题中的一个(并且可能被忽略在您的用例中,您应该进行概要分析以找出答案),但是这段代码代码段已经存在算法问题:
let rec del_zeros s =
let sl = String.length s in
if (sl < 1) then
s
else
(if s.[0] = '0' then
del_zeros (String.sub s 1 (sl - 1))
else
s
)
;;
String.sub 在长度参数上是线性的(在内存中,因此时间),所以整个函数是二次函数:del_zeros
可能会很慢。
(String.make 50_000 '0')
要有效地编写此代码,您应该收集保留的字符在列表累加器中,边走边累加总长度,以及最后创建一个大小合适的字符串并写入这些字符
作为近似值,使用 Buffer
的自然代码已经是相当高效(这就是我建议通常写的应用程序,但如果那是一部分的话,可能不在算法竞赛中关键路径):
let del_zeros s =
let buf = Buffer.create (String.length s) in
for i = 0 to (String.length s) - 1 do
if s.[i] <> '0' then Buffer.add_char buf s.[i]
done;
Buffer.contents buf
关于ocaml - 为什么这个 OCaml 代码这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16014877/
我正在尝试以更命令的方式表达一组链式调用。例如,图像我们有一个函数,它接受一个列表和一个元素,并将该元素附加到列表的末尾: let insert l e = l @ [e] 我想一次插入几个元素。
是否有一个完整的列表(或详尽的规则)可以给 OCaml 中的自定义中缀运算符提供可能的名称? 最佳答案 如 OCaml manual 中所述, 中缀运算符必须匹配正则表达式 [-=<>@^|&+*/$
我想开始使用 OCaml 编程。由于我是 Windows 用户,我知道最好使用 Netbeans 的 OCaml 插件。 我已经从以下链接下载了上述插件:http://ocamlplugin.loki
能够做到这一点以获得最大速度不是很重要吗? 编辑: 例如,Clojure 有 map ,它使用多个核心。 Harrop 博士写道(2011 年 1 月 9 日): 语言中添加的新功能,例如一流 OCa
我在 x86 机器上用字节码编译 OCaml 程序,然后将字节码传输到 ppc64 机器。假设 ppc64 机器有 ocamlrun(为 ppc64 编译),我能在 ppc64 架构上执行我的程序吗?
我创建了一个新模块,它只是名称很长的模块的较短别名: module M = ModuleWithLongName 我处于最终可执行文件的大小很重要的情况。上面的构造是由编译器合理处理的吗(即 M 实际
我在使用 ocaml 时遇到了麻烦。 我想创建一个函数,每次调用它时都会增加我的计数器,并将我的 vargen 字符串与计数器编号连接起来,然后返回这个新字符串。 我没有成功的做法是: let (co
我正在学习 OCaml,我对变量的不变性有点困惑。根据我正在阅读的书,变量是不可变的。到目前为止一切顺利,但为什么我可以这样做: let foo = 42 let foo = 4242 我错过了什么?
非尾递归组合函数可以这样写: let rec combinations l k = if k List.length l then [] else if k = 1 then List.ma
我有一段包含camlp4引用的代码。 let f_name = "my_func" > 运行此程序后 camlp4of ,它产生这个: Ast.StExp (_loc, (Ast.ExAp
如何在 OCaml 中模拟这个 Python 习语? if __name__=="__main__": main() 见 RosettaCode其他编程语言中的示例。 最佳答案 Ocaml 中没
我开始学习 Ocaml,使用 hickey book ,我被困在练习 3.4,第 9 部分 让 x x = x + 1 在 x 2 运算结果为3 ,但我不明白为什么? 最佳答案 当你写 let x x
Rust具有线性系统。有什么(好的)方法可以在 OCaml 中模拟这个吗?例如,当使用 ocaml-lua 时,我想确保仅当 Lua 处于特定状态(堆栈顶部的表等)时才调用某些函数。 编辑 :这是最近
在 OCaml?我知道非常酷的Bitstring图书馆,但是 虽然这将是在某些协议(protocol)中解析二进制数据的好方法, 它不支持异或或移位等按位运算。 我相信该库使用的底层数据结构是 只是
我们可以像这样构造一个无限列表: let rec endless = 1::endless 我认为它会吃掉所有的内存,但是当我在 utop 中尝试时,好像不是这样。 utop显示列表已构建: val
是否可以通过合并列表的元素而不是创建列表的列表来创建列表? 例子: List.combine ["A";"B"] ["C";"D"];; 我得到: [("A", "C"); ("B", "D")] 有
我想在 OCaml 中创建一个查找表。该表将有 7000 多个条目,在查找时(通过 int)返回一个字符串。用于此任务的适当数据结构是什么?表是否应该从基本代码中外部化,如果是这样,如何“包括”查找表
我正在评估 Ocaml 顶层中的一段非常简单的代码: let p5 () = print_int 5;; p5 ();; print_string "*************************
记录和元组之间是否有任何区别而不仅仅是句法差异? 有性能差异吗? 元组和记录的实现是否相同? 您是否有可以使用元组完成但不能使用记录完成的事情的示例(和 反之)? 最佳答案 模数语法它们几乎相同。主要
OCaml 中的 ` 运算符有什么作用? let int_of_meth = function | `GET -> 0 | `POST -> 1 | `PUT ->
我是一名优秀的程序员,十分优秀!