首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >麻省理工学院中的Pascal三角形

麻省理工学院中的Pascal三角形
EN

Code Review用户
提问于 2016-11-18 13:00:54
回答 2查看 1.7K关注 0票数 1

正如源文件名称(ex1.12.scm)所建议的那样,我刚刚开始通过阅读SICP来学习麻省理工学院的方案。在练习1.12中,我被要求“通过递归过程计算Pascal三角形的元素”。为了好玩和额外的练习,我写了一个程序打印整个三角形。(我花了几分钟打印一个帕斯卡三角形,花了几个小时美化它:/)

代码语言:javascript
运行
复制
(define (pascal x)
  (define (pascal-iter m n max-len)
    (cond ((and (> m 0) (> n 0))
             (pascal-iter m (- n 1) max-len)       
             (beauti-print (pascal-item m n) max-len))
          ((= n 0) (pascal-iter (- m 1) (- m 1) max-len)
                   (display "\n")
                   (print-space (* (- x m) max-len)))
          ((= m 0) "Done")))
  (define (pascal-item m n)
    (cond ((= n 1) 1)
          ((= n m) 1)
          (else (+ (pascal-item (- m 1) (- n 1))
                   (pascal-item (- m 1) n)))))
  (define (beauti-print item max-len)
    (print-space (floor (- max-len
                       (/ (num-of-digit item) 2))))
    (display item)
    (print-space (ceiling (- max-len
                         (/ (num-of-digit item) 2)))))
  (define (num-of-digit n)
    (+ (floor (/ (log n) (log 10))) 1) )
  ;; (print-space 1)   -> " "
  ;; (print-space 1.5) -> "  "
  (define (print-space n)
    (cond ((> n 0) (display " ")
                (print-space (- n 1)))
          (else (display ""))))
  (pascal-iter x x (num-of-digit (pascal-item x (/ x 2)))))

(pascal 12)

这是输出:

代码语言:javascript
运行
复制
;Loading "ex1.12.scm"...

                                   1   
                                1     1   
                             1     2     1   
                          1     3     3     1   
                       1     4     6     4     1   
                    1     5     10    10    5     1   
                 1     6     15    20    15    6     1   
              1     7     21    35    35    21    7     1   
           1     8     28    56    70    56    28    8     1   
        1     9     36    84   126   126    84    36    9     1   
     1     10    45   120   210   252   210   120    45    10    1   
  1     11    55   165   330   462   462   330   165    55    11    1   
;... done

它的一个缺点是显而易见的:递归非常昂贵。事实上,(pascal 15)会在我的机器上生产;Aborting!: maximum recursion depth exceeded

但是,在回答这个问题时,请不要过于强调性能相关的问题,因为我认为,就目前而言,好的编程习惯的形式比优化算法更重要。因此,请关注可读性、代码样式等。

EN

回答 2

Code Review用户

回答已采纳

发布于 2016-11-21 05:59:08

将您的关注点分隔开,

一个对设计好的软件至关重要的设计原则是“分离关注点”。换句话说,每个功能都应该关注做一件事,而且只做一件事。

如果您后退一步,查看一下pascal函数,您将看到它正在尝试同时执行两项任务:

  1. 计算Pascal三角
  2. 漂亮的打印三角形

你可以把这些顾虑分开。

让我们从pascal函数开始。它应该只计算三角形中的值。它应该返回一个“行”列表,其中一行表示一个数字列表。

所以我们可以使用pascal来计算一个数字列表。现在我们想把这张清单打印出来。我们可以在一个函数中完成这一切(这没有什么问题)。但是如果我们小心的话,我们可以使事情变得更通用(从而可重用)。我们可以组成漂亮的打印三角形如下:

  • 格式化每一行。这涉及到获取数字列表并返回该行的字符串表示形式。
  • 对着一排排。基本上,用空格填充每个字符串。
  • 打印行。取下字符串并将它们分别打印在不同的行上。

我们可以定义函数format-rowcenter-linesprint-lines来处理这些任务。现在我们可以定义一个函数pretty-print-pascal,它将这些函数组合在一起:

代码语言:javascript
运行
复制
(define pretty-print-pascal (x)
  (print-lines (center-lines (map format-row (pascal x)))))
票数 4
EN

Code Review用户

发布于 2016-11-21 03:15:24

pascal-item的次级定义是在1.12练习中所要求的。但是,它完全不适合计算X行的整个三角形。没有适当的数据结构(列表、向量、哈希表.)可怜的pascal-item必须做所有的工作(而缺少记忆必须比实际需要的还要多很多次)

没有数据结构也迫使您将打印逻辑与三角形的一步一步的计算混为一谈,这虽然聪明,但它有点难以理解,而且很难单独使用。

我的建议是在书中继续前进,到那时,这一切将变得更加清晰。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/147418

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档