Skip to content

Instantly share code, notes, and snippets.

@yanfeng42
Created December 28, 2020 18:49
Show Gist options
  • Save yanfeng42/8eb1ff0b0636bd3594e99a7072c96aa9 to your computer and use it in GitHub Desktop.
Save yanfeng42/8eb1ff0b0636bd3594e99a7072c96aa9 to your computer and use it in GitHub Desktop.
SICP练习1.14. 使用 GrapViz 可视化 零钱问题的 递归计算步骤.
(define (count-change amount)
(cc amount 5 0)
)
(define (cc amount kinds-of-coins depth)
(define from-node (cc-node-depth amount kinds-of-coins depth))
(display (cc-node-depth-label amount kinds-of-coins depth))
(cond
((= amount 0) 1)
((or (< amount 0) (= kinds-of-coins 0)) 0)
(else (let ((to-node (cc-node-depth amount (- kinds-of-coins 1) (+ depth 1)))) (display (cc-link from-node to-node)))
(let ((to-node (cc-node-depth (- amount (first-denomination kinds-of-coins)) kinds-of-coins (+ depth 1)))) (display (cc-link from-node to-node)))
(+
;除第一种硬币之外的所有其他硬币的不同方式的数目.
(cc amount (- kinds-of-coins 1) (+ depth 1))
; 将现金 a - d 换成所有种类的硬币的不同方式的数目.
(cc (- amount (first-denomination kinds-of-coins)) kinds-of-coins (+ depth 1))
)
)
)
)
(define (first-denomination kinds-of-coins)
(cond
((= kinds-of-coins 1) 1)
((= kinds-of-coins 2) 5)
((= kinds-of-coins 3) 10)
((= kinds-of-coins 4) 25)
((= kinds-of-coins 5) 50)
)
)
(define (cc-node amount kinds-of-coins)
; (cc 11 5)
(string-append "(cc " (number->string amount) " " (number->string kinds-of-coins) ")")
)
(define (cc-node-depth amount kinds-of-coins depth)
(define node (cc-node amount kinds-of-coins))
; "[0] (cc 11 5)"
(string-append "\"[" (number->string depth) "] " node "\"")
)
(define (cc-node-depth-label amount kinds-of-coins depth)
(define node (cc-node amount kinds-of-coins))
; "[0] (cc 11 5)" [label="(cc 11 5)", ];
; "[15] (cc 0 1)" [label="(cc 0 1)",color=gray80];
(if (= amount 0)
(string-append "\"[" (number->string depth) "] " node "\" [label=\"" node "\",color=gray80];\n")
(string-append "\"[" (number->string depth) "] " node "\" [label=\"" node "\"];\n")
)
)
(define (cc-link from-node to-node)
; "[0] (cc 11 5)" -> "[1] (cc 11 4)";
(string-append from-node " -> " to-node ";\n")
)
@yanfeng42
Copy link
Author

count-change-13

https://codology.net/post/sicp-solution-exercise-1-14/ 有提到这种思路, 不过并没有给出 打印 gv dot 的具体方式.

这种 基于 GrapViz 来辅助理解 空间复杂度的解法, 让人很新奇, 也很使用. 后续必将成为一个 很强势的 基础技能.

特实现下 gv 的输出代码, 同时熟悉/温习下 gv 的基础语法.

如果想自己看效果的, 可以安装 VSCode 的 GrapViz 插件.

我自己打印了下 (count-change 13)

digraph G {
node [color = gray95,style=filled];
graph [ranksep=0.25];
node [color = gray95,style=filled,fontsize=9,shape=box, margin=.08, width=0, height=0 ];
edge [penwidth=.5, arrowsize=0.5];
"[0] (cc 13 5 )" [label="(cc 13 5 )"];
"[0] (cc 13 5 )" ->  "[1] (cc 13 4 )";
"[0] (cc 13 5 )" ->  "[1] (cc -37 5 )";
"[1] (cc 13 4 )" [label="(cc 13 4 )"];
"[1] (cc 13 4 )" ->  "[2] (cc 13 3 )";
"[1] (cc 13 4 )" ->  "[2] (cc -12 4 )";
"[2] (cc 13 3 )" [label="(cc 13 3 )"];
"[2] (cc 13 3 )" ->  "[3] (cc 13 2 )";
"[2] (cc 13 3 )" ->  "[3] (cc 3 3 )";
"[3] (cc 13 2 )" [label="(cc 13 2 )"];
"[3] (cc 13 2 )" ->  "[4] (cc 13 1 )";
"[3] (cc 13 2 )" ->  "[4] (cc 8 2 )";
"[4] (cc 13 1 )" [label="(cc 13 1 )"];
"[4] (cc 13 1 )" ->  "[5] (cc 13 0 )";
"[4] (cc 13 1 )" ->  "[5] (cc 12 1 )";
"[5] (cc 13 0 )" [label="(cc 13 0 )"];
"[5] (cc 12 1 )" [label="(cc 12 1 )"];
"[5] (cc 12 1 )" ->  "[6] (cc 12 0 )";
"[5] (cc 12 1 )" ->  "[6] (cc 11 1 )";
"[6] (cc 12 0 )" [label="(cc 12 0 )"];
"[6] (cc 11 1 )" [label="(cc 11 1 )"];
"[6] (cc 11 1 )" ->  "[7] (cc 11 0 )";
"[6] (cc 11 1 )" ->  "[7] (cc 10 1 )";
"[7] (cc 11 0 )" [label="(cc 11 0 )"];
"[7] (cc 10 1 )" [label="(cc 10 1 )"];
"[7] (cc 10 1 )" ->  "[8] (cc 10 0 )";
"[7] (cc 10 1 )" ->  "[8] (cc 9 1 )";
"[8] (cc 10 0 )" [label="(cc 10 0 )"];
"[8] (cc 9 1 )" [label="(cc 9 1 )"];
"[8] (cc 9 1 )" ->  "[9] (cc 9 0 )";
"[8] (cc 9 1 )" ->  "[9] (cc 8 1 )";
"[9] (cc 9 0 )" [label="(cc 9 0 )"];
"[9] (cc 8 1 )" [label="(cc 8 1 )"];
"[9] (cc 8 1 )" ->  "[10] (cc 8 0 )";
"[9] (cc 8 1 )" ->  "[10] (cc 7 1 )";
"[10] (cc 8 0 )" [label="(cc 8 0 )"];
"[10] (cc 7 1 )" [label="(cc 7 1 )"];
"[10] (cc 7 1 )" ->  "[11] (cc 7 0 )";
"[10] (cc 7 1 )" ->  "[11] (cc 6 1 )";
"[11] (cc 7 0 )" [label="(cc 7 0 )"];
"[11] (cc 6 1 )" [label="(cc 6 1 )"];
"[11] (cc 6 1 )" ->  "[12] (cc 6 0 )";
"[11] (cc 6 1 )" ->  "[12] (cc 5 1 )";
"[12] (cc 6 0 )" [label="(cc 6 0 )"];
"[12] (cc 5 1 )" [label="(cc 5 1 )"];
"[12] (cc 5 1 )" ->  "[13] (cc 5 0 )";
"[12] (cc 5 1 )" ->  "[13] (cc 4 1 )";
"[13] (cc 5 0 )" [label="(cc 5 0 )"];
"[13] (cc 4 1 )" [label="(cc 4 1 )"];
"[13] (cc 4 1 )" ->  "[14] (cc 4 0 )";
"[13] (cc 4 1 )" ->  "[14] (cc 3 1 )";
"[14] (cc 4 0 )" [label="(cc 4 0 )"];
"[14] (cc 3 1 )" [label="(cc 3 1 )"];
"[14] (cc 3 1 )" ->  "[15] (cc 3 0 )";
"[14] (cc 3 1 )" ->  "[15] (cc 2 1 )";
"[15] (cc 3 0 )" [label="(cc 3 0 )"];
"[15] (cc 2 1 )" [label="(cc 2 1 )"];
"[15] (cc 2 1 )" ->  "[16] (cc 2 0 )";
"[15] (cc 2 1 )" ->  "[16] (cc 1 1 )";
"[16] (cc 2 0 )" [label="(cc 2 0 )"];
"[16] (cc 1 1 )" [label="(cc 1 1 )"];
"[16] (cc 1 1 )" ->  "[17] (cc 1 0 )";
"[16] (cc 1 1 )" ->  "[17] (cc 0 1 )";
"[17] (cc 1 0 )" [label="(cc 1 0 )"];
"[17] (cc 0 1 )" [label="(cc 0 1 )",color=gray80];
"[4] (cc 8 2 )" [label="(cc 8 2 )"];
"[4] (cc 8 2 )" ->  "[5] (cc 8 1 )";
"[4] (cc 8 2 )" ->  "[5] (cc 3 2 )";
"[5] (cc 8 1 )" [label="(cc 8 1 )"];
"[5] (cc 8 1 )" ->  "[6] (cc 8 0 )";
"[5] (cc 8 1 )" ->  "[6] (cc 7 1 )";
"[6] (cc 8 0 )" [label="(cc 8 0 )"];
"[6] (cc 7 1 )" [label="(cc 7 1 )"];
"[6] (cc 7 1 )" ->  "[7] (cc 7 0 )";
"[6] (cc 7 1 )" ->  "[7] (cc 6 1 )";
"[7] (cc 7 0 )" [label="(cc 7 0 )"];
"[7] (cc 6 1 )" [label="(cc 6 1 )"];
"[7] (cc 6 1 )" ->  "[8] (cc 6 0 )";
"[7] (cc 6 1 )" ->  "[8] (cc 5 1 )";
"[8] (cc 6 0 )" [label="(cc 6 0 )"];
"[8] (cc 5 1 )" [label="(cc 5 1 )"];
"[8] (cc 5 1 )" ->  "[9] (cc 5 0 )";
"[8] (cc 5 1 )" ->  "[9] (cc 4 1 )";
"[9] (cc 5 0 )" [label="(cc 5 0 )"];
"[9] (cc 4 1 )" [label="(cc 4 1 )"];
"[9] (cc 4 1 )" ->  "[10] (cc 4 0 )";
"[9] (cc 4 1 )" ->  "[10] (cc 3 1 )";
"[10] (cc 4 0 )" [label="(cc 4 0 )"];
"[10] (cc 3 1 )" [label="(cc 3 1 )"];
"[10] (cc 3 1 )" ->  "[11] (cc 3 0 )";
"[10] (cc 3 1 )" ->  "[11] (cc 2 1 )";
"[11] (cc 3 0 )" [label="(cc 3 0 )"];
"[11] (cc 2 1 )" [label="(cc 2 1 )"];
"[11] (cc 2 1 )" ->  "[12] (cc 2 0 )";
"[11] (cc 2 1 )" ->  "[12] (cc 1 1 )";
"[12] (cc 2 0 )" [label="(cc 2 0 )"];
"[12] (cc 1 1 )" [label="(cc 1 1 )"];
"[12] (cc 1 1 )" ->  "[13] (cc 1 0 )";
"[12] (cc 1 1 )" ->  "[13] (cc 0 1 )";
"[13] (cc 1 0 )" [label="(cc 1 0 )"];
"[13] (cc 0 1 )" [label="(cc 0 1 )",color=gray80];
"[5] (cc 3 2 )" [label="(cc 3 2 )"];
"[5] (cc 3 2 )" ->  "[6] (cc 3 1 )";
"[5] (cc 3 2 )" ->  "[6] (cc -2 2 )";
"[6] (cc 3 1 )" [label="(cc 3 1 )"];
"[6] (cc 3 1 )" ->  "[7] (cc 3 0 )";
"[6] (cc 3 1 )" ->  "[7] (cc 2 1 )";
"[7] (cc 3 0 )" [label="(cc 3 0 )"];
"[7] (cc 2 1 )" [label="(cc 2 1 )"];
"[7] (cc 2 1 )" ->  "[8] (cc 2 0 )";
"[7] (cc 2 1 )" ->  "[8] (cc 1 1 )";
"[8] (cc 2 0 )" [label="(cc 2 0 )"];
"[8] (cc 1 1 )" [label="(cc 1 1 )"];
"[8] (cc 1 1 )" ->  "[9] (cc 1 0 )";
"[8] (cc 1 1 )" ->  "[9] (cc 0 1 )";
"[9] (cc 1 0 )" [label="(cc 1 0 )"];
"[9] (cc 0 1 )" [label="(cc 0 1 )",color=gray80];
"[6] (cc -2 2 )" [label="(cc -2 2 )"];
"[3] (cc 3 3 )" [label="(cc 3 3 )"];
"[3] (cc 3 3 )" ->  "[4] (cc 3 2 )";
"[3] (cc 3 3 )" ->  "[4] (cc -7 3 )";
"[4] (cc 3 2 )" [label="(cc 3 2 )"];
"[4] (cc 3 2 )" ->  "[5] (cc 3 1 )";
"[4] (cc 3 2 )" ->  "[5] (cc -2 2 )";
"[5] (cc 3 1 )" [label="(cc 3 1 )"];
"[5] (cc 3 1 )" ->  "[6] (cc 3 0 )";
"[5] (cc 3 1 )" ->  "[6] (cc 2 1 )";
"[6] (cc 3 0 )" [label="(cc 3 0 )"];
"[6] (cc 2 1 )" [label="(cc 2 1 )"];
"[6] (cc 2 1 )" ->  "[7] (cc 2 0 )";
"[6] (cc 2 1 )" ->  "[7] (cc 1 1 )";
"[7] (cc 2 0 )" [label="(cc 2 0 )"];
"[7] (cc 1 1 )" [label="(cc 1 1 )"];
"[7] (cc 1 1 )" ->  "[8] (cc 1 0 )";
"[7] (cc 1 1 )" ->  "[8] (cc 0 1 )";
"[8] (cc 1 0 )" [label="(cc 1 0 )"];
"[8] (cc 0 1 )" [label="(cc 0 1 )",color=gray80];
"[5] (cc -2 2 )" [label="(cc -2 2 )"];
"[4] (cc -7 3 )" [label="(cc -7 3 )"];
"[2] (cc -12 4 )" [label="(cc -12 4 )"];
"[1] (cc -37 5 )" [label="(cc -37 5 )"];
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment