Ocaml 5位数字的数量,无大于12345的重复数字

Ocaml 5位数字的数量,无大于12345的重复数字,ocaml,Ocaml,我是OCaml和算法的初学者。 我试图得到5位数的数字,重复的数字不超过12345 这是我在OCaml中所做的,我尝试尽可能地使尾部递归,并且我还使用了流。但是,由于尺寸的原因,它的堆栈溢出: type 'a stream = Eos | StrCons of 'a * (unit -> 'a stream) let rec numberfrom n= StrCons (n, fun ()-> numberfrom (n+1)) let nats = numberfrom 1

我是OCaml和算法的初学者。 我试图得到5位数的数字,重复的数字不超过12345

这是我在OCaml中所做的,我尝试尽可能地使尾部递归,并且我还使用了流。但是,由于尺寸的原因,它的堆栈溢出:

type 'a stream = Eos | StrCons of 'a * (unit -> 'a stream)

let rec numberfrom n= StrCons (n, fun ()-> numberfrom (n+1))

let nats = numberfrom 1

let rec listify st n f=
  match st with
  |Eos ->f []
  |StrCons (m, a) ->if n=1 then f [m] else listify (a ()) (n-1) (fun y -> f (m::y))


let rec filter (test: 'a-> bool) (s: 'a stream) : 'a stream=
  match s with
  |Eos -> Eos
  |StrCons(q,w) -> if test q then StrCons(q, fun ()->filter test (w ()))
      else filter test (w ())



let rec check_dup l=
  match l with
  | [] -> false
  | h::t->
      let x = (List.filter (fun x -> x = h) t) in
      if (x == []) then
        check_dup t
      else
        true;;

let digits2 d =
  let rec dig acc d =
    if d < 10 then d::acc
    else dig ((d mod 10)::acc) (d/10) in
  dig [] d

let size a=
  let rec helper n aa=
    match aa with
    |Eos-> n
    |StrCons (q,w) -> helper (n+1) (w())
  in helper 0 a

let result1 = filter (fun x -> x<99999 && x>=12345 && (not (check_dup (digits2 x)))) nats



(* unterminating : size result1 *)
        (*StackOverflow: listify result1 10000 (fun x->x) *)
type'a stream=Eos | StrCons'a*(单元->'a stream)
让recnumberfrom n=StrCons(n,fun()->numberfrom(n+1))
设nats=numberfrom 1
让rec列出st n f=
匹配
|Eos->f[]
|StrCons(m,a)->如果n=1,那么f[m]else列表化(a())(n-1)(funy->f(m::y))
let rec filter(test:'a->bool)(s:'a stream):'a stream=
匹配
|Eos->Eos
|StrCons(q,w)->如果测试q,那么StrCons(q,fun()->过滤测试(w())
else过滤器测试(w())
让记录检查重复=
匹配
|[]->false
|h::t->
让x=(List.filter(funx->x=h)t)进入
如果(x=[]),则
重复检查
其他的
是的;;
让我们把它数字化=
让rec挖掘ACCD=
如果d<10,则d::acc
其他挖掘(d模块10)::acc(d/10)英寸
挖
让我们看看a码=
让rec helper n aa=
将aa与
|Eos->n
|StrCons(q,w)->helper(n+1)(w())
在帮助程序0a中
让result1=filter(funx->x=12345&&(not(check_-dup(digits2x)))nats
(*未终止:大小结果1*)
(*StackOverflow:listify result1 10000(乐趣x->x)*)

我无法重现您报告的问题。当我加载您的代码时,我看到:

# List.length (listify result1 10000 (fun x -> x));;
- : int = 10000
# List.length (listify result1 26831 (fun x -> x));;
- : int = 26831
你的系统可能比我的系统资源更有限

我只想说,编写尾部递归函数的常用方法是反向构建列表,然后在最后反向。可能看起来像这样:

let listify2 st n =
    let rec ilist accum st k =
        match st with
        | Eos -> List.rev accum
        | StrCons (m, a) ->
            if k = 1 then List.rev (m :: accum)
            else ilist (m :: accum) (a ()) (k - 1)
    in
    if n = 0 then []
    else ilist [] st n

您仍然存在一个问题,即如果您请求的元素多于流中的元素,listify不会终止。最好引入一种方法来检测流的结尾并在该点返回Eos。例如,
filter
函数可能接受一个返回三个可能值的函数(应该过滤掉元素,不应该过滤掉元素,流应该结束)。

我无法重现您报告的问题。当我加载您的代码时,我看到:

# List.length (listify result1 10000 (fun x -> x));;
- : int = 10000
# List.length (listify result1 26831 (fun x -> x));;
- : int = 26831
你的系统可能比我的系统资源更有限

我只想说,编写尾部递归函数的常用方法是反向构建列表,然后在最后反向。可能看起来像这样:

let listify2 st n =
    let rec ilist accum st k =
        match st with
        | Eos -> List.rev accum
        | StrCons (m, a) ->
            if k = 1 then List.rev (m :: accum)
            else ilist (m :: accum) (a ()) (k - 1)
    in
    if n = 0 then []
    else ilist [] st n

您仍然存在一个问题,即如果您请求的元素多于流中的元素,listify不会终止。最好引入一种方法来检测流的结尾并在该点返回Eos。例如,
filter
函数可能接受一个返回三个可能值的函数(应该过滤掉元素,不应该过滤掉元素,流应该结束)。

问题是流
result1
的大小未定义

实际上,
nats
是一个永无止境的流:它永远不会返回
Eos

但是,过滤一个永无止境的流会导致另一个永无止境的流 由于过滤后的流仅在基础流返回Eos后返回Eos:

let rec filter (test: 'a-> bool) (s: 'a stream) : 'a stream=
  match s with
  | Eos -> Eos
  | StrCons(q,w) -> if test q then StrCons(q, fun ()->filter test (w ()))
      else filter test (w ())
因此,
size result1
在尝试到达整数结尾时被卡住


还请注意,在标准库的最新版本中,您的类型
称为
Seq.node

问题在于流的大小
result1
未定义

实际上,
nats
是一个永无止境的流:它永远不会返回
Eos

但是,过滤一个永无止境的流会导致另一个永无止境的流 由于过滤后的流仅在基础流返回Eos后返回Eos:

let rec filter (test: 'a-> bool) (s: 'a stream) : 'a stream=
  match s with
  | Eos -> Eos
  | StrCons(q,w) -> if test q then StrCons(q, fun ()->filter test (w ()))
      else filter test (w ())
因此,
size result1
在尝试到达整数结尾时被卡住


还要注意,在标准库的最新版本中,您的类型
被称为
Seq.node

对不起,我认为过滤后的result1是有限的。那么它不应该终止吗?不,
filter
函数无法知道
test
总是在流的前99999个元素之后返回false。因此,它一直试图在result1中再计算一个元素。对不起,我认为过滤后result1是有限的。那么它不应该终止吗?不,
filter
函数无法知道
test
总是在流的前99999个元素之后返回false。因此,它一直在尝试计算result1中的另一个元素。