【问题标题】:Racket: How can I fix my code so that it will return all the flipped pairs that is missing?球拍:我怎样才能修复我的代码,以便它返回所有丢失的翻转对?
【发布时间】:2020-11-13 01:50:46
【问题描述】:

这个函数应该返回 L 的对称闭包。 例子:

(Symmetric-Closure'((a a) (a b) (b a) (b c) (c b))) ---> '((a a) (a b) (b a) (b c) (c b))
(Symmetric-Closure'((a a) (a b) (a c))) ---> '((a a) (a b) (a c) (b a)(c a))
(Symmetric-Closure'((a a) (b b))) ---> '((a a) (b b))
(Symmetric-Closure'())---> '() 

这是我在 Racket 中所拥有的

(define (Symmetric-Closure L)
  ;Iterate over each pair in L
  (andmap (lambda (x)
             ;If the flipped pair does not exist in L, it will
             ;return L and the flipped pair that is missing. Otherwise, return L.
             (if(not(member (list (cadr x)(car x)) L))
                (cons (list (cadr x)(car x)) L)
                (append L)))
           L))

如何修复我的代码,以便它返回所有丢失的翻转对 例如,我的代码只返回 L 和最后一个丢失的翻转对 (ca) 而不是 (b a) 和 (ca)

;this is wrong, it should return '((c a)(b a)(a a)(a b)(a c))
(Symmetric-Closure '((a a)(a b)(a c))-----> '((c a)(a a)(a b)(a c)) 
;this is correct
(Symmetric-Closure '((a a)(a b)(b a)(b c)(c b)))-----> '((a a)(a b)(b a)(b c)(c b)) 

【问题讨论】:

    标签: closures racket symmetric


    【解决方案1】:

    andmap 表示“map 使用此函数的列表,然后将and 组合在一起的结果。”在 Racket 中,每当您将and 任何值放在一起时,结果将是提供给它的最后一个值,或者是false。例如,如果value1value2 都不是false(and value1 value2) 的结果是value2(如果其中之一是false,则结果也是false)。由于您的lambda 生成的值永远不会是false,因此您的andmap 的结果将是最后一次调用它的lambda 表达式的值,在这种情况下,它可能是列表@987654337 @ 表示它在原始列表 L 中看到的 x 的最后一个值。这意味着 consed 的所有先前值根本不会影响结果。

    您可以将其修改为使用简单的map。但这会产生一个对列表,而不是你想要的对列表。所以最后你需要把它展平才能得到结果。

    (define (symmetric-closure L)
      ;Iterate over each pair in L
      (apply append
             (map (lambda (x)
                    ;If the flipped pair does not exist in L, it will
                    ;return L and the flipped pair that is missing. Otherwise, return L.
                    (if (not (member (list (cadr x) (car x)) L))
                        (list (list (cadr x) (car x)) x)
                        (list x)))
                  L)))
    

    需要注意的一点是,该算法会为原始列表中的每个元素调用member。检查列表中的成员资格是O(N),而您正在这样做N 次,这意味着该算法的复杂度是O(N²)。您应该能够更有效地执行此操作,例如使用hash set

    【讨论】:

    • 谢谢!你能解释一下“应用附加”是如何工作的吗?
    • apply 允许您将参数作为列表而不是直接传递给函数。例如。如果你有一个数字列表(list 1 2 3 4 5) 并且你想找到总和,你不能直接做(+ (list 1 2 3 4 5))(试试看)。但是你可以通过使用 apply 函数来做到这一点。 (apply + (list 1 2 3 4 5)。总而言之,+ 是一个接受数字作为参数的函数,apply 允许您在列表中提供这些数字。同样,append 是一个接受列表作为参数的函数,并且 apply 允许您在列表中提供这些列表。写下一些例子,你就会明白了。
    • @mindthief 我认为,当您可以将foldrconsappend 一起使用时,(apply append ...)map 相比几乎永远不会正确。如果需要,使用 foldr 还可以让您在同一步骤中进行过滤。
    • @RyanSchaefer 我不确定在这种情况下如何使用foldr。当我将map 更改为foldr 时,它会显示foldr: arity mismatch; the expected number of arguments does not match the given number expected: at least 3 given: 2 arguments...:
    • @RyanSchaefer 我觉得考虑到问题的具体情况,对foldr 的讨论超出了答案的范围。虽然我不会说有一种“正确”的方法可以做到这一点,但我鼓励您使用 fold 写出答案。我认为这将是一个有用的贡献:)
    猜你喜欢
    • 2023-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-03
    • 1970-01-01
    • 2018-03-26
    相关资源
    最近更新 更多