Topics:SICP in other languages:Qi:Chapter 1
From CTMWiki
About SICP
The following Qi code is derived from the examples provided in the book:
"Structure and Interpretation of Computer Programs, Second Edition"
by Harold Abelson and Gerald Jay Sussman with Julie Sussman.
http://mitpress.mit.edu/sicp/
| Table of contents |
[edit]
\* SICP Chapter #01 Examples in Qi *\
[edit]
\* 1.1.1 The Elements of Programming - Expressions *\
486 (+ 137 349) (- 1000 334) (* 5 99) (/ 10 5) (+ 2.7 10) (+ (+ 21 35) (+ 12 7)) (* (* 25 4) 12) (+ (* 3 5) (- 10 6)) (+ (* 3 (+ (* 2 4) (+ 3 5))) (+ (- 10 7) 6))
[edit]
\* 1.1.2 The Elements of Programming - Naming and the Environment *\
(set size 2) (value size) (* 5 (value size)) (set pi 3.14159) (set radius 10) (* (value pi) (* (value radius) (value radius))) (set circumference (* 2 (* (value pi) (value radius)))) (value circumference)
[edit]
\* 1.1.3 The Elements of Programming - Evaluating Combinations *\
(* (+ 2 (* 4 6)) (+ 3 (+ 5 7)))
[edit]
\* 1.1.4 The Elements of Programming - Compound Procedures *\
(define square
{ number --> number }
X -> (* X X)
)
(square 21)
(square (+ 2 5))
(square (square 3))
(define sum-of-squares
{ number --> number --> number }
X Y -> (+ (square X) (square Y))
)
(sum-of-squares 3 4)
(define f
{ number --> number }
A -> (sum-of-squares (+ A 1) (* A 2))
)
(f 5)
[edit]
\* 1.1.5 The Elements of Programming - The Substitution Model for Procedure Application *\
(f 5) (sum-of-squares (+ 5 1) (* 5 2)) (+ (square 6) (square 10)) (+ (* 6 6) (* 10 10)) (+ 36 100) (f 5) (sum-of-squares (+ 5 1) (* 5 2)) (+ (square (+ 5 1)) (square (* 5 2))) (+ (* (+ 5 1) (+ 5 1)) (* (* 5 2) (* 5 2))) (+ (* 6 6) (* 10 10)) (+ 36 100) 136
[edit]
\* 1.1.6 The Elements of Programming - Conditional Expressions and Predicates *\
(define abs
{ number --> number }
X ->
(if (> X 0)
X
(if (= X 0) X (- 0 X)))
)
(define abs
{ number --> number }
X -> (if (< X 0) (- 0 X) X)
)
(set x 6)
(and (> (value x) 5) (< (value x) 10))
(define ge
{ number --> number }
X Y -> (or (> X Y) (= X Y))
)
(define ge
{ number --> number }
X Y -> (not (< X Y))
)
\* Exercise 1.1 *\
10
(+ 5 (+ 3 4))
(- 9 1)
(/ 6 2)
(+ (* 2 4) (- 4 6))
(set a 3)
(set b (+ (value a) 1))
(+ (+ (value a) (value b)) (* (value a) (value b)))
(= a b)
(if (and (> (value b) (value a))
(< (value b) (* (value a) (value b))))
(value b)
(value a))
(if (= a 4)
6
(if (= b 4)
(+ 6 (+ 7 a))
25))
(+ 2 (if (> (value b) (value a)) (value b) (value a)))
(* (if (> (value a) (value b))
(value a)
(if (< (value a) (value b)) (value b) -1))
(+ (value a) 1))
\* Exercise 1.2 *\
(/ (+ (+ 5 4) (- 2 (- 3 (+ 6 (/ 4 5)))))
(* 3 (* (- 6 2) (- 2 7))))
\* Exercise 1.3 *\
(define three-n
{ number --> number --> number --> number }
N1 N2 N3 ->
(if (> N1 N2)
(if (> N1 N3)
(if (> N2 N3)
(+ (* N1 N1) (* N2 N2))
(+ (* N1 N1) (* N3 N3)))
(+ (* N1 N1) (* N3 N3)))
(if (> N2 N3)
(if (> N1 N3)
(+ (* N2 N2) (* N1 N1))
(+ (* N2 N2) (* N3 N3)))
(+ (* N2 N2) (* N3 N3))))
)
\* Exercise 1.4 *\
(define a-plus-abs-b
{ number --> number --> number }
A B ->
(if (> B 0)
(+ A B)
(- A B))
)
\* Exercise 1.5 *\
(define p
() -> (p ())
)
(define test
{ number --> number --> number }
X Y ->
(if (= X 0) 0 Y)
)
\* commented out as this is in infinite loop
(test 0 (p ())) *\
[edit]
\* 1.1.7 The Elements of Programming - Example: Square Roots by Newton's Method *\
(define square
{ number --> number }
X -> (* X X)
)
(define good-enough?
{ number --> number --> number }
Guess X -> (< (abs (- (square Guess) X)) 0.001)
)
(define average
{ number --> number --> number }
X Y -> (/ (+ X Y) 2)
)
(define improve
{ number --> number --> number }
Guess X -> (average Guess (/ X Guess))
)
(define sqrt-iter
{ number --> number --> number }
Guess X ->
(if (good-enough? Guess X)
Guess
(sqrt-iter (improve Guess X) X))
)
(define sqrtx
{ number --> number }
X -> (sqrt-iter 1.0 X)
)
(sqrtx 9)
(sqrtx (+ 100 37))
(sqrtx (sqrtx (+ 2 (sqrtx 3))))
(square (sqrtx 1000))
\* Exercise 1.6 *\
(define new-if
Predicate Then-Clause Else-Clause ->
(if Predicate
Then-Clause
Else-Clause)
)
(new-if (= 2 3) 0 5)
(new-if (= 1 1) 0 5)
(define sqrt-iter
{ number --> number --> number }
Guess X ->
(new-if (good-enough? Guess X)
Guess
(sqrt-iter (improve Guess X) X))
)
\* from wadler paper *\
(define new-if
true X Y -> X
false X Y -> Y
)
\* Exercse 1.7 *\
(define good-enough-gp?
{ number --> number --> number }
Guess Prev -> (< (/ (abs (- Guess Prev)) Guess) 0.001)
)
(define sqrt-iter-gp
{ number --> number --> number }
Guess Prev X ->
(if (good-enough-gp? Guess Prev)
Guess
(sqrt-iter-gp (improve Guess X) Guess X))
)
(define sqrt-gp
{ number --> number }
X -> (sqrt-iter-gp 4.0 1.0 X)
)
\* Exercise 1.8 *\
(define improve-cube
{ number --> number }
Guess X ->
(/ (+ (* 2 Guess) (/ X (* Guess Guess))) 3)
)
(define cube-iter
{ number --> number --> number }
Guess Prev X ->
(if (good-enough-gp? Guess Prev)
Guess
(cube-iter (improve-cube Guess X) Guess X))
)
(define cube-root
{ number --> number }
X -> (cube-iter 27.0 1.0 X)
)
[edit]
\* 1.1.8 The Elements of Programming - Procedures as Black-Box Abstractions *\
(define square
{ number --> number }
X -> (* X X)
)
(define double
{ number --> number }
X -> (+ X X)
)
(define squarex
{ number --> number }
X -> (EXP (double (LOG X)))
)
(define good-enough?
{ number --> number --> number }
Guess X -> (< (abs (- (square Guess) X)) 0.001)
)
(define improve
{ number --> number --> number }
Guess X -> (average Guess (/ X Guess))
)
(define sqrt-iter
{ number --> number --> number }
Guess X ->
(if (good-enough? Guess X)
Guess
(sqrt-iter (improve Guess X) X))
)
(define sqrtx
{ number --> number }
X -> (sqrt-iter 1.0 X)
)
(square 5)
\* Block-structured *\
\* Note: Although lambda expressions can be use to get the effect of nested functions,
I haven't figured a way to get recursive lambda functions. Means that this
example is not correct yet.
(define sqrtx
{ number --> number }
X ->
(let
good-enough? (/. Guess (/. X
(< (abs (- (square Guess) X)) 0.001)))
(let
improve (/. Guess (/. X
(average Guess (/ X Guess))))
(let
sqrt-iter (/. Guess (/. X
(if (good-enough? Guess X)
Guess
(sqrt-iter (improve Guess X) X))))
(sqrt-iter 1.0 X)
)
)
)
)
*\
\* Taking advantage of lexical scoping *\
\* Note: Although lambda expressions can be use to get the effect of nested functions,
I haven't figured a way to get recursive lambda functions. Means that this
example is not correct yet.
(define sqrtx
{ number --> number }
X ->
(let
good-enough? (/. Guess
(< (abs (- (square Guess) X)) 0.001))
(let
improve (/. Guess
(average Guess (/ X Guess)))
(let
sqrt-iter (/. Guess
(if (good-enough? Guess)
Guess
(sqrt-iter (improve Guess))))
(sqrt-iter 1.0)
)
)
)
)
*\
[edit]
\* 1.2.1 Procedures and the Processes They Generate - Linear Recursion and Iteration *\
\* Recursive *\
(define factorialx
{ integer --> integer }
N ->
(if (= N 1)
1
(* N (factorialx (- N 1))))
)
(factorialx 6)
\* Iterative *\
(define fact-iter
{ integer --> integer --> integer --> integer }
Product Counter Max-Count ->
(if (> Counter Max-Count)
Product
(fact-iter (* Counter Product) (+ Counter 1) Max-Count))
)
(define factorialx
{ integer --> integer }
N -> (fact-iter 1 1 N)
)
\* Iterative, block-structured (from footnote) *\
\* Note: Although lambda expressions can be use to get the effect of nested functions,
I haven't figured a way to get recursive lambda functions. Means that this
example is not correct yet.
(define factorialxz
{ integer --> integer }
N ->
(let
fun-iter (/. Product (/. Counter (/. Max-Count
(if (> Counter Max-Count)
Product
(fact-iter (* Counter Product) (+ Counter 1) Max-Count)))))
(fact-iter 1 1 N)
)
)
*\
\* Exercise 1.9 *\
(define inc { integer --> integer } A -> (+ A 1))
(define dec { integer --> integer } A -> (- A 1))
(define plus
{ integer --> integer --> integer }
A B ->
(if (= A 0)
B
(inc (plus (dec A) B)))
)
(define plus
{ integer --> integer --> integer }
A B ->
(if (= A 0)
B
(plus (dec A) (inc B)))
)
\* Exercise 1.10 *\
(define a
{ integer --> integer --> integer }
X 0 -> 0
0 Y -> (* 2 Y)
X 1 -> 2
X Y -> (a (- X 1) (a X (- Y 1)))
)
(a 1 10)
(a 2 4)
(a 3 3)
(define f { integer --> integer } N -> (a 0 N))
(define g { integer --> integer } N -> (a 1 N))
(define h { integer --> integer } N -> (a 2 N))
(define k { integer --> integer } N -> (* 5 (* N N)))
[edit]
\* 1.2.2 Procedures and the Processes They Generate - Tree Recursion *\
\* Recursive *\
(define fib
{ integer --> integer }
0 -> 0
1 -> 1
N -> (+ (fib (- N 1)) (fib (- N 2)))
)
\* Iterative *\
(define fib-iter
{ integer --> integer --> integer --> integer }
A B 0 -> B
A B Count -> (fib-iter (+ A B) A (- Count 1))
)
(define fib
{integer --> integer }
N -> (fib-iter 1 0 N)
)
\* Counting change *\
(define first-denomination
{ integer --> integer }
1 -> 1
2 -> 5
3 -> 10
4 -> 25
5 -> 50
)
(define cc
{ integer --> integer --> integer }
0 Kinds-Of-Coins -> 1
Amount Kinds-Of-Coins -> 0 where (< Amount 0)
Amount 0 -> 0
Amount Kinds-Of-Coins ->
(+ (cc Amount (- Kinds-Of-Coins 1))
(cc (- Amount (first-denomination Kinds-Of-Coins)) Kinds-Of-Coins))
)
(define count-change
{ integer --> integer }
Amount -> (cc Amount 5)
)
(count-change 100)
\* Exercise 1.11 *\
(define f
{ integer --> integer }
N ->
(if (< N 3)
N
(+ (f (- N 1)) (+ (* 2 (f (- N 2))) (* 3 (f (- N 3))))))
)
(define f-iter
{ integer --> integer --> integer --> integer --> integer }
A B C 0 -> C
A B C Count -> (f-iter (+ A (+ (* 2 B) (* 3 C))) A B (- Count 1))
)
(define f
{ integer --> integer }
N -> (f-iter 2 1 0 n)
)
\* Exercise 1.12 *\
(define pascals-triangle
{ number --> number --> number }
0 K -> 1
N 0 -> 1
N K -> 1 where (= N K)
N K -> (+ (pascals-triangle (- N 1) (- K 1))
(pascals-triangle (- N 1) K))
)
[edit]
\* 1.2.3 Procedures and the Processes They Generate - Orders of Growth *\
\* Exercise 1.15 *\
(define cube { number --> number } X -> (* X (* X X)))
(define p { number --> number } X -> (- (* 3 X) (* 4 (cube X))))
(define sine
{ number --> number }
Angle ->
(if (not (> (abs Angle) 0.1))
Angle
(p (sine (/ Angle 3.0))))
)
[edit]
\* 1.2.4 Procedures and the Processes They Generate - Exponentiation *\
\* Linear recursion *\
(define expt
{ number --> number --> number }
B 0 -> 1
B N -> (* B (expt B (- N 1)))
)
\* Linear iteration *\
(define expt-iter
{ number --> number --> number --> number }
B 0 Product -> Product
B Counter Product -> (expt-iter B (- Counter 1) (* B Product))
)
(define expt
{ number --> number --> number }
B N -> (expt-iter B N 1)
)
\* Logarithmic iteration *\
(define div { integer --> integer } X Y -> (TRUNCATE (/ X Y)))
(define even
{ integer --> integer }
N -> (= (MOD N 2) 0)
)
(define fast-expt
{ integer --> integer --> integer }
B 0 -> 1
B N -> (square (fast-expt B (div N 2))) where (even N)
B N -> (* B (fast-expt B (- N 1)))
)
\* Exercise 1.17 *\
(define multiply
{ integer --> integer --> integer }
A 0 -> 0
A B -> (+ A (* A (- B 1)))
)
\* Exercise 1.19 *\
(define fib-iter
{ integer --> integer --> integer --> integer --> integer --> integer }
A B P Q 0 -> B
A B P Q Count -> (fib-iter A B (+ (* P P) (* Q Q)) (+ (* 2 (* P Q)) (* Q Q)) (div Count 2))
where (even Count)
A B P Q Count -> (fib-iter (+ (* B Q) (+ (* A Q) (* A P))) (+ (* B P) (* A Q)) P Q (- Count 1))
)
(define fib
{ integer --> integer }
N -> (fib-iter 1 0 0 1 N)
)
[edit]
\* 1.2.5 Procedures and the Processes They Generate - Greatest Common Divisors *\
(define gcd
{ integer --> integer --> integer }
A 0 -> A
A B -> (gcd B (MOD A B))
)
(gcd 40 6)
\* Exercise 1.20 *\
(gcd 206 40)
[edit]
\* 1.2.6 Procedures and the Processes They Generate - Example: Testing for Primality *\
\* prime *\
(define divides
{ integer --> integer --> integer }
A B -> (= (MOD B A) 0)
)
(define find-divisor
{ integer --> integer --> integer }
N Test-Divisor ->
(if (> (square Test-Divisor) N)
N
(if (divides Test-Divisor N)
Test-Divisor
(find-divisor N (+ Test-Divisor 1))))
)
(define smallest-divisor
{ integer --> integer }
N -> (find-divisor N 2)
)
(define prime?
{ integer --> integer }
N -> (= N (smallest-divisor N))
)
\* fast-prime *\
(define expmod
{ integer --> integer --> integer --> integer }
Nbase 0 M -> 1
Nbase Nexp M -> (MOD (square (expmod Nbase (div Nexp 2) M)) M)
where (even Nexp)
Nbase Nexp M -> (MOD (* Nbase (expmod Nbase (- Nexp 1) M)) M)
)
(define fermat-test
{ integer --> boolean }
N ->
(let
try-it (/. A (= (expmod A N N) A))
(try-it (+ 1 (random (- N 1)))))
)
(define fast-prime?
{ integer --> integer --> integer }
N 0 -> true
N Ntimes ->
(if (fermat-test N)
(fast-prime? N (- Ntimes 1))
false)
)
\* Exercise 1.21 *\
(smallest-divisor 199)
(smallest-divisor 1999)
(smallest-divisor 19999)
\* Exercise 1.22 *\
\* not sure how to get msec clock in Qi *\
(define get-time-in-milliseconds -> 1234)
(define report-prime
{ integer --> () }
Elapsed-Time ->
(output " *** ~A~%" Elapsed-Time)
)
(define start-prime-test
{ integer --> integer --> () }
N Start-Time ->
(if (prime? N)
(report-prime (- (get-time-in-milliseconds) Start-Time))
'())
)
(define timed-prime-test
{ integer --> () }
N ->
(let
X (output "~A~%" N)
(start-prime-test N (get-time-in-milliseconds)))
)
\* Exercise 1.25 *\
(define expmod
{ integer --> integer --> integer }
Nbase Nexp M -> (MOD (fast-expt Nbase Nexp) M)
)
\* Exercise 1.26 *\
(define expmod
{ integer --> integer --> integer }
Nbase 0 M -> 1
Nbase Nexp M -> (MOD (* (expmod Nbase (div Nexp 2) M) (expmod Nbase (div Nexp 2) M)) M)
where (even Nexp)
Nbase Nexp M -> (MOD (* Nbase (expmod Nbase (- Nexp 1) M)) M)
)
\* Exercise 1.27 *\
(define carmichael?
{ integer --> boolean }
N -> (and (fast-prime? N 100) (not (prime? N)))
)
(carmichael? 561)
(carmichael? 1105)
(carmichael? 1729)
(carmichael? 2465)
(carmichael? 2821)
(carmichael? 6601)
[edit]
\* 1.3 Formulating Abstractions with Higher-Order Procedures *\
(define cube { number --> number } X -> (* X (* X X)))
[edit]
\* 1.3.1 Formulating Abstractions with Higher-Order Procedures - Procedures as Arguments *\
(define sum-integers
{ integer --> integer --> integer }
A B -> 0 where (> A B)
A B -> (+ A (sum-integers (+ A 1) B))
)
(define sum-cubes
{ integer --> integer --> integer }
A B -> 0 where (> A B)
A B -> (+ (cube A) (sum-cubes (+ A 1) B))
)
(define pi-sum
{ real --> real --> real }
A B -> 0.0 where (> a b)
A B -> (+ (/ 1.0 (* A (+ A 2.0)))
(pi-sum (+ A 4.0) B)))
(define sum
{ (number --> number) --> number --> (number --> number) --> number --> number }
Term A Next B -> 0 where (> A B)
Term A Next B -> (+ (Term A) (sum Term (Next A) Next B))
)
\* Using sum *\
(define inc { integer --> integer } N -> (+ N 1))
(define sum-cubes
{ integer --> integer --> integer }
A B -> (sum cube A inc B)
)
(sum-cubes 1 10)
(define identity { a --> a } X -> X)
(define sum-integers
{ integer --> integer --> integer }
A B -> (sum identity A inc B)
)
(sum-integers 1 10)
(define pi-sum
{ real --> real --> real}
A B ->
(let
pi-term (/. X (/ 1.0 (* X (+ X 2.0))))
(let
pi-next (/. X (+ X 4.0))
(sum pi-term A pi-next B)))
)
(* 8.0 (pi-sum 1.0 1000.0))
(define integral
{ (number --> number) --> number --> number --> number --> number }
F A B Dx ->
(let
add-dx (/. X (+ X Dx))
(* (sum F (+ A (/ Dx 2.0)) add-dx B) Dx))
)
(integral cube 0.0 1.0 0.01)
(integral cube 0.0 1.0 0.001)
\* Exercise 1.29 *\
(define sum-iter
{ (number --> number) --> number --> (number --> number) --> number --> number --> number --> number --> number }
Term Start Next Stop Acc A H -> Acc where (> Start Stop)
Term Start Next Stop Acc A H ->
(sum-iter Term (Next Start) Next Stop (+ Acc (Term (+ A (* Start H)))) A H)
)
(define simpson
{ (number --> number) --> number --> number --> integer --> number }
F A B N ->
(let
H (/ (abs (- B A)) N)
(* H (sum-iter F 1 inc N 0.0 A H)))
)
(simpson cube 0.0 1.0 100)
\* Exercise 1.30 *\
(define sum-iter
{ (number --> number) --> number --> (number --> number) --> number --> number --> number }
Term A Next B Acc -> Acc where (> A B)
Term A Next B Acc -> (sum-iter Term (Next A) Next B (+ Acc (Term A)))
)
(define sum-cubes
{ integer --> integer --> integer }
A B -> (sum-iter cube A inc B 0)
)
(sum-cubes 1 10)
\* Exercise 1.31 *\
(define product
{ (number --> number) --> number --> (number --> number) --> number --> number }
Term A Next B -> 1 where (> A B)
Term A Next B -> (* (Term A) (product Term (Next A) Next B))
)
(define factorial
{ integer --> integer }
N -> (product identity 1 inc N)
)
(define product-iter
{ (number --> number) --> number --> (number --> number) --> number --> number --> number }
Term A Next B Acc -> Acc where (> A B)
Term A Next B Acc -> (product-iter Term (Next A) Next B (* Acc (Term A)))
)
\* Exercise 1.32 *\
(define accumulate
{ (a --> a --> a) --> a --> (a --> a) --> a --> (a --> a) --> a --> a }
Combiner Null-Value Term A Next B -> Null-Value where (> A B)
Combiner Null-Value Term A Next B ->
(Combiner (Term A) (accumulate Combiner Null-Value Term (Next A) Next B))
)
(define sum-n { integer --> integer } A B -> (accumulate + 0 identity A inc B))
(define product-n { integer --> integer } A B -> (accumulate * 1 identity A inc B))
(define accumulate-iter
{ (a --> a --> a) --> (a --> a) --> a --> (a --> a) --> a --> a --> a }
Combiner Term A Next B Acc -> Acc where (> A B)
Combiner Term A Next B Acc ->
(accumulate-iter Combiner Term (Next A) Next B (Combiner Acc (Term A)))
)
(define sum-n { integer --> integer } A B -> (accumulate-iter + identity A inc B 0))
(define product-n { integer --> integer } A B -> (accumulate-iter * identity A inc B 1))
\* Exercise 1.33 *\
(define filtered-accumulate
{ (a --> a --> a) --> a --> (a --> a) --> a --> (a --> a) --> a --> (a --> a) --> a }
Combiner Null-Value Term A Next B Pred -> Null-Value where (> A B)
Combiner Null-Value Term A Next B Pred ->
(Combiner (Term A) (filtered-accumulate Combiner Null-Value Term (Next A) Next B Pred))
where (Pred A)
Combiner Null-Value Term A Next B Pred ->
(filtered-accumulate Combiner Null-Value Term (Next A) Next B Pred)
)
(filtered-accumulate + 0 square 1 inc 5 prime?)
[edit]
\* 1.3.2 Formulating Abstractions with Higher-Order Procedures - Constructing Procedures Using Lambda *\
(define pi-sum
{ real --> real }
A B -> (sum (/. X (/ 1.0 (* X (+ X 2.0))))
A
(/. X (+ X 4.0))
B)
)
(define integral
{ (number --> number) --> number --> number --> number --> number }
F A B Dx ->
(* (sum F
(+ A (/ Dx 2.0))
(/. X (+ X Dx))
B)
Dx)
)
(define plus4 { number --> number } X -> (+ X 4))
(set plus4 (/. X (+ X 4)))
((/. X (/. Y (/. Z (+ X (+ Y (square Z)))))) 1 2 3)
![[Main Page]](/wiki/stylesheets/images/wiki.png)