【问题标题】:Creating an n-sized permutation with scheme using only basic constructs仅使用基本结构创建具有方案的 n 大小排列
【发布时间】:2010-11-14 22:36:42
【问题描述】:

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

【问题讨论】:

  • 没有defineletrec(或至少lambda)?
  • “有没有可能...” 鉴于您的允许构造集是图灵完备的,任何事情都是可能的

标签: permutation


【解决方案1】:

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

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

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

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

您还需要一个函数来连接列表。这也可以递归实现,没有太多麻烦。

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

现在定义一个创建 n 大小排列的函数。这个函数应该接受数字n 和一个列表。如果n 为0,它应该返回空列表。否则,它应该为列表中的每个项目x 递归调用自身,其中(- n 1) 作为n 的新值,并且从列表中删除x 的结果作为列表的新值。那么递归调用的结果应该被连接起来。

【讨论】:

    【解决方案2】:

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

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

    seq 构建一个包含数字序列的列表。例如 (seq 0 3) -> (0 1 2 3)。 列表中的元素 (numbers)insert 函数中用于将 carItem 插入到 'cdr'列表。

    (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)) 
          )
      )
    

    insert 生成一个列表,其中 carItem 插入到 cdrList 的第“n”个位置。例如,(insert '(b c) 0 'a) -> '(a b c) 和 (insert '(b c) 2 'a) -> '(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))))
    

    最后,对于主函数permute,它以递归的方式使用insertseq。 例如,当 plist = '(b,c) lambda eval 为以下内容:

    ; (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))))]))
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-26
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多