使用仅使用基本结构的方案创建n大小的排列

时间:2010-11-14 22:36:42

标签: permutation

是否可以仅使用基本方案构造生成列表的n大小的排列?

2 个答案:

答案 0 :(得分:0)

使用define你可以这样做(没有define答案是否定的,因为你需要使用递归):

首先定义一个获取列表和值列表的函数,并返回列表列表,其中给定项目已添加到原始列表列表中的每个列表中。

这可以通过编写一个简单的递归函数来完成,该函数使用cons将项目添加到第一个列表(使用car获取第一个列表),然后再次使用consprepend扩展列表到在其他列表上调用函数的结果(即在列表列表的cdr上)。如果列表为空(因此没有carcdr),则返回空列表。

您还需要一个从列表中删除给定项目的函数。这也可以通过定义一个带有项和列表的简单递归函数来完成。在每一步,如果递归调用的结果不等于要删除的项,则应将给定列表的“car”添加到递归调用的结果之前。如果它相等,则应直接返回递归调用的结果。

此外,您还需要一个连接列表的函数。这也可以递归实现而不会有太多麻烦。

然后定义一个给定列表列表的函数,一个项调用前一个函数,并将项目和每个子列表作为参数。

现在定义一个创建n个大小排列的函数。此函数应采用数字n和列表。如果n为0,则应返回空列表。否则,它应该为列表中的每个项目x递归调用自身(- n 1)作为n的新值以及从列表中删除x作为新值的结果列表。然后应该连接递归调用的结果。

答案 1 :(得分:0)

这是对Rosetta中的代码的解释,但是,我已经更改了变量名称以使其更具可读性,并添加了我对下面代码的解释。我确实检查过代码是否在DrRacket中有效,而且确实如此。

在定义 permute 之前,需要两个辅助函数,即 seq insert

seq 会构建一个包含一系列数字的列表。例如(seq 0 3) - &gt; (0 1 2 3)。 列表中的元素(数字)用于插入功能,以便在 cdr <中的各个位置插入 carItem / strong>'list。

(define (seq start end) 
  (if (= start end) 
      (list end)    ; if start and end are the same number, we are done
      (cons start (seq (+ start 1) end)) 
      )
  )

插入会生成一个列表,其中 carItem 插入 cdrList 的第“n”位置。例如,(insert'(b c)0'a) - &gt; '(a b c)和(insert'(b c)2'a) - &gt; '(b c a)。

(define (insert cdrList n carItem)
  (if (= 0 n)
      (cons carItem cdrList) ; if n is 0, prepend carItem to cdrList
      (cons (car cdrList)  
            (insert (cdr cdrList) (- n 1) carItem))))

最后,对于主要功能置换,它以递归方式使用插入 seq 。 例如,当plist ='(b,c)时,lambda将证实为:

; (map (lambda (n)
;    (insert '(b c) n 'a))
;    '(0 1 2)) -> output of seq function given n = 2, which is length of '(b c)
; '((a b c) (b a c) (b c a)) ---> will be the output

(define (permute mylist)
  (if (null? mylist)
      '(())
      (apply append (map (lambda (plist)
                           (map (lambda (n)
                                  (insert plist n (car mylist)))
                                (seq 0 (length plist))))
                         (permute (cdr mylist))))))

(permute '(a b c))

如果上面的嵌套的lambdas 使你的头旋转(这对我来说),请在下面找到,恕我直言,一个更具可读性的“定义”版本,感谢Matthias Felleisen:

(define (permute mylist)
  (cond 
    [(null? mylist) '(())]
    [else 
      (define (genCombinationsFor plist)
      (define (combineAt n) (insert plist n (car mylist)))
        (map combineAt (seq 0 (length plist))))
        (apply append (map genCombinationsFor (permute (cdr mylist))))]))