trackler 2.0.0.1 → 2.0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (226) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bump-content +3 -1
  3. data/bin/verify-metadata +2 -2
  4. data/common/exercises/alphametics/canonical-data.json +19 -9
  5. data/common/exercises/food-chain/canonical-data.json +7 -1
  6. data/common/exercises/grains/canonical-data.json +66 -0
  7. data/common/exercises/raindrops/description.md +4 -5
  8. data/common/exercises/triangle/canonical-data.json +81 -54
  9. data/lib/trackler/version.rb +1 -1
  10. data/tracks/c/config.json +26 -19
  11. data/tracks/c/exercises/allergies/makefile +15 -0
  12. data/tracks/c/exercises/allergies/src/allergies.h +21 -0
  13. data/tracks/c/exercises/allergies/src/example.c +32 -0
  14. data/tracks/c/exercises/allergies/src/example.h +26 -0
  15. data/tracks/c/exercises/allergies/test/test_allergies.c +203 -0
  16. data/tracks/c/exercises/allergies/test/vendor/unity.c +1300 -0
  17. data/tracks/c/exercises/allergies/test/vendor/unity.h +274 -0
  18. data/tracks/c/exercises/allergies/test/vendor/unity_internals.h +701 -0
  19. data/tracks/c/exercises/atbash-cipher/makefile +16 -0
  20. data/tracks/c/exercises/atbash-cipher/src/example.c +71 -0
  21. data/tracks/c/exercises/atbash-cipher/src/example.h +7 -0
  22. data/tracks/c/exercises/atbash-cipher/test/test_atbash_cipher.c +113 -0
  23. data/tracks/c/exercises/atbash-cipher/test/vendor/unity.c +1300 -0
  24. data/tracks/c/exercises/atbash-cipher/test/vendor/unity.h +274 -0
  25. data/tracks/c/exercises/atbash-cipher/test/vendor/unity_internals.h +701 -0
  26. data/tracks/c/exercises/phone-number/makefile +16 -0
  27. data/tracks/c/exercises/phone-number/src/example.c +66 -0
  28. data/tracks/c/exercises/phone-number/src/example.h +8 -0
  29. data/tracks/c/exercises/phone-number/test/test_phone_number.c +108 -0
  30. data/tracks/c/exercises/phone-number/test/vendor/unity.c +1300 -0
  31. data/tracks/c/exercises/phone-number/test/vendor/unity.h +274 -0
  32. data/tracks/c/exercises/phone-number/test/vendor/unity_internals.h +701 -0
  33. data/tracks/csharp/config.json +8 -0
  34. data/tracks/csharp/exercises/bowling/BowlingTest.cs +188 -33
  35. data/tracks/csharp/exercises/bowling/Example.cs +38 -9
  36. data/tracks/csharp/exercises/rectangles/Example.cs +91 -0
  37. data/tracks/csharp/exercises/rectangles/RectanglesTest.cs +133 -0
  38. data/tracks/elisp/docs/INSTALLATION.org +1 -1
  39. data/tracks/elixir/config.json +8 -66
  40. data/tracks/elixir/docs/LEARNING.md +1 -1
  41. data/tracks/elixir/exercises/diamond/diamond_test.exs +12 -12
  42. data/tracks/elixir/exercises/grep/example.exs +92 -0
  43. data/tracks/elixir/exercises/grep/grep.exs +6 -0
  44. data/tracks/elixir/exercises/grep/grep_test.exs +259 -0
  45. data/tracks/elixir/exercises/markdown/markdown.exs +59 -2
  46. data/tracks/elixir/exercises/nucleotide-count/nucleotide_count_test.exs +4 -4
  47. data/tracks/elixir/exercises/phone-number/phone_number_test.exs +5 -0
  48. data/tracks/fsharp/exercises/bowling/BowlingTest.fs +158 -43
  49. data/tracks/fsharp/exercises/bowling/Example.fs +53 -24
  50. data/tracks/go/config.json +5 -0
  51. data/tracks/go/exercises/diamond/diamond_test.go +227 -0
  52. data/tracks/go/exercises/diamond/example.go +47 -0
  53. data/tracks/go/exercises/food-chain/example.go +1 -1
  54. data/tracks/go/exercises/food-chain/food_chain_test.go +30 -6
  55. data/tracks/go/exercises/nucleotide-count/example.go +21 -8
  56. data/tracks/go/exercises/nucleotide-count/nucleotide_count_test.go +45 -37
  57. data/tracks/haskell/exercises/anagram/test/Tests.hs +1 -11
  58. data/tracks/java/bin/journey-test.sh +165 -128
  59. data/tracks/java/docs/ABOUT.md +5 -8
  60. data/tracks/java/exercises/hello-world/build.gradle +0 -6
  61. data/tracks/java/exercises/hello-world/src/test/java/HelloWorldTest.java +0 -1
  62. data/tracks/java/exercises/meetup/build.gradle +0 -1
  63. data/tracks/java/exercises/meetup/src/example/java/Meetup.java +9 -7
  64. data/tracks/java/exercises/meetup/src/test/java/MeetupTest.java +185 -188
  65. data/tracks/lua/config.json +0 -73
  66. data/tracks/lua/exercises/bowling/bowling_spec.lua +92 -48
  67. data/tracks/lua/exercises/bowling/example.lua +4 -1
  68. data/tracks/objective-c/config.json +9 -30
  69. data/tracks/objective-c/exercises/pangram/PangramExample.h +7 -0
  70. data/tracks/objective-c/exercises/pangram/PangramExample.m +21 -0
  71. data/tracks/objective-c/exercises/pangram/PangramTest.m +51 -0
  72. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
  73. data/tracks/ocaml/README.md +46 -1
  74. data/tracks/ocaml/SETUP.md +21 -2
  75. data/tracks/ocaml/config.json +48 -78
  76. data/tracks/perl5/README.md +15 -8
  77. data/tracks/perl5/testall.pl +5 -5
  78. data/tracks/php/config.json +26 -34
  79. data/tracks/php/docs/ABOUT.md +15 -0
  80. data/tracks/php/exercises/allergies/allergies_test.php +121 -0
  81. data/tracks/php/exercises/allergies/example.php +64 -0
  82. data/tracks/php/exercises/etl/etl_test.php +52 -0
  83. data/tracks/php/exercises/etl/example.php +12 -0
  84. data/tracks/php/exercises/nucleotide-count/example.php +25 -0
  85. data/tracks/php/exercises/nucleotide-count/nucleotide-count_test.php +36 -0
  86. data/tracks/php/exercises/pig-latin/example.php +25 -29
  87. data/tracks/php/exercises/pig-latin/pig-latin_test.php +26 -19
  88. data/tracks/php/exercises/space-age/example.php +65 -0
  89. data/tracks/php/exercises/space-age/space-age_test.php +70 -0
  90. data/tracks/php/exercises/triangle/example.php +43 -0
  91. data/tracks/php/exercises/triangle/triangle_test.php +140 -0
  92. data/tracks/pony/exercises/anagram/example.pony +6 -6
  93. data/tracks/pony/exercises/anagram/test.pony +3 -4
  94. data/tracks/pony/exercises/bob/test.pony +23 -23
  95. data/tracks/pony/exercises/difference-of-squares/test.pony +11 -11
  96. data/tracks/pony/exercises/hamming/example.pony +3 -3
  97. data/tracks/pony/exercises/hamming/test.pony +16 -16
  98. data/tracks/pony/exercises/hello-world/test.pony +5 -4
  99. data/tracks/pony/exercises/leap/test.pony +8 -8
  100. data/tracks/python/config.json +18 -0
  101. data/tracks/python/exercises/diamond/diamond_test.py +33 -0
  102. data/tracks/python/exercises/diamond/example.py +15 -0
  103. data/tracks/python/exercises/linked-list/example.py +47 -0
  104. data/tracks/python/exercises/linked-list/linked_list.py +13 -0
  105. data/tracks/python/exercises/linked-list/linked_list_test.py +49 -0
  106. data/tracks/python/exercises/list-ops/example.py +55 -0
  107. data/tracks/python/exercises/list-ops/list_ops.py +38 -0
  108. data/tracks/python/exercises/list-ops/list_ops_test.py +136 -0
  109. data/tracks/ruby/bin/generate +22 -2
  110. data/tracks/ruby/config.json +12 -83
  111. data/tracks/ruby/exercises/allergies/allergies_test.rb +0 -1
  112. data/tracks/ruby/exercises/atbash-cipher/atbash_cipher_test.rb +0 -1
  113. data/tracks/ruby/exercises/beer-song/beer_song_test.rb +1 -2
  114. data/tracks/ruby/exercises/binary/example.rb +0 -1
  115. data/tracks/ruby/exercises/binary-search-tree/binary_search_tree_test.rb +1 -1
  116. data/tracks/ruby/exercises/bowling/.version +1 -0
  117. data/tracks/ruby/exercises/bowling/bowling_test.rb +109 -133
  118. data/tracks/ruby/exercises/bowling/example.rb +7 -7
  119. data/tracks/ruby/exercises/bowling/example.tt +27 -0
  120. data/tracks/ruby/exercises/circular-buffer/circular_buffer_test.rb +0 -2
  121. data/tracks/ruby/exercises/clock/example.rb +0 -2
  122. data/tracks/ruby/exercises/connect/connect_test.rb +0 -1
  123. data/tracks/ruby/exercises/custom-set/custom_set_test.rb +0 -1
  124. data/tracks/ruby/exercises/diamond/diamond_test.rb +0 -1
  125. data/tracks/ruby/exercises/etl/etl_test.rb +1 -1
  126. data/tracks/ruby/exercises/house/house_test.rb +0 -1
  127. data/tracks/ruby/exercises/isogram/isogram_test.rb +2 -2
  128. data/tracks/ruby/exercises/largest-series-product/example.tt +0 -3
  129. data/tracks/ruby/exercises/largest-series-product/largest_series_product_test.rb +0 -4
  130. data/tracks/ruby/exercises/linked-list/linked_list_test.rb +1 -1
  131. data/tracks/ruby/exercises/meetup/meetup_test.rb +0 -1
  132. data/tracks/ruby/exercises/nth-prime/example.tt +0 -2
  133. data/tracks/ruby/exercises/nth-prime/nth_prime_test.rb +0 -2
  134. data/tracks/ruby/exercises/ocr-numbers/ocr_numbers_test.rb +1 -2
  135. data/tracks/ruby/exercises/protein-translation/protein_translation_test.rb +0 -1
  136. data/tracks/ruby/exercises/proverb/proverb_test.rb +1 -3
  137. data/tracks/ruby/exercises/queen-attack/example.rb +3 -1
  138. data/tracks/ruby/exercises/queen-attack/queen_attack_test.rb +34 -8
  139. data/tracks/ruby/exercises/robot-simulator/robot_simulator_test.rb +1 -1
  140. data/tracks/ruby/exercises/strain/strain_test.rb +2 -2
  141. data/tracks/ruby/exercises/tournament/.version +1 -0
  142. data/tracks/ruby/exercises/tournament/example.rb +54 -0
  143. data/tracks/ruby/exercises/tournament/example.tt +23 -0
  144. data/tracks/ruby/exercises/tournament/tournament_test.rb +92 -0
  145. data/tracks/ruby/exercises/transpose/.version +1 -0
  146. data/tracks/ruby/exercises/transpose/example.rb +14 -0
  147. data/tracks/ruby/exercises/transpose/example.tt +22 -0
  148. data/tracks/ruby/exercises/transpose/transpose_test.rb +303 -0
  149. data/tracks/ruby/lib/bowling_cases.rb +46 -0
  150. data/tracks/ruby/lib/isogram_cases.rb +1 -1
  151. data/tracks/ruby/lib/tournament_cases.rb +45 -0
  152. data/tracks/ruby/lib/transpose_cases.rb +45 -0
  153. data/tracks/rust/config.json +2 -0
  154. data/tracks/rust/exercises/bowling/.gitignore +7 -0
  155. data/tracks/rust/exercises/bowling/Cargo.toml +3 -0
  156. data/tracks/rust/exercises/bowling/example.rs +134 -0
  157. data/tracks/rust/exercises/bowling/tests/bowling.rs +373 -0
  158. data/tracks/rust/exercises/grains/.gitignore +7 -0
  159. data/tracks/rust/exercises/grains/Cargo.toml +3 -0
  160. data/tracks/rust/exercises/grains/example.rs +11 -0
  161. data/tracks/rust/exercises/grains/src/lib.rs +7 -0
  162. data/tracks/rust/exercises/grains/tests/grains.rs +63 -0
  163. data/tracks/rust/problems.md +2 -0
  164. data/tracks/scala/README.md +38 -0
  165. data/tracks/scala/config.json +20 -74
  166. data/tracks/scala/exercises/accumulate/src/test/scala/accumulate_test.scala +4 -0
  167. data/tracks/scala/exercises/allergies/src/test/scala/allergies_test.scala +11 -0
  168. data/tracks/scala/exercises/alphametics/build.sbt +6 -0
  169. data/tracks/scala/exercises/alphametics/example.scala +125 -0
  170. data/tracks/scala/exercises/alphametics/src/main/scala/.keep +0 -0
  171. data/tracks/scala/exercises/alphametics/src/test/scala/AlphameticsTest.scala +62 -0
  172. data/tracks/scala/exercises/atbash-cipher/src/test/scala/atbash_test.scala +8 -0
  173. data/tracks/scala/exercises/bank-account/src/test/scala/BankAccountTest.scala +4 -0
  174. data/tracks/scala/exercises/binary/src/test/scala/binary_test.scala +13 -0
  175. data/tracks/scala/exercises/binary-search-tree/src/test/scala/BstTest.scala +11 -0
  176. data/tracks/scala/exercises/bowling/Example.scala +116 -0
  177. data/tracks/scala/exercises/bowling/build.sbt +3 -0
  178. data/tracks/scala/exercises/bowling/src/main/scala/Bowling.scala +11 -0
  179. data/tracks/scala/exercises/bowling/src/test/scala/BowlingSuite.scala +237 -0
  180. data/tracks/scala/exercises/clock/src/test/scala/ClockTest.scala +50 -0
  181. data/tracks/scala/exercises/connect/README.md +17 -0
  182. data/tracks/scala/exercises/connect/src/test/scala/ConnectTest.scala +7 -0
  183. data/tracks/scala/exercises/crypto-square/src/test/scala/{CrytpoSquareTest.scala → CryptoSquareTest.scala} +9 -0
  184. data/tracks/scala/exercises/custom-set/src/test/scala/CustomSetTest.scala +36 -0
  185. data/tracks/scala/exercises/difference-of-squares/src/test/scala/squares_test.scala +8 -0
  186. data/tracks/scala/exercises/forth/src/test/scala/ForthTest.scala +22 -0
  187. data/tracks/scala/exercises/hexadecimal/src/test/scala/HexadecimalTest.scala +8 -0
  188. data/tracks/scala/exercises/kindergarten-garden/src/test/scala/GardenTest.scala +5 -0
  189. data/tracks/scala/exercises/largest-series-product/src/test/scala/SeriesTest.scala +2 -0
  190. data/tracks/scala/exercises/linked-list/src/test/scala/DequeTest.scala +4 -0
  191. data/tracks/scala/exercises/luhn/src/test/scala/LuhnTest.scala +4 -0
  192. data/tracks/scala/exercises/matrix/src/test/scala/MatrixTest.scala +2 -0
  193. data/tracks/scala/exercises/minesweeper/src/test/scala/MinesweeperTest.scala +6 -0
  194. data/tracks/scala/exercises/nth-prime/src/test/scala/PrimeTest.scala +5 -0
  195. data/tracks/scala/exercises/ocr-numbers/src/test/scala/OcrTest.scala +15 -0
  196. data/tracks/scala/exercises/octal/src/test/scala/OctalTest.scala +7 -0
  197. data/tracks/scala/exercises/parallel-letter-frequency/src/test/scala/FrequencyTest.scala +8 -0
  198. data/tracks/scala/exercises/pascals-triangle/src/test/scala/PascalsTriangleTest.scala +5 -0
  199. data/tracks/scala/exercises/pig-latin/src/test/scala/PigLatinTest.scala +4 -0
  200. data/tracks/scala/exercises/pythagorean-triplet/src/test/scala/PythagoreanTripletTest.scala +3 -0
  201. data/tracks/scala/exercises/queen-attack/src/test/scala/QueensTest.scala +5 -0
  202. data/tracks/scala/exercises/robot-simulator/src/test/scala/RobotTest.scala +16 -8
  203. data/tracks/scala/exercises/say/src/test/scala/SayTest.scala +34 -17
  204. data/tracks/scala/exercises/scrabble-score/src/test/scala/scrabble_score_test.scala +6 -0
  205. data/tracks/scala/exercises/secret-handshake/src/test/scala/SecretHandshakeTest.scala +18 -9
  206. data/tracks/scala/exercises/series/src/test/scala/SeriesTest.scala +4 -2
  207. data/tracks/scala/exercises/sieve/src/test/scala/SieveTest.scala +8 -4
  208. data/tracks/scala/exercises/simple-cipher/src/test/scala/CipherTest.scala +17 -9
  209. data/tracks/scala/exercises/sublist/src/test/scala/sublist_test.scala +17 -0
  210. data/tracks/scala/exercises/trinary/src/test/scala/TrinaryTest.scala +14 -7
  211. data/tracks/scala/exercises/wordy/src/test/scala/WordProblemTest.scala +28 -14
  212. data/tracks/scala/project/Build.scala +3 -3
  213. data/tracks/scala/testgen/src/main/scala/BowlingTestGenerator.scala +57 -0
  214. data/tracks/sml/config.json +41 -6
  215. data/tracks/sml/exercises/flatten-array/example.sml +6 -0
  216. data/tracks/sml/exercises/flatten-array/test_flatten_array.sml +10 -0
  217. data/tracks/sml/exercises/nth-prime/example.sml +46 -0
  218. data/tracks/sml/exercises/nth-prime/test_nth_prime.sml +14 -0
  219. data/tracks/sml/exercises/raindrops/example.sml +9 -0
  220. data/tracks/sml/exercises/raindrops/raindrops.sml +2 -0
  221. data/tracks/sml/exercises/raindrops/test_raindrops.sml +95 -0
  222. data/tracks/swift/config.json +269 -328
  223. data/tracks/swift/exercises/pangram/PangramExample.swift +17 -0
  224. data/tracks/swift/exercises/pangram/PangramTest.swift +43 -0
  225. data/tracks/swift/xcodeProject/xSwift.xcodeproj/project.pbxproj +16 -0
  226. metadata +95 -3
@@ -18,11 +18,11 @@ defmodule DiamondTest do
18
18
  test "letter C" do
19
19
  shape = Diamond.build_shape(?C)
20
20
  assert shape == """
21
- \s A
22
- \sB B
21
+ \s A \s
22
+ \sB B\s
23
23
  C C
24
- \sB B
25
- \s A
24
+ \sB B\s
25
+ \s A \s
26
26
  """
27
27
  end
28
28
 
@@ -30,15 +30,15 @@ defmodule DiamondTest do
30
30
  test "letter E" do
31
31
  shape = Diamond.build_shape(?E)
32
32
  assert shape == """
33
- \s A
34
- \s B B
35
- \s C C
36
- \sD D
33
+ \s A \s
34
+ \s B B \s
35
+ \s C C \s
36
+ \sD D\s
37
37
  E E
38
- \sD D
39
- \s C C
40
- \s B B
41
- \s A
38
+ \sD D\s
39
+ \s C C \s
40
+ \s B B \s
41
+ \s A \s
42
42
  """
43
43
  end
44
44
  end
@@ -0,0 +1,92 @@
1
+ defmodule Grep do
2
+ use Bitwise
3
+
4
+ @line_num_flag 1
5
+ @file_name 2
6
+ @case_insensitive 4
7
+ @invert 8
8
+ @entire_lines 16
9
+
10
+ defp parse_flag("-n"), do: @line_num_flag
11
+ defp parse_flag("-l"), do: @file_name
12
+ defp parse_flag("-i"), do: @case_insensitive
13
+ defp parse_flag("-v"), do: @invert
14
+ defp parse_flag("-x"), do: @entire_lines
15
+ defp parse_flag(_), do: 0
16
+
17
+ defp parse_flags(flags) do
18
+ flags
19
+ |> Enum.map(&parse_flag/1)
20
+ |> Enum.reduce(0, fn(a,b) -> a ||| b end)
21
+ end
22
+
23
+ defp has_flag(flags, flag), do: (flags &&& flag) > 0
24
+
25
+ defp is_match(pattern, flags) do
26
+ pat = if has_flag(flags, @entire_lines) do
27
+ "^#{pattern}$"
28
+ else
29
+ pattern
30
+ end
31
+ cas = if has_flag(flags, @case_insensitive) do
32
+ "i"
33
+ else
34
+ ""
35
+ end
36
+
37
+ regex = Regex.compile!(pat, cas)
38
+
39
+ fn line -> Regex.match?(regex, line) != has_flag(flags, @invert) end
40
+ end
41
+
42
+ defp matching_lines(pattern, flags, file) do
43
+ match_fn = is_match(pattern, flags)
44
+
45
+ File.stream!(file)
46
+ |> Enum.map(fn l -> String.trim_trailing(l, "\n") end)
47
+ |> Enum.with_index(1)
48
+ |> Enum.map(fn {l, i} -> {file, i, l} end)
49
+ |> Enum.filter(fn {_, _, l} -> match_fn.(l) end)
50
+ end
51
+
52
+ defp process_files(pattern, flags, files) do
53
+ files
54
+ |> Enum.filter(fn x -> !Enum.empty?(matching_lines(pattern, flags, x)) end)
55
+ end
56
+
57
+ defp line_formatter(flags, single_file?) do
58
+ print_nums? = has_flag(flags, @line_num_flag)
59
+
60
+ fn {f, ix, l} ->
61
+ case {single_file?, print_nums?} do
62
+ {true, true} -> "#{ix}:#{l}"
63
+ {false, true} -> "#{f}:#{ix}:#{l}"
64
+ {true, false} -> "#{l}"
65
+ {false, false} -> "#{f}:#{l}"
66
+ end
67
+ end
68
+ end
69
+
70
+ defp process_lines(pattern, flags, files) do
71
+ fmt = line_formatter(flags, length(files) == 1)
72
+
73
+ files
74
+ |> Enum.flat_map(fn x -> matching_lines(pattern, flags, x) end)
75
+ |> Enum.map(fmt)
76
+ end
77
+
78
+ @spec grep(String.t, [String.t], [String.t]) :: String.t
79
+ def grep(pattern, flag_args, files) do
80
+ flags = parse_flags(flag_args)
81
+
82
+ output = if has_flag(flags, @file_name) do
83
+ process_files(pattern, flags, files)
84
+ else
85
+ process_lines(pattern, flags, files)
86
+ end
87
+
88
+ output
89
+ |> Enum.map(fn l -> "#{l}\n" end)
90
+ |> Enum.reduce("", fn b,a -> "#{a}#{b}" end)
91
+ end
92
+ end
@@ -0,0 +1,6 @@
1
+ defmodule Grep do
2
+
3
+ @spec grep(String.t, [String.t], [String.t]) :: String.t
4
+ def grep(pattern, flags, files) do
5
+ end
6
+ end
@@ -0,0 +1,259 @@
1
+ if !System.get_env("EXERCISM_TEST_EXAMPLES") do
2
+ Code.load_file("grep.exs", __DIR__)
3
+ end
4
+
5
+ ExUnit.start
6
+ ExUnit.configure exclude: :pending, trace: true
7
+
8
+ defmodule GrepTest do
9
+ use ExUnit.Case
10
+
11
+ setup context do
12
+
13
+ if context[:files] do
14
+ File.write!("iliad.txt", """
15
+ Achilles sing, O Goddess! Peleus' son;
16
+ His wrath pernicious, who ten thousand woes
17
+ Caused to Achaia's host, sent many a soul
18
+ Illustrious into Ades premature,
19
+ And Heroes gave (so stood the will of Jove)
20
+ To dogs and to all ravening fowls a prey,
21
+ When fierce dispute had separated once
22
+ The noble Chief Achilles from the son
23
+ Of Atreus, Agamemnon, King of men.
24
+ """)
25
+
26
+ File.write!("midsummer-night.txt", """
27
+ I do entreat your grace to pardon me.
28
+ I know not by what power I am made bold,
29
+ Nor how it may concern my modesty,
30
+ In such a presence here to plead my thoughts;
31
+ But I beseech your grace that I may know
32
+ The worst that may befall me in this case,
33
+ If I refuse to wed Demetrius.
34
+ """
35
+ )
36
+
37
+ File.write!("paradise-lost.txt", """
38
+ Of Mans First Disobedience, and the Fruit
39
+ Of that Forbidden Tree, whose mortal tast
40
+ Brought Death into the World, and all our woe,
41
+ With loss of Eden, till one greater Man
42
+ Restore us, and regain the blissful Seat,
43
+ Sing Heav'nly Muse, that on the secret top
44
+ Of Oreb, or of Sinai, didst inspire
45
+ That Shepherd, who first taught the chosen Seed
46
+ """)
47
+
48
+ on_exit fn ->
49
+ File.rm!("iliad.txt")
50
+ File.rm!("midsummer-night.txt")
51
+ File.rm!("paradise-lost.txt")
52
+ end
53
+ end
54
+ end
55
+
56
+ @moduletag :files
57
+
58
+ describe "grepping a single file" do
59
+
60
+ test "one match, no flags" do
61
+ assert Grep.grep("Agamemnon", [], ["iliad.txt"]) ==
62
+ """
63
+ Of Atreus, Agamemnon, King of men.
64
+ """
65
+ end
66
+
67
+ @tag :pending
68
+ test "one match, print line numbers flag" do
69
+ assert Grep.grep("Forbidden", ["-n"], ["paradise-lost.txt"]) ==
70
+ """
71
+ 2:Of that Forbidden Tree, whose mortal tast
72
+ """
73
+ end
74
+
75
+ @tag :pending
76
+ test "one match, case-insensitive flag" do
77
+ assert Grep.grep("FORBIDDEN", ["-i"], ["paradise-lost.txt"]) ==
78
+ """
79
+ Of that Forbidden Tree, whose mortal tast
80
+ """
81
+ end
82
+
83
+ @tag :pending
84
+ test "one match, print file names flag" do
85
+ assert Grep.grep("Forbidden", ["-l"], ["paradise-lost.txt"]) ==
86
+ """
87
+ paradise-lost.txt
88
+ """
89
+ end
90
+
91
+ @tag :pending
92
+ test "one match, match entire lines flag" do
93
+ assert Grep.grep("With loss of Eden, till one greater Man",
94
+ ["-x"], ["paradise-lost.txt"]) ==
95
+ """
96
+ With loss of Eden, till one greater Man
97
+ """
98
+ end
99
+
100
+ @tag :pending
101
+ test "one match, multiple flags" do
102
+ assert Grep.grep("OF ATREUS, Agamemnon, KIng of MEN.",
103
+ ["-n", "-i", "-x"], ["iliad.txt"]) ==
104
+ """
105
+ 9:Of Atreus, Agamemnon, King of men.
106
+ """
107
+ end
108
+
109
+ @tag :pending
110
+ test "several matches, no flags" do
111
+ assert Grep.grep("may", [], ["midsummer-night.txt"]) ==
112
+ """
113
+ Nor how it may concern my modesty,
114
+ But I beseech your grace that I may know
115
+ The worst that may befall me in this case,
116
+ """
117
+ end
118
+
119
+ @tag :pending
120
+ test "several matches, print line numbers flag" do
121
+ assert Grep.grep("may", ["-n"], ["midsummer-night.txt"]) ==
122
+ """
123
+ 3:Nor how it may concern my modesty,
124
+ 5:But I beseech your grace that I may know
125
+ 6:The worst that may befall me in this case,
126
+ """
127
+ end
128
+
129
+ @tag :pending
130
+ test "several matches, match entire lines flag" do
131
+ assert Grep.grep("may", ["-x"], ["midsummer-night.txt"]) == ""
132
+ end
133
+
134
+ @tag :pending
135
+ test "several matches, case-insensitive flag" do
136
+ assert Grep.grep("ACHILLES", ["-i"], ["iliad.txt"]) ==
137
+ """
138
+ Achilles sing, O Goddess! Peleus' son;
139
+ The noble Chief Achilles from the son
140
+ """
141
+ end
142
+
143
+ @tag :pending
144
+ test "several matches, inverted flag" do
145
+ assert Grep.grep("Of", ["-v"], ["paradise-lost.txt"]) ==
146
+ """
147
+ Brought Death into the World, and all our woe,
148
+ With loss of Eden, till one greater Man
149
+ Restore us, and regain the blissful Seat,
150
+ Sing Heav'nly Muse, that on the secret top
151
+ That Shepherd, who first taught the chosen Seed
152
+ """
153
+ end
154
+
155
+ @tag :pending
156
+ test "no matches, various flags" do
157
+ assert Grep.grep("Gandalf", ["-n", "-l", "-x", "-i"], ["iliad.txt"]) == ""
158
+ end
159
+ end
160
+
161
+ describe "grepping multiples files at once" do
162
+
163
+ @tag :pending
164
+ test "one match, no flags" do
165
+ assert Grep.grep("Agamemnon", [],
166
+ ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]) ==
167
+ """
168
+ iliad.txt:Of Atreus, Agamemnon, King of men.
169
+ """
170
+ end
171
+
172
+ @tag :pending
173
+ test "several matches, no flags" do
174
+ assert Grep.grep("may", [],
175
+ ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]) ==
176
+ """
177
+ midsummer-night.txt:Nor how it may concern my modesty,
178
+ midsummer-night.txt:But I beseech your grace that I may know
179
+ midsummer-night.txt:The worst that may befall me in this case,
180
+ """
181
+ end
182
+
183
+ @tag :pending
184
+ test "several matches, print line numbers flag" do
185
+ assert Grep.grep("that", ["-n"],
186
+ ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]) ==
187
+ """
188
+ midsummer-night.txt:5:But I beseech your grace that I may know
189
+ midsummer-night.txt:6:The worst that may befall me in this case,
190
+ paradise-lost.txt:2:Of that Forbidden Tree, whose mortal tast
191
+ paradise-lost.txt:6:Sing Heav'nly Muse, that on the secret top
192
+ """
193
+ end
194
+
195
+ @tag :pending
196
+ test "one match, print file names flag" do
197
+ assert Grep.grep("who", ["-l"],
198
+ ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]) ==
199
+ """
200
+ iliad.txt
201
+ paradise-lost.txt
202
+ """
203
+ end
204
+
205
+ @tag :pending
206
+ test "several matches, case-insensitive flag" do
207
+ assert Grep.grep("TO", ["-i"],
208
+ ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]) ==
209
+ """
210
+ iliad.txt:Caused to Achaia's host, sent many a soul
211
+ iliad.txt:Illustrious into Ades premature,
212
+ iliad.txt:And Heroes gave (so stood the will of Jove)
213
+ iliad.txt:To dogs and to all ravening fowls a prey,
214
+ midsummer-night.txt:I do entreat your grace to pardon me.
215
+ midsummer-night.txt:In such a presence here to plead my thoughts;
216
+ midsummer-night.txt:If I refuse to wed Demetrius.
217
+ paradise-lost.txt:Brought Death into the World, and all our woe,
218
+ paradise-lost.txt:Restore us, and regain the blissful Seat,
219
+ paradise-lost.txt:Sing Heav'nly Muse, that on the secret top
220
+ """
221
+ end
222
+
223
+ @tag :pending
224
+ test "several matches, inverted flag" do
225
+ assert Grep.grep("a", ["-v"],
226
+ ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]) ==
227
+ """
228
+ iliad.txt:Achilles sing, O Goddess! Peleus' son;
229
+ iliad.txt:The noble Chief Achilles from the son
230
+ midsummer-night.txt:If I refuse to wed Demetrius.
231
+ """
232
+ end
233
+
234
+ @tag :pending
235
+ test "one match, match entire lines flag" do
236
+ assert Grep.grep("But I beseech your grace that I may know", ["-x"],
237
+ ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]) ==
238
+ """
239
+ midsummer-night.txt:But I beseech your grace that I may know
240
+ """
241
+ end
242
+
243
+ @tag :pending
244
+ test "one match, multiple flags" do
245
+ assert Grep.grep("WITH LOSS OF EDEN, TILL ONE GREATER MAN",
246
+ ["-n", "-x", "-i"],
247
+ ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]) ==
248
+ """
249
+ paradise-lost.txt:4:With loss of Eden, till one greater Man
250
+ """
251
+ end
252
+
253
+ @tag :pending
254
+ test "no matches, various flags" do
255
+ assert Grep.grep("Frodo", ["-n", "-l", "-x", "i"],
256
+ ["iliad.txt", "midsummer-night.txt", "paradise-lost.txt"]) == ""
257
+ end
258
+ end
259
+ end
@@ -10,9 +10,66 @@ defmodule Markdown do
10
10
  iex> Markdown.parse("#Header!\n* __Bold Item__\n* _Italic Item_")
11
11
  "<h1>Header!</h1><ul><li><em>Bold Item</em></li><li><i>Italic Item</i></li></ul>"
12
12
  """
13
-
14
13
  @spec parse(String.t) :: String.t
15
- def parse(markdown) do
14
+ def parse(m) do
15
+ patch(Enum.join(Enum.map(String.split(m, "\n"), fn(t) -> process(t) end)))
16
+ end
17
+
18
+ defp process(t) do
19
+ if String.starts_with?(t, "#") || String.starts_with?(t, "*") do
20
+ if String.starts_with?(t, "#") do
21
+ enclose_with_header_tag(parse_header_md_level(t))
22
+ else
23
+ parse_list_md_level(t)
24
+ end
25
+ else
26
+ enclose_with_paragraph_tag(String.split(t))
27
+ end
28
+ end
29
+
30
+ defp parse_header_md_level(hwt) do
31
+ [h | t] = String.split(hwt)
32
+ {to_string(String.length(h)), Enum.join(t, " ")}
33
+ end
34
+
35
+ defp parse_list_md_level(l) do
36
+ t = String.split(String.trim_leading(l, "* "))
37
+ "<li>" <> join_words_with_tags(t) <> "</li>"
38
+ end
39
+
40
+ defp enclose_with_header_tag({hl, htl}) do
41
+ "<h" <> hl <> ">" <> htl <> "</h" <> hl <> ">"
42
+ end
43
+
44
+ defp enclose_with_paragraph_tag(t) do
45
+ "<p>#{join_words_with_tags(t)}</p>"
46
+ end
47
+
48
+ defp join_words_with_tags(t) do
49
+ Enum.join(Enum.map(t, fn(w) -> replace_md_with_tag(w) end), " ")
50
+ end
51
+
52
+ defp replace_md_with_tag(w) do
53
+ replace_suffix_md(replace_prefix_md(w))
54
+ end
55
+
56
+ defp replace_prefix_md(w) do
57
+ cond do
58
+ w =~ ~r/^#{"__"}{1}/ -> String.replace(w, ~r/^#{"__"}{1}/, "<strong>", global: false)
59
+ w =~ ~r/^[#{"_"}{1}][^#{"_"}+]/ -> String.replace(w, ~r/_/, "<em>", global: false)
60
+ true -> w
61
+ end
62
+ end
63
+
64
+ defp replace_suffix_md(w) do
65
+ cond do
66
+ w =~ ~r/#{"__"}{1}$/ -> String.replace(w, ~r/#{"__"}{1}$/, "</strong>")
67
+ w =~ ~r/[^#{"_"}{1}]/ -> String.replace(w, ~r/_/, "</em>")
68
+ true -> w
69
+ end
70
+ end
16
71
 
72
+ defp patch(l) do
73
+ String.replace_suffix(String.replace(l, "<li>", "<ul>" <> "<li>", global: false), "</li>", "</li>" <> "</ul>")
17
74
  end
18
75
  end
@@ -9,17 +9,17 @@ defmodule NucleotideCountTest do
9
9
  use ExUnit.Case
10
10
 
11
11
  # @tag :pending
12
- test "empty dna string has no adenosine" do
12
+ test "empty dna string has no adenine" do
13
13
  assert NucleotideCount.count('', ?A) == 0
14
14
  end
15
15
 
16
16
  @tag :pending
17
- test "repetitive cytidine gets counted" do
17
+ test "repetitive cytosine gets counted" do
18
18
  assert NucleotideCount.count('CCCCC', ?C) == 5
19
19
  end
20
20
 
21
21
  @tag :pending
22
- test "counts only thymidine" do
22
+ test "counts only thymine" do
23
23
  assert NucleotideCount.count('GGGGGTAACCCGG', ?T) == 1
24
24
  end
25
25
 
@@ -30,7 +30,7 @@ defmodule NucleotideCountTest do
30
30
  end
31
31
 
32
32
  @tag :pending
33
- test "repetitive sequence has only guanosine" do
33
+ test "repetitive sequence has only guanine" do
34
34
  expected = %{?A => 0, ?T => 0, ?C => 0, ?G => 8}
35
35
  assert NucleotideCount.histogram('GGGGGGGG') == expected
36
36
  end
@@ -37,6 +37,11 @@ defmodule PhoneTest do
37
37
  assert Phone.number("1a2a3a4a5a6a7a8a9a0a") == "0000000000"
38
38
  end
39
39
 
40
+ @tag :pending
41
+ test "invalid with correct number of characters but some are letters" do
42
+ assert Phone.number("1a2a3a4a5a") == "0000000000"
43
+ end
44
+
40
45
  @tag :pending
41
46
  test "area code" do
42
47
  assert Phone.area_code("1234567890") == "123"