-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path889823.hs
More file actions
284 lines (220 loc) · 8.62 KB
/
Copy path889823.hs
File metadata and controls
284 lines (220 loc) · 8.62 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
--
-- MATHFUN
--
-- UP889823
--
import Data.Char
import Data.List
import Text.Printf
import Data.Foldable
import Data.Ord
import Numeric
--
-- Types (define Place type here)
type Place = (String, Float, Float, [Int])
--
testData :: [Place]
testData = [("London" ,(51.5), (-0.1), [0, 0, 5, 8, 8, 0, 0]),
("Cardiff" ,(51.5), (-3.2), [12, 8, 15, 0, 0, 0, 2]),
("Norwich" ,(52.6), ( 1.3), [0, 6, 5, 0, 0, 0, 3]),
("Birmingham" ,(52.5), (-1.9), [0, 2, 10, 7, 8, 2, 2]),
("Liverpool" ,(53.4), (-3.0), [8, 16, 20, 3, 4, 9, 2]),
("Hull" ,(53.8), (-0.3), [0, 6, 5, 0, 0, 0, 4]),
("Newcastle" ,(55.0), (-1.6), [0, 0, 8, 3, 6, 7, 5]),
("Belfast" ,(54.6), (-5.9), [10, 18, 14, 0, 6, 5, 2]),
("Glasgow" ,(55.9), (-4.3), [7, 5, 3, 0, 6, 5, 0]),
("Plymouth" ,(50.4), (-4.1), [4, 9, 0, 0, 0, 6, 5]),
("Aberdeen" ,(57.1), (-2.1), [0, 0, 6, 5, 8, 2, 0]),
("Stornoway" ,(58.2), (-6.4), [15, 6, 15, 0, 0, 4, 2]),
("Lerwick" ,(60.2), (-1.1), [8, 10, 5, 5, 0, 0, 3]),
("St Helier" ,(49.2), (-2.1), [0, 0, 0, 0, 6, 10, 0])]
--
-- Your functional code goes here
--
-- i
displayLocations :: [Place] -> [String]
displayLocations x = [name | (name, _, _, _) <- x]
--ii
averageRainfall :: String -> [Place] -> Float
averageRainfall city ((location, float1, float2, int):place)
| city == location = average
| otherwise = averageRainfall city place
where
average = fromIntegral (sum int) / 7
-- iii
rainfallPadding :: Int -> Char -> String -> String
rainfallPadding number char string = replicate ( number - length string) char ++ string
locationPadding :: Int -> Char -> String -> String
locationPadding number char string = string ++ replicate ( number - length string) char
placeToString :: Place -> String
placeToString (location, _, _, rainfall) = locationPadding 10 ' ' location ++ intercalate " | " (map(rainfallPadding 3 ' ' . show)rainfall)
placesToString :: [Place] -> String
placesToString = concat . intersperse "\n" . map placeToString
-- iv
dryNames :: [Place] -> Int -> [String]
dryNames place days = [location | (location, _, _, rainfall) <- place, rainfall !!(days-1) == 0]
-- v
updateRainfall :: [Place] -> [Int] -> [Place]
updateRainfall _ [] = []
updateRainfall ((location, float1, float2, rainfall):place) (x:xs) =
((location, float1, float2, x: init rainfall):updateRainfall place xs)
--vi
replaceData :: String -> Place -> [Place] -> [Place]
replaceData old new [] = []
replaceData old new ((location,float1,float2,rainfall):place)
| old == location = new : replaceData old new place
| otherwise = (location,float1,float2,rainfall) : replaceData old new place
--vii
dist2 :: Float -> Float -> Float -> Float -> Float
dist2 x1 y1 x2 y2 = sqrt((x2-x1)^2 + (y2-y1)^2)
dryYesterday :: Place -> Bool
dryYesterday (_, _, _, r) = r !!0 == 0
closestPlace :: Float -> Float -> [Place] -> Place
closestPlace x y = (minimumBy (comparing (dist2P x y))) . filter dryYesterday
dist2P :: Float -> Float -> Place -> Float
dist2P x y (_, x', y', _) = dist2 x y x' y'
placeName :: Place -> String
placeName (s, _, _, _) = s
closestPlaceName :: Float -> Float -> [Place] -> String
closestPlaceName x y = placeName . closestPlace x y
--viii --Rainfall Map
--
-- Demo
--
demo :: Int -> IO ()
demo 1 = print (displayLocations testData) -- display the names of all the places
demo 2 = printf "%.2f\n" (averageRainfall "Cardiff" testData) -- display, to two decimal places, the average rainfall in Cardiff
demo 3 = putStrLn (placesToString testData)
demo 4 = print (dryNames testData 2) -- display the names of all places that were dry two days ago
demo 5 = print (updateRainfall testData [0,8,0,0,5,0,0,3,4,2,0,8,0,0]) -- update the data with most recent rainfall
--[0,8,0,0,5,0,0,3,4,2,0,8,0,0] (and remove oldest rainfall figures)
demo 6 = print (replaceData "Plymouth" ("Portsmouth", 50.8, (-1.1), [0, 0, 3, 2, 5, 2, 1]) testData)
-- replace "Plymouth" with "Portsmouth" which has
-- -- location 50.8 (N), -1.1 (E) and rainfall 0, 0, 3, 2, 5, 2, 1
demo 7 = putStrLn (closestPlaceName (50.9) (-1.3) testData)
-- display the name of the place closest to 50.9 (N), -1.3 (E) that was dry yesterday
demo 8 = plotterCords testData
--
-- Screen Utilities (use these to do the rainfall map - note that these do
-- not work in WinGHCi on Windows, so use GHCi.)
--
type ScreenPosition = (Int,Int)
-- Clears the screen
clearScreen :: IO ()
clearScreen = putStr "\ESC[2J"
-- Moves to a position on the screen
goTo :: ScreenPosition -> IO ()
goTo (x, y) = putStr ("\ESC[" ++ show y ++ ";" ++ show x ++ "H")
-- Writes a string at a position on the screen
writeAt :: ScreenPosition -> String -> IO ()
writeAt position text = do
goTo position
putStr text
--
-- Your rainfall map code goes here
--
plotterCords :: [Place] -> IO()
plotterCords ((location, degN, degE, rainfall):place) = do
clearScreen
plot ((location, degN, degE, rainfall):place)
goTo (0,50)
plot :: [Place] -> IO()
plot [] = return()
plot ((location, degN, degE, rainfall):place) = do
writeAt (xAxis degE, yAxis degN)
("+ " ++ location ++ " " ++ printf "%.2f" (avgRain rainfall))
plot place
xAxis, yAxis :: Float -> Int
xAxis x = round(((x + 6.6) / 0.1) -1)
yAxis y = round(((y - 61.25) / (-0.25)) -1)
avgRain :: [Int] -> Float
avgRain int = fromIntegral (sum int) / 7
--
-- Your user interface (and loading/saving) code goes here
--
menu = "\n \n Haskell Rain Menu \n \n 1 - Display Names of all the locations"++
"\n 2 - Find the average rainfall for a given place \n 3 - Display all locatins and their rainfall" ++
"\n 4 - Find all the dry locations a certain number of days ago \n 5 - Update the data" ++
"\n 6 - Replace a location with a new one \n 7 - Find the closest dry place yesterday when you pass in coordinates" ++
"\n 8 - Display a map of all the locations in the data \n 9 - Exit Program \n\n"
main :: IO()
main = do
clearScreen
content <- readFile("places.txt")
let dataFile :: [Place]
dataFile = read content
menuFunction (dataFile)
-- let finalData = show dataFile
-- writeFile ("places.txt") finalData
menuFunction :: [Place] -> IO()
menuFunction place = do
putStrLn "\n\n"
print (displayLocations place)
putStrLn menu
input <- getLine
outputsIO input place
outputsIO :: String -> [Place] -> IO()
outputsIO inp place
| inp == "1" = do
print(displayLocations place)
menuFunction place
| inp == "2" = do
putStr "Please Enter the City: "
city <- getLine
printf "%.2f\n" (averageRainfall city place)
menuFunction place
| inp == "3" = do
putStrLn (placesToString place)
menuFunction place
| inp == "4" = do
putStr "How many days ago : "
days <- getLine
let day = read days
print (dryNames place day)
menuFunction place
| inp == "5" = do
putStr "Enter to new Data in order of the locations you see above: "
newData <- getLine
let dataString = "[" ++ newData ++"]"
let newDatas = read dataString
putStrLn "\n"
print(updateRainfall place newDatas)
menuFunction place
| inp == "6" = do
noSix place
menuFunction place
| inp == "7" = do
putStr "What is the degE: "
degE <- getLine
let degEF = read degE
putStr "What is the degN: "
degN <- getLine
let degNStr = "("++degN++")"
let degNF = read degNStr
putStrLn (closestPlaceName (degNF) (degEF) place)
menuFunction place
| inp == "8" = do
plotterCords place
menuFunction place
| inp == "9" = do
putStrLn "You have exited"
return()
| otherwise = menuFunction place
noSix :: [Place] -> IO()
noSix place = do
putStr "What location would you like to replace: "
oldCity <- getLine
putStr "What is the new location: "
newCity <- getLine
putStr "What is the Degrees North: "
degN <- getLine
let degNF = read degN
putStr "What is the Degrees East: "
degE <- getLine
let degEStr = "("++ degE ++")"
let degEFloat = read degEStr
putStr "What is the ranifall for the last 7 days: "
newData <- getLine
let dataString = "[" ++ newData ++"]"
let newDatas = read dataString
print (replaceData oldCity (newCity, degNF, degEFloat, newDatas) place)