Guest User

Untitled

a guest
Oct 15th, 2018
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.05 KB | None | 0 0
  1. # CSCI0190 (Fall 2018)
  2. provide *
  3.  
  4. import shared-gdrive("map-reduce-support.arr",
  5. "1F87DfS_i8fp3XeAyclYgW3sJPIf-WRuH") as support
  6. import lists as L
  7.  
  8. type Tv-pair = support.Tv-pair
  9. tv = support.tv
  10. wc-map = support.wc-map
  11. wc-reduce = support.wc-reduce
  12.  
  13. # DO NOT CHANGE ANYTHING ABOVE THIS LINE
  14.  
  15.  
  16.  
  17.  
  18. fun count<A>(target :: A, a :: List<A>, eq-checker :: (A, A -> Boolean))
  19. -> Number:
  20. doc: "counts quantity of target in a"
  21. fun el-checker(el, cnt):
  22. if eq-checker(el, target):
  23. cnt + 1
  24. else:
  25. cnt
  26. end
  27. end
  28. a.foldl(el-checker, 0)
  29. where:
  30. count(3, [list: 1, 2, 3], lam(x, a): x == a end) is 1
  31. count(3, [list: 3, 2, 3], lam(x, a): x == a end) is 2
  32. count(4, [list: 1, 2, 3], lam(x, a): x == a end) is 0
  33. end
  34.  
  35. fun lst-same-els<A>(
  36. a :: List<A>,
  37. b :: List<A>,
  38. eq-checker :: (A, A -> Boolean))
  39. -> Boolean:
  40. doc: "checks whether two lists have the same elements in the same quantity"
  41. fun same-count(el, acc):
  42. acc and (count(el, a, eq-checker) == count(el, b, eq-checker))
  43. end
  44. (a.length() == b.length()) and a.foldl(same-count, true)
  45. where:
  46. lst-same-els([list: 1, 2, 3], [list: 1, 2, 3], lam(x, a): x == a end)
  47. is true
  48. lst-same-els([list: 1, 2, 3], [list: 1, 2, 3], lam(x, a): x == a end)
  49. is true
  50. lst-same-els([list: 1, 2, 3], [list: 2, 1, 3], lam(x, a): x == a end)
  51. is true
  52. lst-same-els([list: 1, 2, 2], [list: 2, 1], lam(x, a): x == a end)
  53. is false
  54. lst-same-els([list: 1, 2, 2], [list: 2, 1, 1], lam(x, a): x == a end)
  55. is false
  56. end
  57.  
  58.  
  59.  
  60.  
  61. ## A. Your map-reduce definition
  62.  
  63. fun map-reduce<A,B,M,N,O>(input :: List<Tv-pair<A,B>>,
  64. mapper :: (Tv-pair<A,B> -> List<Tv-pair<M,N>>),
  65. reducer :: (Tv-pair<M,List<N>> -> Tv-pair<M,O>)) -> List<Tv-pair<M,O>>:
  66. doc:```Applies the mapper function on every tv-pair in input, then reduces all
  67. the mapper outputs to a list of tv-pair outputs organized by tags```
  68. #first: apply the mapper function to every tv-pair in the input
  69. #this will result in a List<List<Tv-pair<M,N>>>
  70. mapped-inputs = map(mapper, input)
  71.  
  72. #second: extract the inputs from list of list of tv-pairs into a
  73. #List containing every tv-pair
  74. #this will result in a List<Tv-pair<M, N>>
  75. extracted-inputs = extract-all-tv-pairs(mapped-inputs)
  76.  
  77. #third: organize all inputs by tags and a list of all its values
  78. #this will result in a List<Tv-pair<M, List<N>>>
  79. organized-inputs = organize-all-tv-pairs(extracted-inputs)
  80.  
  81. #fourth: apply the reducer function to every tag and a list of its values
  82. #into a tag and a single value, return that output
  83. #this will result in a List<Tv-pair<M, O>>
  84. map(reducer, organized-inputs)
  85.  
  86. where:
  87. nothing
  88. end
  89.  
  90. #map-reduce helper functions
  91. fun extract-all-tv-pairs<M,N>(all-tv-pairs :: List<List<Tv-pair<M, N>>>)
  92. -> List<Tv-pair<M, N>>:
  93. doc:```extracts the tv-pairs from every inner list in all-tv-pairs
  94. into a single list```
  95. cases (List) all-tv-pairs:
  96. #if outer list empty, have traversed through every tv-pair, return empty
  97. | empty => empty
  98. #i.e. all-tv-pairs has more elements
  99. | link(flists, rlists) =>
  100. #add all first list elements to extracted rest of lists
  101. L.append(flists, extract-all-tv-pairs(rlists))
  102. end
  103. where:
  104. #base cases: ensure that doubly nested list produces single list
  105. extract-all-tv-pairs(empty) is empty
  106. extract-all-tv-pairs(
  107. [list:
  108. [list: ]]) is [list: ]
  109. #all lists in single inner list
  110. extract-all-tv-pairs(
  111. [list:
  112. [list:
  113. tv("Hi", "there")]])
  114. is [list: tv("Hi", "there")]
  115. extract-all-tv-pairs(
  116. [list:
  117. [list:
  118. tv("Hi", "there"),
  119. tv("Hello", "there")]])
  120. is [list: tv("Hi", "there"), tv("Hello", "there")]
  121. #all elements in different lists
  122. extract-all-tv-pairs(
  123. [list:
  124. [list:
  125. tv("Hi", "there"),
  126. tv("Hello", "there"),
  127. tv("good", "day")],
  128. [list:
  129. tv("Hello", "friend"),
  130. tv("Hello", "family"),
  131. tv("ahoy", "captain")]])
  132. is [list: tv("Hi", "there"), tv("Hello", "there"), tv("good", "day"),
  133. tv("Hello", "friend"), tv("Hello", "family"), tv("ahoy", "captain")]
  134. #longer lists, with some emptys
  135. extract-all-tv-pairs(
  136. [list:
  137. [list:
  138. tv("Hi", "there"),
  139. tv("Hello", "there"),
  140. tv("good", "day")],
  141. [list:
  142. tv("abc", "def"),
  143. tv("zyx", "tuv"),
  144. tv("live", "laugh")],
  145. [list: ],
  146. [list: ],
  147. [list:
  148. tv("Hello", "friend"),
  149. tv("Hello", "family"),
  150. tv("ahoy", "captain")]])
  151. is [list: tv("Hi", "there"), tv("Hello", "there"), tv("good", "day"),
  152. tv("abc", "def"), tv("zyx", "tuv"), tv("live", "laugh"),
  153. tv("Hello", "friend"), tv("Hello", "family"), tv("ahoy", "captain")]
  154. end
  155.  
  156. fun organize-all-tv-pairs<M,N>(all-tv-pairs :: List<Tv-pair<M, N>>)
  157. -> List<Tv-pair<M, List<N>>>:
  158. doc:"organizes tv pairs with like tags to contain a list of their values"
  159. cases (List) all-tv-pairs:
  160. #if empty, have traversed through every all-tv-pair
  161. | empty => empty
  162. | link(fpair, rpair) =>
  163. first-tag = fpair.tag
  164. #collects all tv-pairs where tv.tag = first-tag from rest
  165. same-tag-as-first =
  166. filter(
  167. #lambda checks if x.tag is same as first.tag
  168. lam(x :: Tv-pair) -> Boolean: x.tag == first-tag end,
  169. all-tv-pairs)
  170.  
  171. #organizes all tv-pairs with common tag into list of their vals
  172. collect-all-vals =
  173. map(
  174. #lamdba extracts values from tv-pair
  175. lam<A>(x :: Tv-pair) -> A: x.value end,
  176. same-tag-as-first)
  177.  
  178. #creates new-tv-pair using the first-tag and the list of their values
  179. new-tv-pair = tv(first-tag, collect-all-vals)
  180.  
  181. #removes pairs with same tag as first and recurs on it
  182. diff-tag-than-first =
  183. filter(
  184. #lambda checks if x.tag is not same as first.tag
  185. lam(x :: Tv-pair) -> Boolean: not(x.tag == first-tag) end,
  186. rpair)
  187. link(new-tv-pair, organize-all-tv-pairs(diff-tag-than-first))
  188. end
  189. where:
  190. #base case: empty list
  191. organize-all-tv-pairs([list: ])
  192. #all tv-pairs have distinct tags
  193. organize-all-tv-pairs(
  194. [list: tv("Hello", "hi")])
  195. is [list: tv("Hello", [list: "hi"])]
  196. organize-all-tv-pairs(
  197. [list: tv("Hello", "hi"), tv("hola", "hey"), tv("ahoy", "friend")])
  198. is [list:
  199. tv("Hello", [list: "hi"]),
  200. tv("hola", [list: "hey"]),
  201. tv("ahoy", [list: "friend"])]
  202. #ensure that tv-pairs does not mix up tag with value
  203. organize-all-tv-pairs(
  204. [list: tv("Hello", "hi"), tv("hola", "hi"), tv("ahoy", "hi")])
  205. is [list:
  206. tv("Hello", [list: "hi"]),
  207. tv("hola", [list: "hi"]),
  208. tv("ahoy", [list: "hi"])]
  209. #tv-pairs share some tags
  210. organize-all-tv-pairs(
  211. [list:
  212. tv("Hi", "there"), tv("Hello", "there"), tv("good", "day"),
  213. tv("Hello", "friend"), tv("Hello", "family"), tv("ahoy", "captain")])
  214. is [list:
  215. tv("Hi", [list: "there"]),
  216. tv("Hello", [list: "there", "friend", "family"]),
  217. tv("good", [list: "day"]),
  218. tv("ahoy", [list: "captain"])]
  219. organize-all-tv-pairs([list: tv("Hi", "there"), tv("Hello", "there"),
  220. tv("good", "day"), tv("abc", "def"), tv("zyx", "tuv"),
  221. tv("Hi", "laugh"), tv("Hello", "friend"), tv("Hello", "family"),
  222. tv("zyx", "captain"), tv("abc", "alphabet")])
  223. is [list:
  224. tv("Hi", [list: "there", "laugh"]),
  225. tv("Hello", [list: "there", "friend", "family"]),
  226. tv("good", [list: "day"]),
  227. tv("abc", [list: "def", "alphabet"]),
  228. tv("zyx", [list: "tuv", "captain"])]
  229. end
  230.  
  231. fun anagram-map<A,B,M,N>(tv-input :: Tv-pair<A,B>) -> List<Tv-pair<M,N>>:
  232. doc: ```Mapper for anagram, splits the list of words (value) and maps a tv
  233. with a tag of a alphabetized word onto each one```
  234. split-values = string-split-all(tv-input.value, " ")
  235. split-values.map(lam(x): tv-producer(x) end)
  236. end
  237.  
  238. fun tv-producer<M,N>(string-input :: String) -> Tv-pair<M,N>:
  239. doc: ```Generates the new tv for the given string, with the tag being the
  240. alphabetized string, and the value being the string itself.```
  241. num-string = string-to-code-points(string-input)
  242. sorted-num-string = num-string.sort()
  243. sorted-tag = string-from-code-points(sorted-num-string)
  244. tv(sorted-tag, string-input)
  245. end
  246.  
  247. check "anagram-map tests":
  248. #Single-case
  249. anagram-map(tv("file1", "a")) is [list: tv("a", "a")]
  250. #Case with multiple tvs
  251. anagram-map(tv("file1", "box cat dog Sass")) is
  252. [list: tv("box", "box"), tv("act", "cat"), tv("dgo", "dog"),
  253. tv("Sass", "Sass")]
  254. anagram-map(tv("file1", "obx act odg aSss")) is
  255. [list: tv("box", "obx"), tv("act", "act"), tv("dgo", "odg"),
  256. tv("Sass", "aSss")]
  257. #Case with repetition (identical and permutations)
  258. anagram-map(tv("file1", "box obx oxb xob obx")) is
  259. [list: tv("box", "box"), tv("box", "obx"), tv("box", "oxb"), tv("box", "xob"),
  260. tv("box", "obx")]
  261. end
  262.  
  263. fun anagram-reduce<M,N,O>(input-tv :: Tv-pair<M, List<N>>)
  264. -> Tv-pair<M, O>:
  265. doc: ```Reducer for anagram. Essentially just deletes duplicate strings from
  266. each list```
  267. tv(input-tv.tag, L.distinct(input-tv.value))
  268. end
  269.  
  270. fun anagram-list(tv-pair :: List<Tv-pair>)
  271. -> List<List>:
  272. doc: "Converts a list of tv-pair to a list of their values"
  273. cases (List) tv-pair:
  274. | empty => empty
  275. | link(f, r) => link(f.value, anagram-list(r))
  276. end
  277. end
  278.  
  279. check "anagram-list checks":
  280. #Checks the base case
  281. anagram-list(empty) is empty
  282. #Checks the single case
  283. anagram-list([list: tv("box", [list: "Obx"])]) is [list: [list: "Obx"]]
  284. #Checks a more complex case
  285. anagram-list([list:
  286. tv("box-group", [list: "box", "obx", "oxb", "xob", "bxo"]),
  287. tv("cat-group", [list: "cat", "act", "atc", "tac"])]) is
  288. [list: [list: "box", "obx", "oxb", "xob", "bxo"],
  289. [list: "cat", "act", "atc", "tac"]]
  290. end
  291.  
  292. fun is-equiv(new-tv :: List<String>, new-check-list :: List<List>)
  293. -> Boolean:
  294. doc: "Checks if a tv's list is inside the list of tv-lists"
  295. cases (List) new-check-list:
  296. | empty => false
  297. | link(f, r) =>
  298. lst-same-els(new-tv, f, lam(x, a): x == a end) or is-equiv(new-tv, r)
  299. end
  300. end
  301.  
  302. check "is-equiv checks":
  303. #Checks the base case
  304. is-equiv(empty, [list: [list: "box", "obx", "oxb", "xob", "bxo"]]) is false
  305. #Checks for case-variations changes between inputs
  306. is-equiv([list: "box", "obx", "oxb", "xob", "bxo"],
  307. [list: [list: "bOx", "obx", "oxb", "xob", "bxo"],
  308. [list: "cat", "act", "atc", "tac"]]) is false
  309. #Checks for variations in order
  310. is-equiv([list: "obx", "box", "bxo", "xob", "oxb"],
  311. [list: [list: "box", "obx", "oxb", "xob", "bxo"],
  312. [list: "cat", "act", "atc", "tac"]]) is true
  313. end
  314.  
  315. fun anagram-check(tv-list :: List<Tv-pair>, check-list :: List<Tv-pair>)
  316. -> Boolean:
  317. doc: "Checks if the tv-list is equivalent to the expected check-list"
  318. a-list=anagram-list(tv-list)
  319. b-list=anagram-list(check-list)
  320. bool-list =
  321. a-list.map(lam(x): is-equiv(x, b-list) end)
  322. (not(bool-list.member(false)) and (a-list.length() == b-list.length()))
  323. end
  324.  
  325. check "anagram-check":
  326. #Generic check for anagram-check
  327. anagram-check(map-reduce([list:
  328. tv("file1", "box cat dog Sass"), tv("file2", "obx act odg aSss"),
  329. tv("file3", "oxb atc ogd xob Ssas box"),
  330. tv("file4", "tac god bxo sass")],
  331. anagram-map, anagram-reduce),
  332. [list:
  333. tv("box-group", [list: "box", "obx", "oxb", "xob", "bxo"]),
  334. tv("cat-group", [list: "cat", "act", "atc", "tac"]),
  335. tv("dog-group", [list: "dog", "odg", "ogd", "god"]),
  336. tv("Sass-group", [list: "Sass", "aSss", "Ssas"]),
  337. tv("sass-group", [list: "sass"])]) is true
  338. #Checks for character-case
  339. anagram-check(map-reduce([list:
  340. tv("file1", "box cat"), tv("file2", "oBx cAt act")],
  341. anagram-map, anagram-reduce),
  342. [list:
  343. tv("box", [list: "box"]),
  344. tv("act", [list: "cat", "act"]),
  345. tv("Act", [list: "cAt"]),
  346. tv("Box", [list: "oBx"])])
  347. is true
  348. anagram-check(map-reduce([list:
  349. tv("file1", "box cat"), tv("file2", "oBx cAt act")],
  350. anagram-map, anagram-reduce),
  351. [list:
  352. tv("box", [list: "box"]),
  353. tv("act", [list: "cat", "act", "cAt"]),
  354. tv("Box", [list: "oBx"])])
  355. is false
  356. end
  357.  
  358. recommend(title :: String,
  359. book-records :: List<Tv-pair<String, String>)
  360. -> Tv-pair<Number, List<String>>
Add Comment
Please, Sign In to add comment