计划中的子列表回文

时间:2013-11-01 21:18:48

标签: lisp scheme

我有一个工作的回文,它通过乘坐汽车并将其与反向汽车进行比较,为单个列表中的原子返回true / false。然后用cdr抛出第一个和最后一个(反向(cdr list))。

我想让它与子列表中的原子一起使用,以便'(a b)c(b a))将返回true。

我正在尝试首先检查汽车是否是列表,如果是,请比较caar和反向caar,直到它为null然后继续。
我得到“对象#f不适用”。

(DEFINE (pdrome lst)
  (cond
    ; ((NOT (LIST? lst)) DISPLAY "USAGE: (palindrome [list])" )
    ((null? lst) #t)
     ((null? (cdr lst)) #t)

     ((LIST? (car lst))
       ((null? (car lst) ) () )
       ((null? (cdr lst) ) () )
    ((equal? (caar lst) (caar (reverse lst)))
    (pdrome (cdar (reverse(cdar lst))))))

     ((equal? (car lst) (car(reverse lst))) 
      (pdrome (cdr (reverse (cdr lst)))))

        (else #F) ) )

我也试过这样做,所以它不会嵌套,但我无法解决这个问题。任何提示或提示赞赏。谢谢!

(LIST? car lst)  
palindrome (append (caar lst) (caar (reverse lst)))

2 个答案:

答案 0 :(得分:1)

这是您的代码,缩进正确:

(DEFINE (pdrome lst)
  (cond
   ((null? lst) #t)
   ((null? (cdr lst)) #t)
   ((LIST? (car lst))
    ((null? (car lst))())
    ((null? (cdr lst))())
    ((equal? (caar lst) (caar (reverse lst)))
     (pdrome (cdar (reverse(cdar lst))))))
   ((equal? (car lst) (car(reverse lst))) 
    (pdrome (cdr (reverse (cdr lst)))))
   (else #F)))

请注意第三个条款何时不会结束?或者您可能在检查(equal? (caar lst) (caar (reverse lst)))之前尝试检查几个条件。

当你调用(pdrome '((a b) c (b a)))时,它会到达(LIST? (car lst))为真的点,因此它会评估该子句中的其余代码。那就是:

    ((null? (car lst))())
    ((null? (cdr lst))())
    ((equal? (caar lst) (caar (reverse lst))

让我们看看第一个:((null? (car lst))())。这是如何评估的?它是一个包含两个元素的列表,因此评估第一个:(null? (car lst))。评估结果为#F。然后,我们有(#F ())#F处于功能位置(列表中第一个被评估为代码的东西),但不是函数。所以我们得到错误Object #f is not applicable

基本上,cond的每个条款都是这样的:

(condition form1 form2 ...)

可以有任意数量的表格,包括零。

那么让我们来看看你的单一条款

((LIST? (car lst))
 ((null? (car lst))())
 ((null? (cdr lst))())
 ((equal? (caar lst) (caar (reverse lst)))
  (pdrome (cdar (reverse(cdar lst))))))

以下是条件:

(LIST? (car lst))

以下是表格。其中有三个:

 ((null? (car lst))())
 ((null? (cdr lst))())
 ((equal? (caar lst) (caar (reverse lst)))
  (pdrome (cdar (reverse(cdar lst))))))

如果条件为真(即(car lst)本身就是一个列表),那么你想做什么?

我要退后一步,按照我手工制作算法来布置算法。

在我们不再有列表之前,切断第一件事,最后一件事,看看第一件事是否与最后一件相同。如果这些东西本身就是列表,那么倒转最后一个。然后继续在列表的中间(即没有第一个或最后一个元素的列表)执行此操作,直到我们最终得到一个空列表或一个只包含一个内容的列表。

现在让我们写一些代码:

(define (palindrome lst)
  (if (null? lst)
      #t
      (let ((first-element (car lst))
            (last-element (car (reverse lst))))
        (and (equal? first-element
                     (if (list? last-element)
                         (reverse last-element)
                         last-element))
             (palindrome (get-middle lst))))))

(define (get-middle lst)
  (if (null? (cdr lst))
      '()
      (reverse (cdr (reverse (cdr lst))))))

> (palindrome '())
#t
> (palindrome '(a))
#t
> (palindrome '((a)))
#t
> (palindrome '((a) b))
#f
> (palindrome '((a) b (a)))
#t
> (palindrome '((a b) c (b a)))
#t  

请注意,此代码与书面算法略有不同。当它到达包含一个元素的列表时(例如,它被称为(palindrome '(a)),它将获得第一个元素'a,最后一个元素'a,确保他们相等,然后拨打(get-middle '(a))'()。然后(palindrome '())#f,这样我们就会很好。

答案 1 :(得分:0)

最简单的方法是使用递归反转列表的deep-reverse过程。

(define (deep-reverse l) 
  (if (list? l) 
      (reverse (map deep-reverse l)) 
      l))

了解它与内置反向的比较:

-> (reverse '((a b) c (d e)))
'((d e) c (a b))
-> (deep-reverse '((a b) c (d e)))
'((e d) c (b a))

所以回文只是一个相同的列表?它的深度逆转:

(define (pdrome? lst)
  (equal? lst (deep-reverse lst)))