【问题标题】:Scheme: given a list of lists and a permutation, permuteScheme:给定一个列表列表和一个排列,permute
【发布时间】:2014-10-12 18:28:36
【问题描述】:

我正在为我的编程范式考试练习并解决问题集,我遇到了这个问题。这是递归加入列表后的第一个问题,所以我想有一个优雅的递归解决方案。

我得到了一个列表列表和一个排列。我应该排列每个列表,包括具有指定排列的列表列表。

举个例子:

->(permute '((1 2 3) (a b c) (5 6 7)) '(1 3 2))
->((1 3 2) (5 7 6) (a c b))

我什至不知道如何开始。我需要在递归解释中制定问题才能解决它,但我不知道如何解决。

【问题讨论】:

  • 我最大的麻烦其实是不知道 list-ref 函数。而且我没有想到它是一个简单的函数,具有简单的实现。

标签: recursion functional-programming scheme permutation


【解决方案1】:

好吧,让我们看看如何解决这个问题。我们得到一个列表列表和一个数字列表,我们希望根据数字列表指定的顺序对每个列表进行排序:

=>(permute '((1 2 3) (4 5 6)) '(3 2 1))
'((3 2 1) (6 5 4))

我们可以看到列表列表中的每个列表都可以单独处理,它们的解决方案彼此无关。所以我们可以有一个帮助器permute1 来处理一个列表的情况,然后使用map 将此函数应用于每个列表(每次都具有相同的顺序):

(define (permute lists ordering)
  (map (lambda (xs) (permute1 xs ordering))
       lists))

(define (permute1 items ordering)
  ...)

现在,计算(permute1 '(4 5 6) '(3 2 1)),我们的意思是:

  1. 新列表的第一项将是items3rd 项,因为ordering 中的第一个数字是3
  2. 新列表中的其余项目将通过使用排序中的其余数字来确定。
  3. 如果排序是空列表,则返回空列表。

这形成了基本情况 (3)、递归情况 (1) 以及更深层次的递归步骤 (2)。所以我们的解决方案的草图如下所示:

(define (permute1 items ordering)
  (if (empty? ordering)
      '()
      (let ([next-item ???])
        (??? next-item
             (permute1 items (rest ordering))))))

其中???s 分别表示根据ordering 中的第一个数字获取项目并将该项目与计算的其余部分相结合。

【讨论】:

  • 第一???实际上是将汽车订购作为参数的 list-ref,第二个 ???是 cons ,其余排序是 cdr ordering 。 . .然后实际代码如下所示: (define (permute1 items ordering) (if (empty?ordering) '() (let ((next-item (list-ref items (- (car ordering) 1)))) (cons next -item (permute1 items (cdr ordering)))))) 非常感谢!
  • 对!虽然rest实际上是scheme的Racket方言中的一个真正的函数,你可以使用firstrest来代替carcdr。不过我不知道你在用什么方案来实现它。
  • MZScheme/PrettyBig,包括 R5RS
【解决方案2】:

这是另一种选择,使用高阶函数。这是用函数式语言思考解决方案的惯用方式 - 我们将问题拆分为子问题,使用现有程序解决每个问题,最后我们组成答案:

(define (atom? x)
  (and (not (null? x))
       (not (pair? x))))

(define (perm lst order)
  (foldr (lambda (idx acc)
           (cons (list-ref lst (sub1 idx)) acc))
         '()
         order))

(define (permute lst order)
  (if (atom? lst)
      lst
      (perm (map (lambda (x) (permute x order)) lst)
            order)))

我们首先定义atom?,一个通用谓词和perm,一个帮助器,它将根据其参数之一中指定的顺序对任何给定列表重新排序。它使用foldr 构建输出列表并使用list-ref 访问列表中的元素,因为它的索引从0 开始(这就是我们从每个索引中减去一个的原因)。

permute 主函数负责(递归)将perm 映射到任意嵌套输入列表的每个元素上,因此我们可以获得所需的结果:

(permute '((1 2 3) (a b c) (5 6 7)) '(1 3 2))
=> '((1 3 2) (5 7 6) (a c b))

【讨论】:

  • 谢谢,这对我很有用。我需要将我对问题的看法从递归转向高阶函数,这样会更清晰、更简单。
【解决方案3】:

举个例子:

(permute ('(1 2 3) '(a b c) '(5 6 7)) '(1 3 2))
((1 3 2) (5 7 6) (a c b))

您给出的语法不正确,会导致错误,但您的意思很清楚。你想要那个

(permute '((1 2 3) (a b c) (5 6 7)) '(1 3 2))
;=> ((1 3 2) (5 7 6) (a c b))

现在,不清楚您是如何表示排列的。 '(1 3 2) 是排列,因为它有一些(基于 1 的)索引,并指示重新排列元素的方式,还是因为它实际上是第一个元素的排列第一个列表的列表?例如,会

(permute '((x y z) (a b c) (5 6 7)) '(1 3 2))
;=> ((x z y) (5 7 6) (a c b))

也工作?我会假设它会,因为它会使问题变得更容易。

我什至不知道如何开始。我需要将问题表述为 递归解释能够解决它,但我想不通 怎么做。

您需要编写一个可以获取索引列表的函数,并返回一个执行置换的函数。例如,。

(define (make-permutation indices)
  …)

这样

((make-permutation '(3 1 2)) '(a b c))
;=> (c a b)

你有一个,听起来你的 permute 功能很简单:

(define (permute lists indices)
  (let ((p (make-permutation indices)))
    (p (map p lists))))

这将处理您在示例中给出的情况,因为 (map p lists) 将返回 ((1 3 2) (abc) (5 7 6)),然后调用 p 将返回 ((1 3 2) (5 7 6) (acb))。如果您需要能够处理更深的嵌套列表,则需要实现递归映射函数。

【讨论】:

    【解决方案4】:

    这是我的看法,似乎比前面的例子要短:

    (define (permute lst ord)
      (define ord-1 (map sub1 ord)) ; change from 1-based to 0-based indexes
      (define (perm elts)           ; recursive sub-procedure
        (if (list? elts)
            (map perm (map (curry list-ref elts) ord-1)) ; list -> recurse
            elts))                                       ; else return unchanged
      (perm lst))                   ; initial call
    

    测试

    > (permute '((1 2 3) (a b c) (5 6 7)) '(1 3 2))
    '((1 3 2) (5 7 6) (a c b))
    > (permute '((1 (i permute did) 3) (a b (scheme cool is)) (5 6 7)) '(1 3 2))
    '((1 3 (i did permute)) (5 7 6) (a (scheme is cool) b))
    

    【讨论】:

      猜你喜欢
      • 2011-02-03
      • 1970-01-01
      • 2021-01-04
      • 1970-01-01
      • 1970-01-01
      • 2017-03-06
      • 1970-01-01
      • 2020-08-16
      • 1970-01-01
      相关资源
      最近更新 更多