Lisp 每个级别上的原子数,方案

Lisp 每个级别上的原子数,方案,lisp,scheme,Lisp,Scheme,请帮我做一个关于这个计划的简单练习 Write函数,该函数返回 列表例如: (a(b(c(def)k15)e))–>((11)(21)(32)(45)(51)) 我的解决方案: (define (atom? x) (and (not (pair? x)) (not (null? x)))) (define (count L) (cond ((null? L) 0) ((pair? (car L)) (count (cdr L))) (el

请帮我做一个关于这个计划的简单练习

Write函数,该函数返回 列表例如:

(a(b(c(def)k15)e))–>((11)(21)(32)(45)(51))

我的解决方案:

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

但我们假设‘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)

对此,你能说些什么?

你知道如果你运行它会得到什么吗

(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))
我在右侧添加的整个额外嵌套结构已被忽略。这就是为什么

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

  • 计算当前“级别”的所有原子数
  • 向下移动,直到找到一个成对的s表达式(不是原子)
  • 一旦它找到一个嵌套对,它就会调用它自己。等等

    fun从第一个嵌套对返回时,oLoLo中会发生什么?哎呀,它回来了!它确实继续在列表中查找另一个


    您的函数在任何级别都不会找到超过第一个列表的内容。如果是这样的话,你会怎么做呢?把第一个列表中该级别的计数添加到第二个列表中?您需要仔细考虑如何在包含多个嵌套列表的列表中完全重复出现,以及如何在每个级别保留信息。有多种方法可以实现此目的,但您尚未了解其中任何一种。

    请注意,根据您的实现,此处使用的库可能需要以其他方式导入。可能很难找到导入它的方式以及要使用的函数的确切名称。有些人会将其作为
    过滤器
    左减
    <代码>需要扩展可能是也可能不是特定于欺诈,我真的不知道

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

    当然,正如我前面提到的,最好使用哈希表。使用列表可能会产生一些教育效果。但我强烈反对说教式的效果,这种效果会让你编写出本质上糟糕的代码。

    我不知道如何在scheme中使用哈希表。此时此刻;)关于您的设计,还有一些其他方面:将初始级别指定给顶级函数是笨拙的,并且会导致错误;这是一个应该隐藏的内部实现细节(除非您真的想让用户选择从0或1开始)。创建一个函数(比如levelcount),只需将列表作为参数,声明其中的所有帮助函数,并让它将1(或0)传递给fun的初始调用这不是Guile特定的,但Guile和Gauche是我所知道的唯一支持它的开箱即用的实现。谢谢!很好的例子,我会试着理解并自己做:)谢谢,我已经意识到我的错误了。现在我需要考虑一下。我只是一个新手方案程序员。这是我学习函数式编程的第一步。再次感谢。对于新手来说,这是一个相对复杂的问题。你能回顾一下我的新解决方案吗?请:-)
    (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))