-
Notifications
You must be signed in to change notification settings - Fork 0
/
q2.tex
137 lines (105 loc) · 5.34 KB
/
q2.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
%%% Question 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\question This question is about recursive and higher-order functions.
\begin{parts}
\part[4] Define a function
\begin{center}
\haskellIn{isPrime :: Integer -> Bool}
\end{center}
which given an integer value, determines whether it is a prime number. For example, \haskellIn{isPrime 3} should evaluate to \haskellIn{True}. \droppoints
\begin{solution}
\emph{Application.} A simple solution using a list comprehension is:
\begin{verbatim}
isPrime :: Integer -> Bool
isPrime n = null [x | x <- [2..n-1], n `mod` x == 0]
\end{verbatim}
\end{solution}
\part[2] With the help of \haskellIn{isPrime}, write a definition
\begin{center}
\haskellIn{primes :: [Integer]}
\end{center}
which represents the \emph{infinite} list of prime numbers. For example, the expression \haskellIn{take 4 primes} should evaluate to \haskellIn{[2,3,5,7]}. \droppoints
\begin{solution} \emph{Application.}
\begin{verbatim}
primes :: [Integer]
primes = [n | n <- [2..], isPrime n]
\end{verbatim}
\end{solution}
\part Two words are anagrams of each other if they are made up of the same characters. For example, \haskellIn{"team"} and \haskellIn{"meta"} are anagrams of each other. One method for determining whether two words are anagrams of each other is to assign a unique prime number to each character in the alphabet, map each character in a given word to its corresponding prime number, and then calculate the product of all those numbers. The product of two or more prime numbers is guaranteed to be unique for those prime factors so if two words result in the same product, they must be anagrams of each other.
\begin{subparts}
\subpart[4] Write a function
\begin{center}
\haskellIn{toPrime :: Char -> Integer}
\end{center}
which maps each character in the alphabet to a unique prime number. For example, \haskellIn{toPrime 'A'} and \haskellIn{toPrime 'a'} could evaluate to \haskellIn{2} while \haskellIn{toPrime 'C'} could evaluate to \haskellIn{5}. \emph{Hint}: the \haskellIn{ord :: Char -> Int} function maps characters to their corresponding integer value in the ASCII encoding. \droppoints
\begin{solution}
\emph{Application.}
\begin{verbatim}
toPrime :: Char -> Integer
toPrime c = primes !! (ord (toUpper c) - ord 'A')
\end{verbatim}
\end{solution}
\subpart[3] With the help of \haskellIn{toPrime}, define a function
\begin{center}
\haskellIn{score :: String -> Integer}
\end{center}
which calculates the product of all the prime numbers for all the characters in the input string. For example, assuming that \haskellIn{toPrime} maps \haskellIn{'a'} to \haskellIn{2}, \haskellIn{'b'} to \haskellIn{3}, \haskellIn{'c'} to \haskellIn{5} and so on, \haskellIn{score "team"} should evaluate to \haskellIn{64042}. \droppoints
\begin{solution}
\emph{Application.}
\begin{verbatim}
score :: String -> Integer
score = product . map toPrime
\end{verbatim}
\end{solution}
\subpart[2] With the help of \haskellIn{score}, define a function
\begin{center}
\haskellIn{isAnagram :: String -> String -> Bool}
\end{center}
which determines whether two \haskellIn{String} values are anagrams of each other. For example, \haskellIn{isAnagram "team" "meta"} should evaluate to \haskellIn{True}. \droppoints
\begin{solution}
\emph{Application.}
\begin{verbatim}
isAnagram :: String -> String -> Bool
isAnagram xs ys = score xs == score ys
\end{verbatim}
\end{solution}
\subpart[5] With the help of the previous definitions, define a function
\begin{center}
\haskellIn{anagrams :: [String] -> [(String, [String])]}
\end{center}
which, given a list of \haskellIn{String} values representing a list of words, returns a list of the same size in which every input word is mapped to a list of its anagrams. For example: \\[1mm]
\haskellIn{anagrams ["team", "meta", "meat", "late"]} \\
\haskellIn{=> [("team",["meta","meat"]),("meta",["team","meat"]),} \\
\haskellIn{ ("meat",["team","meta"]),("late",[])]} \droppoints
\begin{solution}
\emph{Application.}
\begin{verbatim}
anagrams :: [String] -> [(String, [String])]
anagrams xs = map (go xs) xs
where go ys x = (x, [y | y <- ys,
isAnagram x y, x /= y])
\end{verbatim}
\end{solution}
\ifprintanswers \else \pagebreak \fi
\subpart[5] With the help of the previous definitions, define a function
\begin{center}
\haskellIn{subgrams :: [String] -> [(String, [String])]}
\end{center}
which behaves like \haskellIn{anagrams}, except it also considers words which do not use every character from the original word. For example:\\[1mm]
\haskellIn{subgrams ["team", "meta", "eat", "tea"]} \\
\haskellIn{=> [("team",["meta","eat","tea"]),} \\
\haskellIn{ ("meta",["team","eat","tea"]),}\\
\haskellIn{ ("eat",["tea"]),("tea",["eat"])]} \droppoints
\begin{solution}
\emph{Application.}
\begin{verbatim}
subgrams :: [String] -> [(String, [String])]
subgrams xs = map (go xs) xs
where go ys x = (x, nub [y | y <- ys,
w <- subsequences x,
w /= [],
isAnagram y w,
x /= y])
\end{verbatim}
\end{solution}
\end{subparts}
\end{parts}