My solutions to the scheme text "How to Design Programs 2nd ed". (Or htdp2e) I aim to complete as many as these as I can - please feel free to comment on my solutions/answers!
Tuesday, 21 February 2012
Exercise 156: Use cons and empty to construct lists.
Exercise 156: Use cons and empty to construct the equivalent of the following lists:
; 1) (list 0 1 2 3 4 5)
; 2) (list (list "adam" 0) (list "eve" 1) (list "louisXIV" 2))
; 3) (list 1 (list 1 2) (list 1 2 3))
I found this exercise a little harder than expected. This is because I very quickly got tired of using cons to build up lists and have been using list most of the time.
It's good to have the theory and knowledge of lists being constructed of cons and empty, but in practise it is far too tedious.
1) This is very straight forward - just a list of cons...
(check-expect (cons 0 (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 empty ))))))
(list 0 1 2 3 4 5))
2) This is a little more complex - each sublist needs to be cons back into the main list.
(check-expect (cons (cons "adam" (cons 0 empty))
(cons (cons "eve" (cons 1 empty))
(cons (cons "louisXIV" (cons 2 empty)) empty)))
(list (list "adam" 0) (list "eve" 1) (list "louisXIV" 2)))
3) Again, a little more complex. I found it easier to build this up from the inside.
(check-expect (cons 1
(cons (cons 1 (cons 2 empty))
(cons (cons 1 (cons 2 (cons 3 empty))) empty)))
(list 1 (list 1 2) (list 1 2 3)))
Tuesday, 14 February 2012
Question 155: List Processing
Before we start . . . you may ask what happened to question 154? Well, there doesn't seem to be a question 154 in the book! There is an exercise there, but they give you the answer! So, on to question 155...
I had actually 'cheated' somewhat here, and given up on cons a long time ago. A quick hunt through the manual showed the list command and and I've been using that since right near the start.
This is very straight forward exercise:
; Question 1
(check-expect (list "a" "b" "c" "d" "e")
(cons "a"
(cons "b"
(cons "c"
(cons "d"
(cons "e" empty))))))
; Question 2
(check-expect (list (list 1 2))
(cons (cons 1 (cons 2 empty)) empty))
; Question 3
(check-expect (list "a" (list 1) false)
(cons "a" (cons (cons 1 empty) (cons false empty))))
; Question 4
(check-expect (list (list 1 2) (list 2))
(cons (cons 1 (cons 2 empty)) (cons (cons 2 empty) empty)))
; Question 5
(check-expect (list (list "a" 2) "hello")
(cons (cons "a" (cons 2 empty)) (cons "hello" empty))eB.
; Question 1
(check-expect (list "a" "b" "c" "d" "e")
(cons "a"
(cons "b"
(cons "c"
(cons "d"
(cons "e" empty))))))
; Question 2
(check-expect (list (list 1 2))
(cons (cons 1 (cons 2 empty)) empty))
; Question 3
(check-expect (list "a" (list 1) false)
(cons "a" (cons (cons 1 empty) (cons false empty))))
; Question 4
(check-expect (list (list 1 2) (list 2))
(cons (cons 1 (cons 2 empty)) (cons (cons 2 empty) empty)))
; Question 5
(check-expect (list (list "a" 2) "hello")
(cons (cons "a" (cons 2 empty)) (cons "hello" empty)))
Wednesday, 8 February 2012
Exercise 153: Yet More Text Editing
Note: This question is building on the answers to the questions preceding it. Rather than include the code from the last questions each time, I am only including that code which is specific to this question. If I seem to be missing a function or two, I suggest you go look at one of the previous answers!
Exercise 153: Design the functions
;; Editor -> Editor
;; move the cursor position one 1String left, if possible
;(define (editor-lft ed)
; ed)
;
;; Editor -> Editor
;; move the cursor position one 1String right, if possible
;(define (editor-rgt ed)
; ed)
;; Editor -> Editor
;; delete one 1String to the left of the cursor, if possible
;(define (editor-del ed)
; ed)
These are all fairly straight forward functions - simple list manipulation with no recursion to worry about. The challenge here lies in coming up with a reasonable test suite.
; Editor -> Editor
; move the cursor position one 1String left, if possible
; All we need to do is remove the leading character of the
; 'pre' list and append it to the start of the 'post' list
(define (editor-lft ed)
(cond ((empty? (editor-pre ed)) ed)
(else (make-editor (rest (editor-pre ed))
(cons (first (editor-pre ed))
(editor-post ed))))))
; simple case - text on both sides, should move cursor to
; the left
(check-expect (editor-lft (create-editor "eht" "word"))
(create-editor "ht" "eword"))
; empty on left hand side - shouldn't change state
(check-expect (editor-lft (create-editor "" "word"))
(create-editor "" "word"))
I can't think of any other test cases we need to cover here - if editor-post is populated or empty, it shouldn't make any difference to our functions.
; Editor -> Editor
; move the cursor position one 1String right, if possible
; This is the inverse of editor-lft - remove the first character
; from the 'post' text and prepend that to the 'pre' text
(define (editor-rgt ed)
(cond ((empty? (editor-post ed)) ed)
(else (make-editor (append
(explode (first (editor-post ed)))
(editor-pre ed) )
(rest (editor-post ed))))))
; simple case - text on both sides, should move cursor to the right
; Bear in mind that editor-pre is stored reversed, so we need to add chars to the front
; of it.
(check-expect (editor-rgt (create-editor "eht" "cat"))
(create-editor "ceht" "at"))
; empty on right hand side - shouldn't change state
(check-expect (editor-rgt (create-editor "word" ""))
(create-editor "word" ""))
; empty on both sides - shouldn't change state
(check-expect (editor-rgt (create-editor "" ""))
(create-editor "" ""))
; Editor -> Editor
; delete one 1String to the left of the cursor, if possible
(define (editor-del ed)
(cond ((empty? (editor-pre ed)) ed)
(else (make-editor (rest (editor-pre ed))
( editor-post ed)))))
; simple case - string populated on both sides should just
; delete the first chart to the left
(check-expect (editor-del (create-editor "eht" "cat"))
(create-editor "ht" "cat"))
; if the editor-pre is not populated, then nothing should change
; (as there is nothing to delete)
(check-expect (editor-del (create-editor "" "cat"))
(create-editor "" "cat"))
; if the editor-post is not populated, then should still
; be a straight forward delete
(check-expect (editor-del (create-editor "eht " ""))
(create-editor "ht " ""))
; if the editor-post *and* editor-pre are not populated,
; then nothing should happen
(check-expect (editor-del (create-editor "" ""))
(create-editor "" ""))
; and finally, check what happens when there is exactly
; one character to delete
(check-expect (editor-del (create-editor "a" "xxx"))
(create-editor "" "xxx"))
Exercise 153: Design the functions
;; Editor -> Editor
;; move the cursor position one 1String left, if possible
;(define (editor-lft ed)
; ed)
;
;; Editor -> Editor
;; move the cursor position one 1String right, if possible
;(define (editor-rgt ed)
; ed)
;; Editor -> Editor
;; delete one 1String to the left of the cursor, if possible
;(define (editor-del ed)
; ed)
These are all fairly straight forward functions - simple list manipulation with no recursion to worry about. The challenge here lies in coming up with a reasonable test suite.
; Editor -> Editor
; move the cursor position one 1String left, if possible
; All we need to do is remove the leading character of the
; 'pre' list and append it to the start of the 'post' list
(define (editor-lft ed)
(cond ((empty? (editor-pre ed)) ed)
(else (make-editor (rest (editor-pre ed))
(cons (first (editor-pre ed))
(editor-post ed))))))
; simple case - text on both sides, should move cursor to
; the left
(check-expect (editor-lft (create-editor "eht" "word"))
(create-editor "ht" "eword"))
; empty on left hand side - shouldn't change state
(check-expect (editor-lft (create-editor "" "word"))
(create-editor "" "word"))
I can't think of any other test cases we need to cover here - if editor-post is populated or empty, it shouldn't make any difference to our functions.
; Editor -> Editor
; move the cursor position one 1String right, if possible
; This is the inverse of editor-lft - remove the first character
; from the 'post' text and prepend that to the 'pre' text
(define (editor-rgt ed)
(cond ((empty? (editor-post ed)) ed)
(else (make-editor (append
(explode (first (editor-post ed)))
(editor-pre ed) )
(rest (editor-post ed))))))
; simple case - text on both sides, should move cursor to the right
; Bear in mind that editor-pre is stored reversed, so we need to add chars to the front
; of it.
(check-expect (editor-rgt (create-editor "eht" "cat"))
(create-editor "ceht" "at"))
; empty on right hand side - shouldn't change state
(check-expect (editor-rgt (create-editor "word" ""))
(create-editor "word" ""))
; empty on both sides - shouldn't change state
(check-expect (editor-rgt (create-editor "" ""))
(create-editor "" ""))
; Editor -> Editor
; delete one 1String to the left of the cursor, if possible
(define (editor-del ed)
(cond ((empty? (editor-pre ed)) ed)
(else (make-editor (rest (editor-pre ed))
( editor-post ed)))))
; simple case - string populated on both sides should just
; delete the first chart to the left
(check-expect (editor-del (create-editor "eht" "cat"))
(create-editor "ht" "cat"))
; if the editor-pre is not populated, then nothing should change
; (as there is nothing to delete)
(check-expect (editor-del (create-editor "" "cat"))
(create-editor "" "cat"))
; if the editor-post is not populated, then should still
; be a straight forward delete
(check-expect (editor-del (create-editor "eht " ""))
(create-editor "ht " ""))
; if the editor-post *and* editor-pre are not populated,
; then nothing should happen
(check-expect (editor-del (create-editor "" ""))
(create-editor "" ""))
; and finally, check what happens when there is exactly
; one character to delete
(check-expect (editor-del (create-editor "a" "xxx"))
(create-editor "" "xxx"))
Subscribe to:
Posts (Atom)