Scheme上每个级别的原子数

时间:2012-10-09 13:09:20

标签: lisp scheme

请帮助我做一个关于该计划的简单练习。

  

写入函数,返回每个级别的原子数   名单。例如:

     

(a(b(c(d e(f)k 1 5)e))) - > ((11)(2 1)(3 2)(4 5)(5 1))

我的解决方案:

(define (atom? x)
  (and (not (pair? x)) (not (null? x))))
(define (count L)
  (cond ((null? L) 0)
        ((pair? (car L))
         (count (cdr L)))
        (else
         (+ 1 (count (cdr L))))))
(define (fun L level)
  (cons 
   (list level (count L))
   (ololo L level)))
(define (ololo L level)
  (if (null? L)
      '()
      (if (atom? (car L))
          (ololo (cdr L) level)            
          (fun (car L) (+ level 1)))))
(fun '(a (b (c (d e (f) k 1 5) e))) 1)

它工作正常,但没有正确回答此列表:

(a (b (c (d e (f) (k) 1 5) e)))

是:

((1 1) (2 1) (3 2) (4 4) (5 1))

但我们假设'f'和'k'在一个级别上,答案必须是:

((1 1) (2 1) (3 2) (4 4) (5 2))

我应该如何编辑代码才能使其正常工作?


UPD(29.10.12): 我的最终解决方案:

(define A '(a (b (c (d e (f) k 1 5) e))))

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

(define (unite L res)
  (if (null? L) (reverse res)
      (unite (cdr L) (cons (car L) res))))

(define (count-atoms L answ)
  (cond ((null? L) answ)
        ((pair? (car L))
         (count-atoms (cdr L) answ))
        (else
         (count-atoms (cdr L) (+ answ 1)))))

(define (del-atoms L answ)   
  (cond ((null? L) answ)
        ((list? (car L))
         (begin
         (del-atoms (cdr L) (unite (car L) answ))))
        (else
         (del-atoms (cdr L) answ))))

(define (count L)
(define (countme L level answ)
  (if (null? L)  (reverse answ)
      (countme (del-atoms L '()) (+ level 1) (cons (cons level (cons (count-atoms L 0) '())) answ))))
  (countme L 1 '()))

(count A)

你能说些什么呢?

2 个答案:

答案 0 :(得分:2)

如果你这样做,你知道你得到了什么吗?

(fun '(a (b (c (d e (f) k 1 5) e)) (a (b (c)))) 1)

你明白了:

((1 1) (2 1) (3 2) (4 5) (5 1))

我在右侧添加的整个额外嵌套结构已被忽略。这就是为什么......

你的函数的每次递归都会做两件事:

  1. 计算当前“等级”的所有原子
  2. 向下移动水平,直到找到一对(表达式,而不是原子)的表达式
  3. 一旦找到嵌套对,就会调用它。等等

    有趣从第一个嵌套对返回时, oLoLo 会发生什么?为什么,它回来了!它确实继续沿着列表寻找另一个。

    您的功能永远不会找到任何级别的第一个列表。如果确实如此,你会做什么从第一个列表到第二个列表添加计数?您需要仔细考虑如何通过包含多个嵌套列表的列表完全重复,以了解如何在每个级别保留信息。这样做的方法不止一种,但你还没有找到任何一种方法。

答案 1 :(得分:0)

请注意,根据您的实现,此处使用的库可能需要以其他方式导入。找到必须导入的方式以及要使用的函数的确切名称可能非常困难。有些人会将其改为filterreduce-leftrequire-extension可能是也可能不是Guile特有的,我真的不知道。

(require-extension (srfi 1))
(define (count-atoms source-list)
  (define (%atom? x) (not (or (pair? x) (null? x))))
  (define (%count-atoms source-list level)
    (if (not (null? source-list))
        (cons (list level (count %atom? source-list))
                (%count-atoms (reduce append '()
                       (filter-map
                        (lambda (x) (if (%atom? x) '() x))
                        source-list)) (1+ level))) '()))
  (%count-atoms source-list 1))

当然,正如我之前提到的,最好用哈希表来做这件事。使用列表执行此操作可能会产生一些教学效果。但是我非常强烈地反对教学效果,这些教学效果会让你写出糟糕的代码。