University stuff.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

oppgave.scm 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. ;; Jeg har med huffman.scm i leveringen, men ingenting der er endret.
  2. ;; Beklager blandingen av norsk og engelsk. Svar på oppgaver er skrevet
  3. ;; på norsk, kodekommentarer er skrevet på engelsk.
  4. (load "huffman.scm")
  5. ;;;;;;;
  6. ;; 1 ;;
  7. ;;;;;;;
  8. ;; A
  9. (define (p-cons x y)
  10. (lambda (proc) (proc x y)))
  11. (define (p-car p)
  12. (p (lambda (x y) x)))
  13. (define (p-cdr p)
  14. (p (lambda (x y) y)))
  15. ;; B
  16. (define foo 42)
  17. ;; let (evaluerer til 'different):
  18. (let ((foo 5)
  19. (x foo))
  20. (if (= x foo)
  21. 'same
  22. 'different))
  23. ;; med lambda:
  24. ((lambda (foo x)
  25. (if (= x foo)
  26. 'same
  27. 'different))
  28. 5 foo)
  29. ;; let (evaluerer til ('towel (42 'towel)))
  30. (let ((bar foo)
  31. (baz 'towel))
  32. (let ((bar (list bar baz))
  33. (foo baz))
  34. (list foo bar)))
  35. ;; med lambda:
  36. ((lambda (bar baz)
  37. ((lambda (bar foo)
  38. (list foo bar))
  39. (list bar baz) baz))
  40. foo 'towel)
  41. ;; C
  42. (define (infix-eval exp)
  43. (let ((opr1 (car exp))
  44. (operator (cadr exp))
  45. (opr2 (caddr exp)))
  46. (operator opr1 opr2)))
  47. ;; D
  48. ;; Resultatet blir en "not a procedure"-feil. Dette er fordi at når vi bruker
  49. ;; quote er / et symbol, ikke en prosedyre. '(/) er dermed en liste som
  50. ;; inneholder symbolet /, mens (list /) blir en liste som inneholder prosedyren
  51. ;; med navn /.
  52. ;;;;;;;
  53. ;; 2 ;;
  54. ;;;;;;;
  55. ;; A
  56. (define (member? eq-pred el items)
  57. (cond ((null? items) #f)
  58. ((eq-pred el (car items)) #t)
  59. (else (member? eq-pred el (cdr items)))))
  60. ;; B
  61. ;; Det er nødvendig med en intern prosedyre fordi vi trenger tilgang
  62. ;; til roten av treet. Siden vi har en decode-1 prosedyre inne i decode,
  63. ;; har decode-1 tilgang til både variablen tree, som er roten av treet,
  64. ;; og current-branch, som er sub-treet den holder på med.
  65. ;; C
  66. (define (decode bits tree)
  67. (define (decode-1 bits current-branch acc)
  68. (if (null? bits)
  69. (reverse acc)
  70. (let ((next-branch
  71. (choose-branch (car bits) current-branch)))
  72. (cond ((leaf? next-branch)
  73. (decode-1 (cdr bits) tree (cons (symbol-leaf next-branch) acc)))
  74. (else (decode-1 (cdr bits) next-branch acc))))))
  75. (decode-1 bits tree '()))
  76. ;; D
  77. (decode sample-code sample-tree)
  78. ;; -> (ninjas fight ninjas by night)
  79. ;; E
  80. ;; This procedure isn't inside the encode function, as it's
  81. ;; useful later
  82. (define (encode-symbol sym tree)
  83. (cond ((leaf? tree) '())
  84. ((member? eq? sym (symbols (left-branch tree)))
  85. (cons 0 (encode-symbol sym (left-branch tree))))
  86. (else
  87. (cons 1 (encode-symbol sym (right-branch tree))))))
  88. (define (encode syms tree)
  89. (if (null? syms)
  90. '()
  91. (append (encode-symbol (car syms) tree)
  92. (encode (cdr syms) tree))))
  93. ;; F
  94. (define (grow-huffman-tree freqs)
  95. (define (get-biggest freqs)
  96. (define (get-biggest-1 freqs biggest)
  97. (cond ((null? freqs) biggest)
  98. ((> (cadr(car freqs)) (cadr biggest))
  99. (get-biggest-1 (cdr freqs) (car freqs)))
  100. (else (get-biggest-1 (cdr freqs) biggest))))
  101. (get-biggest-1 freqs (car freqs)))
  102. ;; Returns a new list with the element removed.
  103. ;; The list is reversed because we don't care about the order.
  104. (define (remove-from-list items elem)
  105. (define (remove-1 items elem acc)
  106. (cond ((null? items) acc)
  107. ((eq? elem (car items)) (remove-1 (cdr items) elem acc))
  108. (else (remove-1 (cdr items) elem (cons (car items) acc)))))
  109. (remove-1 items elem '()))
  110. ;; Inner function because I don't want to define get-biggest
  111. ;; and remove-from-list for every single iteration.
  112. ;; Maybe scheme optimizes that away, but it felt weird.
  113. (define (grow-tree-1 freqs)
  114. (if (null? (cdr freqs))
  115. (make-leaf (caar freqs) (cadar freqs))
  116. (let ((biggest (get-biggest freqs)))
  117. (make-code-tree (make-leaf (car biggest) (cadr biggest))
  118. (grow-tree-1 (remove-from-list freqs biggest))))))
  119. (grow-tree-1 freqs))
  120. ;; G
  121. (define g-freqs
  122. '((samurais 57) (ninjas 20) (fight 45) (night 12) (hide 3) (in 2)
  123. (ambush 2) (defeat 1) (the 5) (sword 4) (by 12) (assassin 1)
  124. (river 2) (forest 1) (wait 1) (poison 1)))
  125. (define g-tree (grow-huffman-tree g-freqs))
  126. (define g-msg '(ninjas fight
  127. ninjas fight ninjas
  128. ninjas fight samurais
  129. samurais fight
  130. samurais fight ninjas
  131. ninjas fight by night))
  132. (encode g-msg g-tree)
  133. ;; -> (1 1 0 1 0 1 1 0 1 0 1 1 0 1 1 0 1 0 0 0 1
  134. ;; 0 0 1 0 1 1 0 1 1 0 1 0 1 1 1 0 1 1 1 1 0)
  135. ;; - 42 bits.
  136. ;; - Den gjennomsnittlige lengden av hvert ord er rundt 2.47 bits (42 / 17).
  137. ;; - Den minste mengden bits vi kan få med en fixed-length code er 51.
  138. ;; Dette er fordi vi har forskjellige 5 symboler, og den minste antall bits
  139. ;; som har minst 5 forskjellige verdier er 3. Meldingen er 17 symboler lang,
  140. ;; og 17 * 3 = 51.
  141. ;; H
  142. (define (huffman-leaves tree)
  143. (define (sym s)
  144. (list (list (symbol-leaf s) (weight-leaf s))))
  145. (if (leaf? tree)
  146. (sym tree)
  147. (append (huffman-leaves (left-branch tree))
  148. (huffman-leaves (right-branch tree)))))
  149. (huffman-leaves sample-tree)
  150. ;; -> ((ninjas 8) (fight 5) (night 1) (by 1))
  151. ;; I
  152. ;; This is kind of big and ugly. I found out that you apparently can't
  153. ;; first define a procedure, then define a variable whose definition
  154. ;; uses that procedure. As a result, I have to define code-length-1 within
  155. ;; a let, even though it seems kind of unnecessary.
  156. (define (expected-code-length tree)
  157. (define syms (huffman-leaves tree))
  158. ;; Function to count the total frequencies
  159. (define (total-freqs-1 syms acc)
  160. (cond ((null? syms) acc)
  161. (else (total-freqs-1 (cdr syms) (+ acc (cadar syms))))))
  162. (let ((total-freqs (total-freqs-1 syms 0)))
  163. ;; Get the number of bits for a symbol
  164. (define (c sym)
  165. (length (encode-symbol (car sym) tree)))
  166. ;; Get the relative frequency of a symbol
  167. (define (p sym)
  168. (/ (cadr sym)
  169. total-freqs))
  170. (define (code-length-1 syms)
  171. (if (null? syms)
  172. 0
  173. (+ (* (p (car syms))
  174. (c (car syms)))
  175. (code-length-1 (cdr syms)))))
  176. (code-length-1 syms)))
  177. (expected-code-length sample-tree)
  178. ;; -> 8/5