为什么此 OCaml 代码会导致运行时错误?
Why is this OCaml code resulting in a runtime error?
我正在尝试 运行 编码问题网站上的以下代码,它说有一个 运行 时间错误,但是 运行 在顶级 ocaml 上使用它似乎工作正常。代码中可能有任何错误来源吗?提前致谢
问题是在给定的列表中找到 'good segments' 的数量和一个特定的数字。好的细分定义如下:
- A 和 B 是满足 A < B 的正整数。
- 满足 A <= x <= B 的 x 不是给定列表的元素。
以下是输入。
- n,这是将要给出的列表中元素的数量。
- a, b, c, ... 是列表的元素。
- t,这是段中必须包含的数字。
输出应该是打印出来的单个数字。
编辑代码:
let rec drop_value l to_drop =
match l with
| [] -> []
| hd :: tl ->
let new_tl = drop_value tl to_drop in
if hd = to_drop then new_tl else hd :: new_tl
;;
let rec find_start li t cur_min =
match li with
| [] -> cur_min
| hd :: tl -> let new_min = abs (t - hd) in
if new_min = 0 then find_start tl t new_min
else if new_min < cur_min && t > hd then find_start tl t new_min
else find_start tl t cur_min
;;
let rec find_end li t cur_min =
match li with
| [] -> cur_min
| hd :: tl -> let new_min = abs (t - hd) in
if new_min = 0 then find_end tl t new_min
else if new_min < cur_min && t < hd then find_end tl t new_min
else find_end tl t cur_min
;;
let rec contains_value l value =
match l with
| [] -> false
| hd :: tl -> if hd = value then true else contains_value tl value
;;
let nums = ref [];;
let n = read_int () in
for i = 1 to n do
Scanf.scanf " %d" (fun a ->
nums := a :: !nums)
done;
Scanf.scanf " %d" (fun t ->
if contains_value !nums t then print_int 0
else let start = if List.length !nums = 1 then 1 else abs (find_start !nums t 1001 - t) in
let finish = find_end (drop_value !nums start) t 1001 + t in
if t > start && t < finish then (if start = 1 && List.length ! nums = 1 then print_int ((t - start + 1) * (finish - t) - 1) else print_int ((t - start) * (finish - t) - 1))
else let start = 1 in print_int ((t - start + 1) * (finish - t) - 1))
;;
例如
5
4 8 13 24 30
10
应该给
5
=> [9, 10], [9, 11], [9, 12], [10, 11], [10, 12]
您没有描述您的代码将获得的确切输入格式。这使得调试代码几乎不可能。
当我使用您描述的输入编译并 运行 您的代码(如 m.ml
)时,我看到了:
$ ./m
5 4 8 13 24 30 10
Fatal error: exception Failure("int_of_string")
事实上,无论我尝试输入什么格式,我都会得到相同的结果。
这可能就是网站上发生的事情。
根据我的经验,使用它总是弊大于利 scanf
。将它与其他输入功能结合使用可能会使事情变得更糟。
如果您仔细描述了预期的输入格式,Whosebug 上的人可以推荐一种获取数字的方法。
同时,这里有一种在一行中读取所有数字的方法:
let rec split_at list n =
if n = 0 then
([], list)
else
match list with
| [] -> ([], [])
| h :: t ->
let (a, b) = split_at t (n - 1) in (h :: a, b)
in
let (nums, t) =
let line = read_line () in
let nstrs = Str.split (Str.regexp "[ \t][ \t]*") line in
match List.map int_of_string nstrs with
| [] -> failwith "no numbers"
| n :: rest ->
if List.length rest <> n + 1 then
failwith "bad count"
else
let (nums, tlist) = split_at rest n in
(nums, List.hd tlist)
in
. . .
我正在尝试 运行 编码问题网站上的以下代码,它说有一个 运行 时间错误,但是 运行 在顶级 ocaml 上使用它似乎工作正常。代码中可能有任何错误来源吗?提前致谢
问题是在给定的列表中找到 'good segments' 的数量和一个特定的数字。好的细分定义如下:
- A 和 B 是满足 A < B 的正整数。
- 满足 A <= x <= B 的 x 不是给定列表的元素。
以下是输入。
- n,这是将要给出的列表中元素的数量。
- a, b, c, ... 是列表的元素。
- t,这是段中必须包含的数字。
输出应该是打印出来的单个数字。
编辑代码:
let rec drop_value l to_drop =
match l with
| [] -> []
| hd :: tl ->
let new_tl = drop_value tl to_drop in
if hd = to_drop then new_tl else hd :: new_tl
;;
let rec find_start li t cur_min =
match li with
| [] -> cur_min
| hd :: tl -> let new_min = abs (t - hd) in
if new_min = 0 then find_start tl t new_min
else if new_min < cur_min && t > hd then find_start tl t new_min
else find_start tl t cur_min
;;
let rec find_end li t cur_min =
match li with
| [] -> cur_min
| hd :: tl -> let new_min = abs (t - hd) in
if new_min = 0 then find_end tl t new_min
else if new_min < cur_min && t < hd then find_end tl t new_min
else find_end tl t cur_min
;;
let rec contains_value l value =
match l with
| [] -> false
| hd :: tl -> if hd = value then true else contains_value tl value
;;
let nums = ref [];;
let n = read_int () in
for i = 1 to n do
Scanf.scanf " %d" (fun a ->
nums := a :: !nums)
done;
Scanf.scanf " %d" (fun t ->
if contains_value !nums t then print_int 0
else let start = if List.length !nums = 1 then 1 else abs (find_start !nums t 1001 - t) in
let finish = find_end (drop_value !nums start) t 1001 + t in
if t > start && t < finish then (if start = 1 && List.length ! nums = 1 then print_int ((t - start + 1) * (finish - t) - 1) else print_int ((t - start) * (finish - t) - 1))
else let start = 1 in print_int ((t - start + 1) * (finish - t) - 1))
;;
例如
5
4 8 13 24 30
10
应该给
5
=> [9, 10], [9, 11], [9, 12], [10, 11], [10, 12]
您没有描述您的代码将获得的确切输入格式。这使得调试代码几乎不可能。
当我使用您描述的输入编译并 运行 您的代码(如 m.ml
)时,我看到了:
$ ./m
5 4 8 13 24 30 10
Fatal error: exception Failure("int_of_string")
事实上,无论我尝试输入什么格式,我都会得到相同的结果。
这可能就是网站上发生的事情。
根据我的经验,使用它总是弊大于利 scanf
。将它与其他输入功能结合使用可能会使事情变得更糟。
如果您仔细描述了预期的输入格式,Whosebug 上的人可以推荐一种获取数字的方法。
同时,这里有一种在一行中读取所有数字的方法:
let rec split_at list n =
if n = 0 then
([], list)
else
match list with
| [] -> ([], [])
| h :: t ->
let (a, b) = split_at t (n - 1) in (h :: a, b)
in
let (nums, t) =
let line = read_line () in
let nstrs = Str.split (Str.regexp "[ \t][ \t]*") line in
match List.map int_of_string nstrs with
| [] -> failwith "no numbers"
| n :: rest ->
if List.length rest <> n + 1 then
failwith "bad count"
else
let (nums, tlist) = split_at rest n in
(nums, List.hd tlist)
in
. . .