功能:构造一个整数列表 1..n

发布于 2024-07-20 07:51:36 字数 643 浏览 7 评论 0原文

这不是家庭作业。 我正在自学标准机器学习。 我也了解一点Scheme,所以这个问题应该可以用任何一种语言来回答。

我给自己布置的任务是编写一个函数,构造一个从 1 到 n 的整数列表。 例如,list(7) 应返回 [1,2,3,4,5,6,7]。 O(n) 的解决方案将是理想的。

在线性时间内反向构造一个列表(即 [n,n-1,..,1])很容易:

fun list 1 = 1::nil
|   list n = n::list(n-1);

我尝试构造一个向前的列表是 O(n^2),因为追加操作是线性的。

fun list 1 = 1::nil
|   list n = list(n-1) @ n::nil;

我的下一个尝试是从 nil 开始,将 n 附加到前面,然后向后递归到 1,从尾到前(从右到左)构建一个列表。但它根本不起作用。

fun list n = (if n = 1
              then 1
              else list(n-1) :: n) :: nil;

有些事情让我觉得我需要一个辅助函数来构建要在递归中使用的未终止列表,但我被难住了。

This is not homework. I'm learning Standard ML on my own. I know a bit of Scheme, too, so this question ought to be answerable in either language.

My self-imposed assignment is to write a function that constructs a list of integers from 1 to n. For example, list(7) should return [1,2,3,4,5,6,7]. An O(n) solution would be ideal.

It's easy to construct a list in reverse (i.e., [n,n-1,..,1]) in linear time:

fun list 1 = 1::nil
|   list n = n::list(n-1);

My attempt to construct a list going forward is O(n^2) because the append operation is linear.

fun list 1 = 1::nil
|   list n = list(n-1) @ n::nil;

My next attempt was to build a list from the end to the front (right to left) by starting with the nil, attaching n to the front, and recursing backwards to 1. But it didn't work at all.

fun list n = (if n = 1
              then 1
              else list(n-1) :: n) :: nil;

Something makes me think I need a helper function that builds un-terminated lists to be used in the recursion, but I'm stumped.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

相守太难 2024-07-27 07:51:36

使用 基础库

fun list n = List.tabulate (n, fn x => x + 1)

通过一个简单的累加器,

val list =
    let fun list' k 0 = k
          | list' k n = list' (n::k) (n-1)
    in list' nil end

这会从尾部开始构建一个列表。 如果您考虑减少,

   list 5
=> list' nil 5
=> list' (5::nil) 4
=> list' (4::5::nil) 3
=> list' (3::4::5::nil) 2
=> list' (2::3::4::5::nil) 1
=> list' (1::2::3::4::5::nil) 0
=> [1, 2, 3, 4, 5]

或者,

有些事情让我觉得我需要一个辅助函数来构建要在递归中使用的未终止列表,但我被难住了。

未终止列表的表示是一个接受列表并返回列表的函数:例如,要表示 10::_,您可以使用 fn x =>; 10::x

fun list n =
    let fun list' m k = if m > n then k nil else
                        list' (m+1) (fn x => k (m::x))
    in list' 1 (fn x => x) end

再次,如果您考虑减少,

   list 5
=> list' 1 (fn x => x)
=> list' 2 (fn x => (fn x => x) (1::x))
=> list' 3 (fn x => (fn x => (fn x => x) (1::x)) (2::x))
=> list' 4 (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x))
=> list' 5 (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x))
=> list' 6 (fn x => (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x)) (5::x))
=> (fn x => (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x)) (5::x)) nil
=> (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x)) (5::nil)
=> (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::5::nil)
=> (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::4::5::nil)
=> (fn x => (fn x => x) (1::x)) (2::3::4::5::nil)
=> (fn x => x) (1::2::3::4::5::nil)
=> [1, 2, 3, 4, 5]

在这种情况下,可以对算法进行结构化,使普通数据结构足以满足累加器的要求,但使用延续作为累加器是一种非常强大且有用的技术,不应被忽视。

Using the Basis Library,

fun list n = List.tabulate (n, fn x => x + 1)

With a simple accumulator,

val list =
    let fun list' k 0 = k
          | list' k n = list' (n::k) (n-1)
    in list' nil end

This builds a list starting from the tail end. If you think of the reductions,

   list 5
=> list' nil 5
=> list' (5::nil) 4
=> list' (4::5::nil) 3
=> list' (3::4::5::nil) 2
=> list' (2::3::4::5::nil) 1
=> list' (1::2::3::4::5::nil) 0
=> [1, 2, 3, 4, 5]

Alternatively,

Something makes me think I need a helper function that builds un-terminated lists to be used in the recursion, but I'm stumped.

A representation of an unterminated list is a function which takes a list and returns a list: for example, to represent 10::_, you could use fn x => 10::x.

fun list n =
    let fun list' m k = if m > n then k nil else
                        list' (m+1) (fn x => k (m::x))
    in list' 1 (fn x => x) end

Once again, if you think of the reductions,

   list 5
=> list' 1 (fn x => x)
=> list' 2 (fn x => (fn x => x) (1::x))
=> list' 3 (fn x => (fn x => (fn x => x) (1::x)) (2::x))
=> list' 4 (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x))
=> list' 5 (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x))
=> list' 6 (fn x => (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x)) (5::x))
=> (fn x => (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x)) (5::x)) nil
=> (fn x => (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::x)) (5::nil)
=> (fn x => (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::x)) (4::5::nil)
=> (fn x => (fn x => (fn x => x) (1::x)) (2::x)) (3::4::5::nil)
=> (fn x => (fn x => x) (1::x)) (2::3::4::5::nil)
=> (fn x => x) (1::2::3::4::5::nil)
=> [1, 2, 3, 4, 5]

In this case, the algorithm can be structured such that an ordinary data structure suffices for the accumulator, but using a continuation as an accumulator is a very powerful and useful technique that should not be overlooked.

孤独难免 2024-07-27 07:51:36

一种经典的方法是以相反的顺序构建它,然后反转它。 这是 O(n) 的两倍,当然也是 O(n)。

One classic approach is to build it in reverse order, then reverse it. That's two times O(n), which is of course just as O(n).

︶葆Ⅱㄣ 2024-07-27 07:51:36

这是一个解决方案:

fun list n =
  let
    fun f 1 m = m::nil
    |   f n m = m::f (n-1) (m+1)
  in
    f n 1
  end;

Here's a solution:

fun list n =
  let
    fun f 1 m = m::nil
    |   f n m = m::f (n-1) (m+1)
  in
    f n 1
  end;
GRAY°灰色天空 2024-07-27 07:51:36

这是使用辅助函数和支持尾递归的累加器的版本:

fun list n =
  let
    fun aux i acc = 
      if i > 0
      then aux (i-1) (i::acc)
      else acc
  in
    aux n nil
  end;

Here's a version using a helper function and a tail-recursion-enabling accumulator:

fun list n =
  let
    fun aux i acc = 
      if i > 0
      then aux (i-1) (i::acc)
      else acc
  in
    aux n nil
  end;
空城仅有旧梦在 2024-07-27 07:51:36

对于此类列表问题,解决更普遍的问题通常更容易。

如何构建一个包含整数i的列表,使得n <= i <= m按顺序排列?

该解决方案具有基本情况和归纳步骤:

  • If n > m,列表为空。

  • 如果n <= m,解决方案是写n,然后是问题的解决方案n+1 <= i <= m

这种观点可以快速生成清晰、简洁的 ML 代码(经过测试):

fun range n m = if n > m then [] else n :: range (n+1) m
fun list n = range 1 n

With list problems like these, it is often easier to solve a more general problem.

How do I build a list containing the integers i such that n <= i <= m, in order?

The solution has a base case and an induction step:

  • If n > m, the list is empty.

  • If n <= m, the solution is to write n followed by the solution to the problem n+1 <= i <= m.

This view leads quickly to clear, concise ML code (tested):

fun range n m = if n > m then [] else n :: range (n+1) m
fun list n = range 1 n
羅雙樹 2024-07-27 07:51:36
(define (iota n)
  (let f ((i n)(a '())
    (if (zero? i)
        (reverse a)
        (f (- i 1) (cons i a)))))
(define (iota n)
  (let f ((i n)(a '())
    (if (zero? i)
        (reverse a)
        (f (- i 1) (cons i a)))))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文