#lang racket
(require rackunit)
(require csc151)
(require csc151/rex)
(require 2htdp/image)
(require racket/match)
(require racket/undefined)
(require rackunit/text-ui)
(define csc151-syllax
(vector
; 0
(vector)
; 1
(vector “cons” “car” “list” “pair” “Scheme” “sort” “match” “string”
“lab” “map” “fold” “test”)
; 2
(vector “vector” “cadr” “cdr” “Racket” “jelly” “sandwich” “syllax”
“image” “recurse” “eboard” “data” “compose” “lambda” “section”
“SoLA” “MP”)
; 3
(vector “recursion” “computer” “digital” “confusing” “programming”
“CSC” “abstraction” “decompose” “document” “abstraction”
“boolean” “binary”)
; 4
(vector “humanities” “exponential” “collaborate” “one-fifty-one”
“algorithm” “DrRacket” “dictionary” “generalize”
“tail recursion”)
; 5
(vector “collaborative” “experiential” “decomposition” “generality”)
; 6
(vector)
; 7
(vector “triskaidekaphobia”)))
(define grinnell-syllax
(vector
; 0
(vector)
; 1
(vector “Mears” “Noyce” “husk” “train” “corn” “black”)
; 2
(vector “self-gov” “Stonewall” “The Bear” “first-year” “scarlet”
“remote” “Webex” “prairie” “need-blind” “soybeans” “Hopkins”
“Younker” “Dibble” “cluster” “scurry”)
; 3
(vector “liberal” “JRC” “CLS” “advisor” “FYE” “laurel leaf” “Honor G”
“ARH” “North Campus” “Iowa” “semester” “Women’s quad”
“Grinnellian”)
; 4
(vector “curriculum” “Mary B. James” “Tutorial” “Green alien” “convocation” “education”)
; 5
(vector)
; 6
(vector “Congregationalist”)))
;;; (random-vector-element vec) -> any?
;;; vec : vector? (nonempty)
;;; Randomly select an element of `vec`
(define random-vector-element
(lambda (vec)
(vector-ref vec (random (vector-length vec)))))
;;; (vector-andmap vec) –> boolean?
;;; vec: vector? (nonempty)
;;; Returns true if every entry of vec is true, and
;;; false otherwise
(define vector-andmap
(lambda (vec)
(let ([len (vector-length vec)])
(letrec ([go (lambda (pos)
(if (= pos len)
#t
(and (vector-ref vec pos) (go (+ pos 1)))))])
(go 0)))))
;;; (strvec? val) -> boolean?
;;; val : any?
;;; Determines if val is a vector of strings?
(define strvec?
(lambda (val)
(and (vector? val)
(vector-andmap string? val))))
;Part 1
;a
;;; (phrase n syllax) -> string?
;;; n : integer?
;;; syllax :vector?
;;; Returns a random string that contains a phrase from ‘syllax’ of n syllables.
(define phrase
(lambda (n syllax)
(cond
[(= n 0)
“”]
[(= n 1)
(random-vector-element (vector-ref syllax 1))]
[else
(let* ([syllable1 (random (+ n 1))]
[syllable2 (- n syllable1)])
(if (or (= syllable1 0) (= syllable2 0))
(random-vector-element (vector-ref syllax n))
(string-append (random-vector-element (vector-ref syllax syllable1))
” ”
(random-vector-element (vector-ref syllax syllable2)))))])))
;b
#|
> (phrase 0 csc151-syllax)
“”
> (phrase 1 csc151-syllax)
“list”
> (phrase 1 csc151-syllax)
“sort”
> (phrase 1 csc151-syllax)
“lab”
> (phrase 2 csc151-syllax)
“lambda”
> (phrase 2 csc151-syllax)
“lab car”
> (phrase 2 csc151-syllax)
“section”
> (phrase 3 csc151-syllax)
“decompose”
> (phrase 3 csc151-syllax)
“CSC”
> (phrase 3 csc151-syllax)
“cadr test”
> (phrase 3 csc151-syllax)
“section list”
> (phrase 4 csc151-syllax)
“DrRacket”
> (phrase 4 csc151-syllax)
“MP vector”
> (phrase 4 csc151-syllax)
“computer map”
> (phrase 5 csc151-syllax)
“decomposition”
> (phrase 5 csc151-syllax)
“generality”
> (phrase 5 csc151-syllax)
“collaborative”
> (phrase 5 csc151-syllax)
“abstraction Racket”
> (phrase 5 csc151-syllax)
“section abstraction”
> (phrase 6 csc151-syllax)
“lab experiential”
> (phrase 6 csc151-syllax)
“compose collaborate”
> (phrase 6 csc151-syllax)
“algorithm SoLA”
> (phrase 7 csc151-syllax)
“confusing tail recursion”
> (phrase 7 csc151-syllax)
“DrRacket decompose”
;For all different input, the number of syllables are correct.
|#
;c
;;;(define haiku syllax) -> string?
;;; syllax: vector?
;;; Returns a string that consists of a line with five syllables, a line with seven syllables, and a line with five syllables.
(define haiku
(lambda (syllax)
(string-append(phrase 5 syllax)
“\n”
(phrase 7 syllax)
“\n”
(phrase 5 syllax)
“\n”)))
#|
> (display (haiku csc151-syllax))
decomposition
triskaidekaphobia
collaborate match
> (display (haiku csc151-syllax))
string humanities
triskaidekaphobia
exponential pair
|#
;Part 2
;;; (extract-words str) -> list?
;;; str: string?
;;; Returns a list of words from the input string.
(define extract-words
(lambda (str)
(rex-split-string (rex-repeat (rex-char-antiset “‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ”)) str)))
(define test-extract-words
(test-suite
“Tests of extract-words”
(check-equal? (extract-words “apple123”)
‘(“apple”)
“string with a words”)
(check-equal? (extract-words “Hello World 2 3 4”)
‘(“Hello” “World”)
“string with two words”)
(check-equal? (extract-words “wed2356y”)
‘(“wed” “y”)
“random string”)
(check-equal? (extract-words “”)
‘()
“empty string”)))
;b
(define dedup
(lambda (lst)
(letrec ([go (lambda (lst so-far)
(if (null? lst)
(reverse so-far)
(if (not (member? (car lst)(cdr lst)))
(go (cdr lst) (cons (car lst) so-far))
(go (cdr lst) so-far))))])
(go lst null))))
(define test-dedup
(test-suite
“Tests of dedup”
(check-equal? (dedup ‘(1 2 3 4 3 5))
‘(1 2 4 3 5)
“list of numbers”)
(check-equal? (dedup ‘(“Hello” “Hi” “Hi” “World”))
‘(“Hello””Hi” “World”)
“list of strings”)
(check-equal? (dedup ‘(#\a 3 #\$ 3 #\a “Hi”))
‘(#\$ 3 #\a “Hi”)
“random list”)
(check-equal? (dedup ‘())
‘()
“empty list”)))
;Part3
;a
;;; (syllables word) -> integer?
;;; word :string?
;;; Returns how many syllables are in the string ‘word’.
(define syllables
(lambda (word)
(cond
[(equal? (list-ref (string->list word) (- (length (string->list word)) 1)) #\e)
(- (length (rex-split-string (rex-repeat (rex-char-set “aeiou”)) word)) 1)]
[else
(length (rex-split-string (rex-repeat (rex-char-antiset “aeiou”)) word))])))
;b
#|
> (syllables “car”)
1
> (syllables “Mear”)
1
> (syllables “boolean”)
2
> (syllables “syllables”)
2
> (syllables “noyce”)
1
;It works well when 2 vowels make only 1 sound, which means we only count once when two vowels are next to each other
;It also works well when we have a silent ‘e’ at the end of the world, we won’t count the silent ‘e’ at the end.
;However, it doesn’t count ‘y’ when ‘y’ makes the sound of a vowel.
|#
;c
;d
;;;(one-syllable? str) -> boolean?
;;; str : string?
;;; Returns #t if the string contains one syllable, returns #f otherwise.
(define one-syllable?
(lambda (str)
(= (syllables str) 1)))
;;;(one-syllable? str) -> boolean?
;;; str : string?
;;; Returns #t if the string contains two syllable, returns #f otherwise.
(define two-syllable?
(lambda (str)
(= (syllables str) 2)))
;;;(one-syllable? str) -> boolean?
;;; str : string?
;;; Returns #t if the string contains three syllable, returns #f otherwise.
(define three-syllable?
(lambda (str)
(= (syllables str) 3)))
;;;(one-syllable? str) -> boolean?
;;; str : string?
;;; Returns #t if the string contains four syllable, returns #f otherwise.
(define four-syllable?
(lambda (str)
(= (syllables str) 4)))
;;;(one-syllable? str) -> boolean?
;;; str : string?
;;; Returns #t if the string contains five syllable, returns #f otherwise.
(define five-syllable?
(lambda (str)
(= (syllables str) 5)))
(define one-syllable
(filter (section one-syllable? <>)(file->words “1260.txt”)))
(define two-syllable
(filter (section two-syllable? <>)(file->words “1260.txt”)))
(define three-syllable
(filter (section three-syllable? <>)(file->words “1260.txt”)))
(define four-syllable
(filter (section four-syllable? <>)(file->words “1260.txt”)))
(define five-syllable
(filter (section five-syllable? <>)(file->words “1260.txt”)))
;e
(define jane-eyre
(vector
(vector)
(list->vector one-syllable)
(list->vector two-syllable)
(list->vector three-syllable)
(list->vector four-syllable)
(list->vector five-syllable)))
#|
> (display (haiku jane-eyre))
representation
knowing communicated
regeneration
> (display (haiku jane-eyre))
dishonour walked
before imagination
life introduced
|#
;Part 4
;a
;;;(might-rhyme? word1 word2) -> boolean?
;;; word1 : string?
;;; word2 : string?
;;; Returns #t if the two words share the last three characters; returns #f otherwise.
(define might-rhyme?
(lambda (word1 word2)
(if (and (>= (string-length word1) 3)(>= (string-length word2) 3))
(equal? (substring word1 (- (string-length word1) 3)(string-length word1))
(substring word2 (- (string-length word2) 3)(string-length word2)))
(if (< (string-length word1) (string-length word2))
(equal? word1
(substring word2 (- (string-length word2) (string-length word1))(string-length word2)))
(equal? word2
(substring word1 (- (string-length word1) (string-length word2))(string-length word1)))))))
;b
;"wind" "mind"
;"love" "move"
;"bough" "cough"
;"gone" "alone"
;"daughter" "laughter"
;"there" "here"
;c
;"today" "away"
;"late" "make"
;"mad" "hat"
;"bee" "tree"
;"enjoy" "distroy"
;"motion" "ocean"
;d
; I found words end with "ate" and "ake" are likely to rhyme. For instance, late, make, mate, shake, awake, date.
;e
;;;(rhymes? word1 word2) -> boolean?
;;; word1 : string?
;;; word2 : string?
;;; Returns #t if the two words appear to rhyme; returns #f otherwise.
(define rhymes?
(lambda (word1 word2)
(if (and (>= (string-length word1) 3)(>= (string-length word2) 3))
(or (equal? (substring word1 (- (string-length word1) 3)(string-length word1))
(substring word2 (- (string-length word2) 3)(string-length word2)))
(and (equal? (substring word1 (- (string-length word1) 3)(string-length word1)) “ate”)
(equal? (substring word2 (- (string-length word2) 3)(string-length word2)) “ake”))
(and (equal? (substring word1 (- (string-length word1) 3)(string-length word1)) “ake”)
(equal? (substring word2 (- (string-length word2) 3)(string-length word2)) “ate”)))
(if (< (string-length word1) (string-length word2))
(equal? word1
(substring word2 (- (string-length word2) (string-length word1))(string-length word2)))
(equal? word2
(substring word1 (- (string-length word1) (string-length word2))(string-length word1)))))))
;f
;;; (rhymes-wtih word words) -> list?
;;; word : string?
;;; words : list?
;;; Returns a list that contains all of the words in ‘words’ that appear to rhyme with ‘word’.
(define rhymes-with
(lambda (word words)
(letrec ([go
(lambda (word words so-far)
(if (null? words)
(reverse so-far)
(if (rhymes? word (car words))
(go word (cdr words) (cons (car words) so-far))
(go word (cdr words) so-far))))])
(go word words null))))
;g
;;; (random-elt lst) –> value?
;;; lst: list?, a non-empty list
;;; Returns a random element from lst.
(define random-elt
(lambda (lst)
(list-ref lst (random (length lst)))))
;;; (abab words) -> string?
;;; words : list?
;;; Returns a string that represents a “random” quatrain of four lines of four words.
;;; The last words of the first and third lines must rhyme, as must the last words of the second and fourth lines
(define abad
(lambda (words)
(let* ([first-word (random-elt words)]
[second-word (random-elt words)]
[third-word (random-elt (rhymes-with first-word words))]
[fourth-word (random-elt (rhymes-with second-word words))])
(string-append (random-elt words)
” ”
(random-elt words)
” ”
(random-elt words)
” ”
first-word
“\n”
(random-elt words)
” ”
(random-elt words)
” ”
(random-elt words)
” ”
second-word
“\n”
(random-elt words)
” ”
(random-elt words)
” ”
(random-elt words)
” ”
third-word
“\n”
(random-elt words)
” ”
(random-elt words)
” ”
(random-elt words)
” ”
fourth-word
“\n”))))
#|
> (display (abad (file->words “1260.txt”)))
to them hearth would
s should so Then
heretofore Mr Bessie could
was their waistcoat then
> (display (abad (file->words “1260.txt”)))
Zembla arrangement a mortal
having of ecstatic for
an fetched fallen total
whose and sensations for
> (display (abad (file->words “1260.txt”)))
days whence and whole
sir in my What
says my damp whole
has the I at
> (display (abad (file->words “1260.txt”)))
watchful Who as for
As asked stern trouble
me hundreds where or
I for by double
|#
;Part 5
;a
;;; (remove-last str) -> string?
;;; str : string?
;;; Return the string without the last character.
(define remove-last
(lambda (str)
(substring str 0 (- (string-length str) 1))))
;;; (sentence-ends str) -> list?
;;; str : string?
;;; Returns a list of words in ‘str’ that end sentences.
(define sentence-ends
(lambda (str)
(map (section remove-last <>)
(append (filter (section string-suffix? <> “.”) (string-split str))
(filter (section string-suffix? <> “?”) (string-split str))
(filter (section string-suffix? <> “!”) (string-split str))))))
(define test-sentence-ends
(test-suite
“Tests of sentence ends”
(check-equal? (sentence-ends “The cat ate the hat. The rat sat.”)
‘(“hat” “sat”)
“sentence1 from the reading”)
(check-equal? (sentence-ends “Do you like blue mac and cheese? No I don’t, it makes me sneeze!”)
‘(“cheese” “sneeze”)
“sentence2 from the reading”)
(check-equal? (sentence-ends “The cat sat on the hat. ‘Where is my hat?’ asked the rat. It’s now a flat hat. How ’bout that? Will the fat rat jump on that brat cat?”)
‘(“hat” “rat” “hat” “that” “cat”)
“sentence3 from the reading”)
(check-equal? (sentence-ends “”)
‘()
“empty string”)))
;b
;;; (sentence-start str) -> list?
;;; str : string?
;;; Returns a list, which contains all of the words in str that begin sentences.
(define sentence-starts
(lambda (str)
(let([list-of-words (string-split str)])
(letrec ([go
(lambda (list-of-words so-far)
(if (null? (cdr list-of-words))
(reverse (dedup so-far))
(if (or (string-suffix? (car list-of-words) “.”)
(string-suffix? (car list-of-words) “?”)
(string-suffix? (car list-of-words) “!”))
(go (cdr list-of-words)(cons (cadr list-of-words) so-far))
(go (cdr list-of-words) so-far))))])
(go list-of-words (list (list-ref list-of-words 0)))))))
(define test-sentence-starts
(test-suite
“Tests of sentence starts”
(check-equal? (sentence-starts “The cat ate the hat. The rat sat.”)
‘(“The”)
“sentence1 from the reading”)
(check-equal? (sentence-starts “Do you like blue mac and cheese? No I don’t, it makes me sneeze!”)
‘(“Do” “No”)
“sentence2 from the reading”)
(check-equal? (sentence-starts “The cat sat on the hat. \”Where is my hat?\” asked the rat. It’s now a flat hat. How ’bout that? Will the fat rat jump on that brat cat who sat?”)
‘(“The” “\”Where” “It’s” “How” “Will”)
“sentence3 from the reading”)
(check-equal? (sentence-starts “Hello World! Nice to see you.”)
‘(“Hello” “Nice”)
“random sentence”)))
;c
;;;(right-neighbors word words) -> list?
;;; word : string?
;;; words : list?
;;; Returns a list of strings, which contains all of the words that immediately follow ‘word’ in ‘words’.
(define right-neighbors
(lambda (word words)
(letrec ([go
(lambda (word words so-far)
(if (null? words)
(reverse so-far)
(if (equal? word (car words))
(go word (cdr words) (cons (cadr words) so-far))
(go word (cdr words) so-far))))])
(go word words null))))
(define cat-thing (extract-words “The cat sat on the hat. \”Where is my hat?\” asked the rat. It’s now a flat hat. How ’bout that? Will the fat rat jump on that brat cat who sat?”))
(define test-right-neighbors
(test-suite
“Tests of right neighbors”
(check-equal? (right-neighbors “hat” cat-thing)
‘(“Where” “asked” “How”)
“example1 from the reading”)
(check-equal? (right-neighbors “The” cat-thing)
‘(“cat”)
“example2 from the reading”)
(check-equal? (right-neighbors “the” cat-thing)
‘(“hat” “rat” “fat”)
“example3 from the reading”)
(check-equal? (right-neighbors “Will” cat-thing)
‘(“the”)
“example4 from the reading”)
(check-equal? (right-neighbors “computer” cat-thing)
‘()
“example5 from the reading”)))
;d
;;; (random-sentence all-words start-words end-words) -> string?
;;; all-words : list?
;;; start-words : string?
;;; end-words : string?
;;; Return a string, which is a sentence. The words are selected from the list ‘all-words’.