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.
- checksums.yaml +4 -4
- data/bin/bump-content +3 -1
- data/bin/verify-metadata +2 -2
- data/common/exercises/alphametics/canonical-data.json +19 -9
- data/common/exercises/food-chain/canonical-data.json +7 -1
- data/common/exercises/grains/canonical-data.json +66 -0
- data/common/exercises/raindrops/description.md +4 -5
- data/common/exercises/triangle/canonical-data.json +81 -54
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +26 -19
- data/tracks/c/exercises/allergies/makefile +15 -0
- data/tracks/c/exercises/allergies/src/allergies.h +21 -0
- data/tracks/c/exercises/allergies/src/example.c +32 -0
- data/tracks/c/exercises/allergies/src/example.h +26 -0
- data/tracks/c/exercises/allergies/test/test_allergies.c +203 -0
- data/tracks/c/exercises/allergies/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/allergies/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/allergies/test/vendor/unity_internals.h +701 -0
- data/tracks/c/exercises/atbash-cipher/makefile +16 -0
- data/tracks/c/exercises/atbash-cipher/src/example.c +71 -0
- data/tracks/c/exercises/atbash-cipher/src/example.h +7 -0
- data/tracks/c/exercises/atbash-cipher/test/test_atbash_cipher.c +113 -0
- data/tracks/c/exercises/atbash-cipher/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/atbash-cipher/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/atbash-cipher/test/vendor/unity_internals.h +701 -0
- data/tracks/c/exercises/phone-number/makefile +16 -0
- data/tracks/c/exercises/phone-number/src/example.c +66 -0
- data/tracks/c/exercises/phone-number/src/example.h +8 -0
- data/tracks/c/exercises/phone-number/test/test_phone_number.c +108 -0
- data/tracks/c/exercises/phone-number/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/phone-number/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/phone-number/test/vendor/unity_internals.h +701 -0
- data/tracks/csharp/config.json +8 -0
- data/tracks/csharp/exercises/bowling/BowlingTest.cs +188 -33
- data/tracks/csharp/exercises/bowling/Example.cs +38 -9
- data/tracks/csharp/exercises/rectangles/Example.cs +91 -0
- data/tracks/csharp/exercises/rectangles/RectanglesTest.cs +133 -0
- data/tracks/elisp/docs/INSTALLATION.org +1 -1
- data/tracks/elixir/config.json +8 -66
- data/tracks/elixir/docs/LEARNING.md +1 -1
- data/tracks/elixir/exercises/diamond/diamond_test.exs +12 -12
- data/tracks/elixir/exercises/grep/example.exs +92 -0
- data/tracks/elixir/exercises/grep/grep.exs +6 -0
- data/tracks/elixir/exercises/grep/grep_test.exs +259 -0
- data/tracks/elixir/exercises/markdown/markdown.exs +59 -2
- data/tracks/elixir/exercises/nucleotide-count/nucleotide_count_test.exs +4 -4
- data/tracks/elixir/exercises/phone-number/phone_number_test.exs +5 -0
- data/tracks/fsharp/exercises/bowling/BowlingTest.fs +158 -43
- data/tracks/fsharp/exercises/bowling/Example.fs +53 -24
- data/tracks/go/config.json +5 -0
- data/tracks/go/exercises/diamond/diamond_test.go +227 -0
- data/tracks/go/exercises/diamond/example.go +47 -0
- data/tracks/go/exercises/food-chain/example.go +1 -1
- data/tracks/go/exercises/food-chain/food_chain_test.go +30 -6
- data/tracks/go/exercises/nucleotide-count/example.go +21 -8
- data/tracks/go/exercises/nucleotide-count/nucleotide_count_test.go +45 -37
- data/tracks/haskell/exercises/anagram/test/Tests.hs +1 -11
- data/tracks/java/bin/journey-test.sh +165 -128
- data/tracks/java/docs/ABOUT.md +5 -8
- data/tracks/java/exercises/hello-world/build.gradle +0 -6
- data/tracks/java/exercises/hello-world/src/test/java/HelloWorldTest.java +0 -1
- data/tracks/java/exercises/meetup/build.gradle +0 -1
- data/tracks/java/exercises/meetup/src/example/java/Meetup.java +9 -7
- data/tracks/java/exercises/meetup/src/test/java/MeetupTest.java +185 -188
- data/tracks/lua/config.json +0 -73
- data/tracks/lua/exercises/bowling/bowling_spec.lua +92 -48
- data/tracks/lua/exercises/bowling/example.lua +4 -1
- data/tracks/objective-c/config.json +9 -30
- data/tracks/objective-c/exercises/pangram/PangramExample.h +7 -0
- data/tracks/objective-c/exercises/pangram/PangramExample.m +21 -0
- data/tracks/objective-c/exercises/pangram/PangramTest.m +51 -0
- data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
- data/tracks/ocaml/README.md +46 -1
- data/tracks/ocaml/SETUP.md +21 -2
- data/tracks/ocaml/config.json +48 -78
- data/tracks/perl5/README.md +15 -8
- data/tracks/perl5/testall.pl +5 -5
- data/tracks/php/config.json +26 -34
- data/tracks/php/docs/ABOUT.md +15 -0
- data/tracks/php/exercises/allergies/allergies_test.php +121 -0
- data/tracks/php/exercises/allergies/example.php +64 -0
- data/tracks/php/exercises/etl/etl_test.php +52 -0
- data/tracks/php/exercises/etl/example.php +12 -0
- data/tracks/php/exercises/nucleotide-count/example.php +25 -0
- data/tracks/php/exercises/nucleotide-count/nucleotide-count_test.php +36 -0
- data/tracks/php/exercises/pig-latin/example.php +25 -29
- data/tracks/php/exercises/pig-latin/pig-latin_test.php +26 -19
- data/tracks/php/exercises/space-age/example.php +65 -0
- data/tracks/php/exercises/space-age/space-age_test.php +70 -0
- data/tracks/php/exercises/triangle/example.php +43 -0
- data/tracks/php/exercises/triangle/triangle_test.php +140 -0
- data/tracks/pony/exercises/anagram/example.pony +6 -6
- data/tracks/pony/exercises/anagram/test.pony +3 -4
- data/tracks/pony/exercises/bob/test.pony +23 -23
- data/tracks/pony/exercises/difference-of-squares/test.pony +11 -11
- data/tracks/pony/exercises/hamming/example.pony +3 -3
- data/tracks/pony/exercises/hamming/test.pony +16 -16
- data/tracks/pony/exercises/hello-world/test.pony +5 -4
- data/tracks/pony/exercises/leap/test.pony +8 -8
- data/tracks/python/config.json +18 -0
- data/tracks/python/exercises/diamond/diamond_test.py +33 -0
- data/tracks/python/exercises/diamond/example.py +15 -0
- data/tracks/python/exercises/linked-list/example.py +47 -0
- data/tracks/python/exercises/linked-list/linked_list.py +13 -0
- data/tracks/python/exercises/linked-list/linked_list_test.py +49 -0
- data/tracks/python/exercises/list-ops/example.py +55 -0
- data/tracks/python/exercises/list-ops/list_ops.py +38 -0
- data/tracks/python/exercises/list-ops/list_ops_test.py +136 -0
- data/tracks/ruby/bin/generate +22 -2
- data/tracks/ruby/config.json +12 -83
- data/tracks/ruby/exercises/allergies/allergies_test.rb +0 -1
- data/tracks/ruby/exercises/atbash-cipher/atbash_cipher_test.rb +0 -1
- data/tracks/ruby/exercises/beer-song/beer_song_test.rb +1 -2
- data/tracks/ruby/exercises/binary/example.rb +0 -1
- data/tracks/ruby/exercises/binary-search-tree/binary_search_tree_test.rb +1 -1
- data/tracks/ruby/exercises/bowling/.version +1 -0
- data/tracks/ruby/exercises/bowling/bowling_test.rb +109 -133
- data/tracks/ruby/exercises/bowling/example.rb +7 -7
- data/tracks/ruby/exercises/bowling/example.tt +27 -0
- data/tracks/ruby/exercises/circular-buffer/circular_buffer_test.rb +0 -2
- data/tracks/ruby/exercises/clock/example.rb +0 -2
- data/tracks/ruby/exercises/connect/connect_test.rb +0 -1
- data/tracks/ruby/exercises/custom-set/custom_set_test.rb +0 -1
- data/tracks/ruby/exercises/diamond/diamond_test.rb +0 -1
- data/tracks/ruby/exercises/etl/etl_test.rb +1 -1
- data/tracks/ruby/exercises/house/house_test.rb +0 -1
- data/tracks/ruby/exercises/isogram/isogram_test.rb +2 -2
- data/tracks/ruby/exercises/largest-series-product/example.tt +0 -3
- data/tracks/ruby/exercises/largest-series-product/largest_series_product_test.rb +0 -4
- data/tracks/ruby/exercises/linked-list/linked_list_test.rb +1 -1
- data/tracks/ruby/exercises/meetup/meetup_test.rb +0 -1
- data/tracks/ruby/exercises/nth-prime/example.tt +0 -2
- data/tracks/ruby/exercises/nth-prime/nth_prime_test.rb +0 -2
- data/tracks/ruby/exercises/ocr-numbers/ocr_numbers_test.rb +1 -2
- data/tracks/ruby/exercises/protein-translation/protein_translation_test.rb +0 -1
- data/tracks/ruby/exercises/proverb/proverb_test.rb +1 -3
- data/tracks/ruby/exercises/queen-attack/example.rb +3 -1
- data/tracks/ruby/exercises/queen-attack/queen_attack_test.rb +34 -8
- data/tracks/ruby/exercises/robot-simulator/robot_simulator_test.rb +1 -1
- data/tracks/ruby/exercises/strain/strain_test.rb +2 -2
- data/tracks/ruby/exercises/tournament/.version +1 -0
- data/tracks/ruby/exercises/tournament/example.rb +54 -0
- data/tracks/ruby/exercises/tournament/example.tt +23 -0
- data/tracks/ruby/exercises/tournament/tournament_test.rb +92 -0
- data/tracks/ruby/exercises/transpose/.version +1 -0
- data/tracks/ruby/exercises/transpose/example.rb +14 -0
- data/tracks/ruby/exercises/transpose/example.tt +22 -0
- data/tracks/ruby/exercises/transpose/transpose_test.rb +303 -0
- data/tracks/ruby/lib/bowling_cases.rb +46 -0
- data/tracks/ruby/lib/isogram_cases.rb +1 -1
- data/tracks/ruby/lib/tournament_cases.rb +45 -0
- data/tracks/ruby/lib/transpose_cases.rb +45 -0
- data/tracks/rust/config.json +2 -0
- data/tracks/rust/exercises/bowling/.gitignore +7 -0
- data/tracks/rust/exercises/bowling/Cargo.toml +3 -0
- data/tracks/rust/exercises/bowling/example.rs +134 -0
- data/tracks/rust/exercises/bowling/tests/bowling.rs +373 -0
- data/tracks/rust/exercises/grains/.gitignore +7 -0
- data/tracks/rust/exercises/grains/Cargo.toml +3 -0
- data/tracks/rust/exercises/grains/example.rs +11 -0
- data/tracks/rust/exercises/grains/src/lib.rs +7 -0
- data/tracks/rust/exercises/grains/tests/grains.rs +63 -0
- data/tracks/rust/problems.md +2 -0
- data/tracks/scala/README.md +38 -0
- data/tracks/scala/config.json +20 -74
- data/tracks/scala/exercises/accumulate/src/test/scala/accumulate_test.scala +4 -0
- data/tracks/scala/exercises/allergies/src/test/scala/allergies_test.scala +11 -0
- data/tracks/scala/exercises/alphametics/build.sbt +6 -0
- data/tracks/scala/exercises/alphametics/example.scala +125 -0
- data/tracks/scala/exercises/alphametics/src/main/scala/.keep +0 -0
- data/tracks/scala/exercises/alphametics/src/test/scala/AlphameticsTest.scala +62 -0
- data/tracks/scala/exercises/atbash-cipher/src/test/scala/atbash_test.scala +8 -0
- data/tracks/scala/exercises/bank-account/src/test/scala/BankAccountTest.scala +4 -0
- data/tracks/scala/exercises/binary/src/test/scala/binary_test.scala +13 -0
- data/tracks/scala/exercises/binary-search-tree/src/test/scala/BstTest.scala +11 -0
- data/tracks/scala/exercises/bowling/Example.scala +116 -0
- data/tracks/scala/exercises/bowling/build.sbt +3 -0
- data/tracks/scala/exercises/bowling/src/main/scala/Bowling.scala +11 -0
- data/tracks/scala/exercises/bowling/src/test/scala/BowlingSuite.scala +237 -0
- data/tracks/scala/exercises/clock/src/test/scala/ClockTest.scala +50 -0
- data/tracks/scala/exercises/connect/README.md +17 -0
- data/tracks/scala/exercises/connect/src/test/scala/ConnectTest.scala +7 -0
- data/tracks/scala/exercises/crypto-square/src/test/scala/{CrytpoSquareTest.scala → CryptoSquareTest.scala} +9 -0
- data/tracks/scala/exercises/custom-set/src/test/scala/CustomSetTest.scala +36 -0
- data/tracks/scala/exercises/difference-of-squares/src/test/scala/squares_test.scala +8 -0
- data/tracks/scala/exercises/forth/src/test/scala/ForthTest.scala +22 -0
- data/tracks/scala/exercises/hexadecimal/src/test/scala/HexadecimalTest.scala +8 -0
- data/tracks/scala/exercises/kindergarten-garden/src/test/scala/GardenTest.scala +5 -0
- data/tracks/scala/exercises/largest-series-product/src/test/scala/SeriesTest.scala +2 -0
- data/tracks/scala/exercises/linked-list/src/test/scala/DequeTest.scala +4 -0
- data/tracks/scala/exercises/luhn/src/test/scala/LuhnTest.scala +4 -0
- data/tracks/scala/exercises/matrix/src/test/scala/MatrixTest.scala +2 -0
- data/tracks/scala/exercises/minesweeper/src/test/scala/MinesweeperTest.scala +6 -0
- data/tracks/scala/exercises/nth-prime/src/test/scala/PrimeTest.scala +5 -0
- data/tracks/scala/exercises/ocr-numbers/src/test/scala/OcrTest.scala +15 -0
- data/tracks/scala/exercises/octal/src/test/scala/OctalTest.scala +7 -0
- data/tracks/scala/exercises/parallel-letter-frequency/src/test/scala/FrequencyTest.scala +8 -0
- data/tracks/scala/exercises/pascals-triangle/src/test/scala/PascalsTriangleTest.scala +5 -0
- data/tracks/scala/exercises/pig-latin/src/test/scala/PigLatinTest.scala +4 -0
- data/tracks/scala/exercises/pythagorean-triplet/src/test/scala/PythagoreanTripletTest.scala +3 -0
- data/tracks/scala/exercises/queen-attack/src/test/scala/QueensTest.scala +5 -0
- data/tracks/scala/exercises/robot-simulator/src/test/scala/RobotTest.scala +16 -8
- data/tracks/scala/exercises/say/src/test/scala/SayTest.scala +34 -17
- data/tracks/scala/exercises/scrabble-score/src/test/scala/scrabble_score_test.scala +6 -0
- data/tracks/scala/exercises/secret-handshake/src/test/scala/SecretHandshakeTest.scala +18 -9
- data/tracks/scala/exercises/series/src/test/scala/SeriesTest.scala +4 -2
- data/tracks/scala/exercises/sieve/src/test/scala/SieveTest.scala +8 -4
- data/tracks/scala/exercises/simple-cipher/src/test/scala/CipherTest.scala +17 -9
- data/tracks/scala/exercises/sublist/src/test/scala/sublist_test.scala +17 -0
- data/tracks/scala/exercises/trinary/src/test/scala/TrinaryTest.scala +14 -7
- data/tracks/scala/exercises/wordy/src/test/scala/WordProblemTest.scala +28 -14
- data/tracks/scala/project/Build.scala +3 -3
- data/tracks/scala/testgen/src/main/scala/BowlingTestGenerator.scala +57 -0
- data/tracks/sml/config.json +41 -6
- data/tracks/sml/exercises/flatten-array/example.sml +6 -0
- data/tracks/sml/exercises/flatten-array/test_flatten_array.sml +10 -0
- data/tracks/sml/exercises/nth-prime/example.sml +46 -0
- data/tracks/sml/exercises/nth-prime/test_nth_prime.sml +14 -0
- data/tracks/sml/exercises/raindrops/example.sml +9 -0
- data/tracks/sml/exercises/raindrops/raindrops.sml +2 -0
- data/tracks/sml/exercises/raindrops/test_raindrops.sml +95 -0
- data/tracks/swift/config.json +269 -328
- data/tracks/swift/exercises/pangram/PangramExample.swift +17 -0
- data/tracks/swift/exercises/pangram/PangramTest.swift +43 -0
- data/tracks/swift/xcodeProject/xSwift.xcodeproj/project.pbxproj +16 -0
- 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,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(
|
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
|
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
|
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
|
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
|
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"
|