trackler 2.0.3.4 → 2.0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/common/exercises/all-your-base/canonical-data.json +21 -21
  3. data/common/exercises/wordy/description.md +24 -38
  4. data/common/exercises/wordy/metadata.yml +1 -1
  5. data/lib/trackler/version.rb +1 -1
  6. data/tracks/c/config.json +10 -0
  7. data/tracks/c/exercises/meetup/makefile +15 -0
  8. data/tracks/c/exercises/meetup/src/example.c +139 -0
  9. data/tracks/c/exercises/meetup/src/example.h +7 -0
  10. data/tracks/c/exercises/meetup/test/test_meetup.c +223 -0
  11. data/tracks/c/exercises/meetup/test/vendor/unity.c +1300 -0
  12. data/tracks/c/exercises/meetup/test/vendor/unity.h +274 -0
  13. data/tracks/c/exercises/meetup/test/vendor/unity_internals.h +701 -0
  14. data/tracks/crystal/config.json +12 -0
  15. data/tracks/crystal/exercises/pascals-triangle/spec/pascals_triangle_spec.cr +30 -0
  16. data/tracks/crystal/exercises/pascals-triangle/src/example.cr +19 -0
  17. data/tracks/crystal/exercises/pascals-triangle/src/pascals_triangle.cr +1 -0
  18. data/tracks/crystal/exercises/run-length-encoding/spec/run_length_encoding_spec.cr +36 -0
  19. data/tracks/crystal/exercises/run-length-encoding/src/example.cr +40 -0
  20. data/tracks/crystal/src/generator/exercises/pascals-triangle.cr +58 -0
  21. data/tracks/crystal/src/generator/exercises/run_length_encoding.cr +42 -0
  22. data/tracks/javascript/config.json +8 -1
  23. data/tracks/javascript/exercises/all-your-base/all-your-base.spec.js +141 -0
  24. data/tracks/javascript/exercises/all-your-base/example.js +59 -0
  25. data/tracks/javascript/exercises/word-count/example.js +5 -5
  26. data/tracks/javascript/exercises/word-count/word-count.spec.js +23 -8
  27. data/tracks/lua/SETUP.md +60 -7
  28. data/tracks/lua/config.json +9 -0
  29. data/tracks/lua/exercises/say/example.lua +4 -4
  30. data/tracks/lua/exercises/variable-length-quantity/example.lua +36 -0
  31. data/tracks/lua/exercises/variable-length-quantity/variable-length-quantity_spec.lua +73 -0
  32. data/tracks/objective-c/.travis.yml +1 -0
  33. data/tracks/objective-c/config.json +8 -0
  34. data/tracks/objective-c/docs/TESTS.md +1 -1
  35. data/tracks/objective-c/exercises/transpose/TransposeExample.h +7 -0
  36. data/tracks/objective-c/exercises/transpose/TransposeExample.m +59 -0
  37. data/tracks/objective-c/exercises/transpose/TransposeTest.m +150 -0
  38. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
  39. data/tracks/ocaml/.gitignore +1 -0
  40. data/tracks/ocaml/tools/test-generator/Makefile +3 -0
  41. data/tracks/ocaml/tools/test-generator/src/controller.ml +11 -16
  42. data/tracks/ocaml/tools/test-generator/src/model.ml +4 -0
  43. data/tracks/ocaml/tools/test-generator/src/parser.ml +8 -1
  44. data/tracks/ocaml/tools/test-generator/src/special_cases.ml +5 -0
  45. data/tracks/ocaml/tools/test-generator/templates/all-your-base/template.ml +16 -0
  46. data/tracks/ocaml/tools/test-generator/test/model_test.ml +2 -0
  47. data/tracks/ocaml/tools/test-generator/test/parser_test.ml +8 -0
  48. data/tracks/perl5/docs/RESOURCES.md +57 -0
  49. data/tracks/perl5/exercises/hamming/Example.pm +7 -0
  50. data/tracks/perl5/exercises/hamming/hamming.t +17 -4
  51. data/tracks/perl5/exercises/rna-transcription/rna.t +4 -4
  52. data/tracks/perl6/.gitignore +2 -0
  53. data/tracks/perl6/config.json +5 -0
  54. data/tracks/perl6/exercises/phone-number/Example.pm +30 -0
  55. data/tracks/perl6/exercises/phone-number/cases.json +47 -0
  56. data/tracks/perl6/exercises/phone-number/phone.t +48 -0
  57. data/tracks/purescript/.gitignore +8 -0
  58. data/tracks/purescript/config.json +8 -3
  59. data/tracks/purescript/exercises/hello-world/bower.json +17 -0
  60. data/tracks/purescript/exercises/hello-world/examples/src/HelloWorld.purs +8 -0
  61. data/tracks/purescript/exercises/hello-world/src/HelloWorld.purs +6 -0
  62. data/tracks/purescript/exercises/hello-world/test/Main.purs +18 -0
  63. data/tracks/scala/exercises/leap/HINTS.md +4 -0
  64. data/tracks/scala/exercises/robot-name/HINTS.md +5 -0
  65. data/tracks/swift/docs/INSTALLATION.md +4 -1
  66. data/tracks/swift/exercises/accumulate/AccumulateTest.swift +1 -1
  67. data/tracks/swift/exercises/binary/BinaryExample.swift +4 -1
  68. data/tracks/swift/exercises/crypto-square/CryptoSquareExample.swift +3 -2
  69. data/tracks/swift/exercises/leap/LeapExample.swift +1 -3
  70. data/tracks/swift/exercises/pascals-triangle/PascalsTriangleTest.swift +1 -1
  71. data/tracks/swift/exercises/poker/PokerExample.swift +3 -3
  72. data/tracks/swift/exercises/poker/PokerTest.swift +38 -38
  73. data/tracks/swift/exercises/saddle-points/SaddlePointsTest.swift +1 -1
  74. data/tracks/swift/exercises/scrabble-score/ScrabbleScoreExample.swift +6 -3
  75. data/tracks/swift/exercises/series/SeriesTest.swift +1 -1
  76. data/tracks/swift/exercises/simple-linked-list/SimpleLinkedListExample.swift +2 -2
  77. data/tracks/swift/exercises/space-age/SpaceAgeExample.swift +10 -12
  78. data/tracks/swift/exercises/strain/StrainTest.swift +1 -1
  79. data/tracks/swift/exercises/tournament/TournamentExample.swift +2 -2
  80. data/tracks/swift/exercises/triangle/TriangleExample.swift +7 -3
  81. data/tracks/swift/exercises/wordy/WordyExample.swift +1 -2
  82. metadata +34 -3
  83. data/tracks/purescript/exercises/.keep +0 -0
@@ -65,6 +65,8 @@
65
65
  E94ACA151D41763800D56CC2 /* AllYourBaseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E94ACA141D41763800D56CC2 /* AllYourBaseTest.m */; };
66
66
  E951B6B71D4294E6009EB5B6 /* AllergiesExample.m in Sources */ = {isa = PBXBuildFile; fileRef = E951B6B61D4294E6009EB5B6 /* AllergiesExample.m */; };
67
67
  E951B6B91D429550009EB5B6 /* AllergiesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E951B6B81D429550009EB5B6 /* AllergiesTest.m */; };
68
+ E96993981DF60E1E009EA223 /* TransposeExample.m in Sources */ = {isa = PBXBuildFile; fileRef = E96993971DF60E1E009EA223 /* TransposeExample.m */; };
69
+ E969939A1DF60E5F009EA223 /* TransposeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E96993991DF60E5F009EA223 /* TransposeTest.m */; };
68
70
  E99D1D811D5533BF0006A303 /* SumOfMultiplesExample.m in Sources */ = {isa = PBXBuildFile; fileRef = E99D1D801D5533BF0006A303 /* SumOfMultiplesExample.m */; };
69
71
  E99D1D831D5533D80006A303 /* SumOfMultiplesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E99D1D821D5533D80006A303 /* SumOfMultiplesTest.m */; };
70
72
  E9A7B2F71DA5AC37009056B6 /* LargestSeriesProductExample.m in Sources */ = {isa = PBXBuildFile; fileRef = E9A7B2F61DA5AC37009056B6 /* LargestSeriesProductExample.m */; };
@@ -150,6 +152,9 @@
150
152
  E951B6B51D4294E6009EB5B6 /* AllergiesExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AllergiesExample.h; path = ../../exercises/allergies/AllergiesExample.h; sourceTree = "<group>"; };
151
153
  E951B6B61D4294E6009EB5B6 /* AllergiesExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AllergiesExample.m; path = ../../exercises/allergies/AllergiesExample.m; sourceTree = "<group>"; };
152
154
  E951B6B81D429550009EB5B6 /* AllergiesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AllergiesTest.m; path = ../../exercises/allergies/AllergiesTest.m; sourceTree = "<group>"; };
155
+ E96993961DF60E1E009EA223 /* TransposeExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TransposeExample.h; path = ../../exercises/transpose/TransposeExample.h; sourceTree = "<group>"; };
156
+ E96993971DF60E1E009EA223 /* TransposeExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TransposeExample.m; path = ../../exercises/transpose/TransposeExample.m; sourceTree = "<group>"; };
157
+ E96993991DF60E5F009EA223 /* TransposeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TransposeTest.m; path = ../../exercises/transpose/TransposeTest.m; sourceTree = "<group>"; };
153
158
  E99D1D7F1D5533BF0006A303 /* SumOfMultiplesExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SumOfMultiplesExample.h; path = "../../exercises/sum-of-multiples/SumOfMultiplesExample.h"; sourceTree = "<group>"; };
154
159
  E99D1D801D5533BF0006A303 /* SumOfMultiplesExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SumOfMultiplesExample.m; path = "../../exercises/sum-of-multiples/SumOfMultiplesExample.m"; sourceTree = "<group>"; };
155
160
  E99D1D821D5533D80006A303 /* SumOfMultiplesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SumOfMultiplesTest.m; path = "../../exercises/sum-of-multiples/SumOfMultiplesTest.m"; sourceTree = "<group>"; };
@@ -214,6 +219,7 @@
214
219
  E9C1C0201D9D98B80015E86E /* SecretHandshake */,
215
220
  E9E8B6F61D519E340012F12C /* SpaceAge */,
216
221
  E99D1D7B1D5532C50006A303 /* SumOfMultiples */,
222
+ E96993951DF60DF1009EA223 /* Transpose */,
217
223
  E947A4DB1D81FDDA00633720 /* Triangle */,
218
224
  E9E8B6F71D519E3A0012F12C /* WordCount */,
219
225
  1E50BD001CB465C500FC128D /* Info.plist */,
@@ -307,6 +313,16 @@
307
313
  name = Triangle;
308
314
  sourceTree = "<group>";
309
315
  };
316
+ E96993951DF60DF1009EA223 /* Transpose */ = {
317
+ isa = PBXGroup;
318
+ children = (
319
+ E96993961DF60E1E009EA223 /* TransposeExample.h */,
320
+ E96993971DF60E1E009EA223 /* TransposeExample.m */,
321
+ E96993991DF60E5F009EA223 /* TransposeTest.m */,
322
+ );
323
+ name = Transpose;
324
+ sourceTree = "<group>";
325
+ };
310
326
  E99D1D7B1D5532C50006A303 /* SumOfMultiples */ = {
311
327
  isa = PBXGroup;
312
328
  children = (
@@ -617,6 +633,7 @@
617
633
  1EFACAA31CCCAF3D006F2E69 /* AnagramExample.m in Sources */,
618
634
  E94ACA131D41760300D56CC2 /* AllYourBaseExample.m in Sources */,
619
635
  E94ACA151D41763800D56CC2 /* AllYourBaseTest.m in Sources */,
636
+ E96993981DF60E1E009EA223 /* TransposeExample.m in Sources */,
620
637
  E9C1C0291D9DB16B0015E86E /* AcronymExample.m in Sources */,
621
638
  1EFACAA41CCCAF3D006F2E69 /* AnagramTest.m in Sources */,
622
639
  E907FE921D87547D00B93DA9 /* ScrabbleScoreExample.m in Sources */,
@@ -669,6 +686,7 @@
669
686
  E9A7B2F91DA5AC55009056B6 /* LargestSeriesProductTest.m in Sources */,
670
687
  1EFACAAF1CCCAF3D006F2E69 /* LeapExample.m in Sources */,
671
688
  E9C1C0251D9D99620015E86E /* SecretHandshakeTest.m in Sources */,
689
+ E969939A1DF60E5F009EA223 /* TransposeTest.m in Sources */,
672
690
  E99D1D831D5533D80006A303 /* SumOfMultiplesTest.m in Sources */,
673
691
  1EFACAAA1CCCAF3D006F2E69 /* GradeSchoolTest.m in Sources */,
674
692
  );
@@ -3,6 +3,7 @@
3
3
  .DS_Store
4
4
  tmp
5
5
  *.native
6
+ *.byte
6
7
  _build/
7
8
  bin/configlet
8
9
  bin/configlet.exe
@@ -1,6 +1,9 @@
1
1
  test: test_gen.native
2
2
  @./all_tests.native
3
3
 
4
+ test_gen.byte: all_tests.native src/*.ml interfaces/*.mli test/*.ml
5
+ @ocamlbuild -use-ocamlfind -tag thread -tag short_paths -cflags -strict-sequence -r -pkg core -pkg yojson -pkg ppx_deriving -pkg ppx_deriving.eq -pkg ppx_deriving.show -Is src,interfaces test_gen.byte
6
+
4
7
  test_gen.native: all_tests.native src/*.ml interfaces/*.mli test/*.ml
5
8
  @ocamlbuild -use-ocamlfind -tag thread -tag short_paths -cflags -strict-sequence -r -pkg core -pkg yojson -pkg ppx_deriving -pkg ppx_deriving.eq -pkg ppx_deriving.show -Is src,interfaces test_gen.native
6
9
 
@@ -23,26 +23,21 @@ let combine_files (template_files: (string * content) list) (canonical_data_file
23
23
 
24
24
  let generate_code ~(slug: string) ~(template_file: content) ~(canonical_data_file: content): (content, content) Result.t =
25
25
  let template = find_template template_file in
26
+ let edit_expected = edit_expected ~stringify:parameter_to_string ~slug in
27
+ let edit_parameters = edit_parameters ~slug in
28
+ let fill_in_template = fill_in_template edit_expected edit_parameters in
26
29
  let open Result.Monad_infix in
27
30
  Result.of_option template ("cannot recognize file for " ^ slug ^ " as a template") >>= fun template ->
28
- parse_json_text canonical_data_file |> Result.map_error ~f:show_error >>= (function
31
+ parse_json_text canonical_data_file
32
+ |> Result.map_error ~f:show_error >>= (function
29
33
  | Single cases ->
30
- Result.return (fill_in_template
31
- (edit_expected ~stringify:parameter_to_string ~slug)
32
- (edit_parameters ~slug)
33
- template.template
34
- slug
35
- cases |> fill_tests template);
34
+ fill_in_template template.template slug cases
35
+ |> fill_tests template
36
+ |> Result.return
36
37
  | Suite tests ->
37
- let x = List.map tests ~f:(fun {name;cases} ->
38
- (name, fill_in_template
39
- (edit_expected ~stringify:parameter_to_string ~slug)
40
- (edit_parameters ~slug)
41
- template.template
42
- name
43
- cases)
44
- ) in
45
- Result.return (fill_suite template x)
38
+ List.map tests ~f:(fun {name;cases} -> (name, fill_in_template template.template name cases))
39
+ |> fill_suite template
40
+ |> Result.return
46
41
  )
47
42
 
48
43
  let output_tests (files: (string * content * content) list) (output_folder: string): unit =
@@ -3,11 +3,13 @@ open Core.Std
3
3
  open Utils
4
4
 
5
5
  type parameter =
6
+ | Null
6
7
  | String of string
7
8
  | Float of float
8
9
  | Int of int
9
10
  | Bool of bool
10
11
  | StringList of (string list)
12
+ | IntList of (int list)
11
13
  | IntStringMap of ((string * int) list) [@@deriving eq, show]
12
14
 
13
15
  type 'a elements = (string * 'a) list [@@deriving eq, show]
@@ -28,10 +30,12 @@ let surround (ch: char) (s: string): string =
28
30
  Char.to_string ch ^ s ^ Char.to_string ch
29
31
 
30
32
  let parameter_to_string = function
33
+ | Null -> "null"
31
34
  | String s -> String.escaped s
32
35
  | Float f -> Float.to_string f
33
36
  | Int n -> Int.to_string n
34
37
  | Bool b -> Bool.to_string b
35
38
  | StringList xs -> "[" ^ String.concat ~sep:"; " (List.map ~f:(surround '\"' >> String.escaped) xs) ^ "]"
39
+ | IntList xs -> "[" ^ String.concat ~sep:"; " (List.map ~f:Int.to_string xs) ^ "]"
36
40
  | IntStringMap xs -> "[" ^ String.concat ~sep:"; "
37
41
  (List.map xs ~f:(fun (k,v) -> "(\"" ^ String.escaped k ^ "\", " ^ Int.to_string v ^ ")")) ^ "]"
@@ -12,12 +12,19 @@ let to_int_unsafe = function
12
12
  | `Int x -> x
13
13
  | _ -> failwith "need an int here"
14
14
 
15
+ let to_list_safe xs = match xs with
16
+ | [] -> Some (StringList [])
17
+ | `String x :: _ -> Some (StringList (List.map xs ~f:to_string))
18
+ | `Int x :: _ -> Some (IntList (List.map xs ~f:to_int_unsafe))
19
+ | _ -> None
20
+
15
21
  let to_parameter (s: json) = match s with
22
+ | `Null -> Some (Null)
16
23
  | `String x -> Some (String x)
17
24
  | `Float x -> Some (Float x)
18
25
  | `Int x -> Some (Int x)
19
26
  | `Bool x -> Some (Bool x)
20
- | `List x -> Some (StringList (List.map x ~f:to_string))
27
+ | `List x -> to_list_safe x
21
28
  | `Assoc x -> Some (IntStringMap (List.map x ~f:(fun (k,v) -> (k,to_int_unsafe v))))
22
29
  | _ -> None
23
30
 
@@ -7,6 +7,10 @@ let optional_int ~(none: int) = function
7
7
  | Int n -> "(Some " ^ Int.to_string n ^ ")"
8
8
  | x -> parameter_to_string x
9
9
 
10
+ let optional_int_list = function
11
+ | IntList xs -> "(Some " ^ String.concat ~sep:"; " (List.map ~f:Int.to_string xs) ^ ")"
12
+ | _ -> "None"
13
+
10
14
  let optional_int_or_string ~(none: int) = function
11
15
  | String s -> "(Some \"" ^ s ^ "\")"
12
16
  | Int n when n = none -> "None"
@@ -27,6 +31,7 @@ let optional_strings ~(f: string -> bool) (parameters: (string * string) list):
27
31
 
28
32
  let edit_expected ~(stringify: parameter -> string) ~(slug: string) ~(value: parameter) = match slug with
29
33
  | "hamming" -> optional_int ~none:(-1) value
34
+ | "all-your-base" -> optional_int_list value
30
35
  | "say" -> optional_int_or_string ~none:(-1) value
31
36
  | _ -> stringify value
32
37
 
@@ -0,0 +1,16 @@
1
+ open Core.Std
2
+ open OUnit2
3
+ open All_your_bases
4
+
5
+ let ae exp got _test_ctxt =
6
+ assert_equal exp got ~printer:Bool.to_string
7
+
8
+ let tests = [
9
+ (* TEST
10
+ "$description" >::
11
+ ae $expected (convert_bases $input_base $input_digits $output_base);
12
+ END TEST *)
13
+ ]
14
+
15
+ let () =
16
+ run_test_tt_main ("all-your-bases tests" >::: tests)
@@ -20,6 +20,8 @@ let model_tests = [
20
20
  ae "[\"a\"; \"bc\"; \"def\"]" @@ parameter_to_string (StringList ["a"; "bc"; "def"]);
21
21
  "string list parameter with escaped characters to string" >::
22
22
  ae "[\"a\\r\"; \"b\\nc\"; \"d\\tef\"]" @@ parameter_to_string (StringList ["a\r"; "b\nc"; "d\tef"]);
23
+ "int list parameter to string" >::
24
+ ae "[1; 2; 3; 4]" @@ parameter_to_string (IntList [1; 2; 3; 4]);
23
25
  "int string map parameter to string" >::
24
26
  ae "[(\"one\", 1); (\"two\", 1)]" @@ parameter_to_string (IntStringMap [("one", 1); ("two", 1)]);
25
27
  "int string map parameter to string with escaped characters in the keys" >::
@@ -40,6 +40,14 @@ let parser_tests = [
40
40
  ae (single [{description = "d1"; parameters = []; expected = Bool true}])
41
41
  (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : true}]}");
42
42
 
43
+ "parses a single element with a description and expected int list output" >::
44
+ ae (single [{description = "d1"; parameters = []; expected = IntList [1;2;3]}])
45
+ (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : [1, 2, 3]}]}");
46
+
47
+ "parses a single element with a description and expected null output" >::
48
+ ae (single [{description = "d1"; parameters = []; expected = Null}])
49
+ (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : null}]}");
50
+
43
51
  "parses a single element with an int key value pair" >::
44
52
  ae (single [{description = "d1"; parameters = [("input", Int 1996)]; expected = Bool true}])
45
53
  (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"input\" : 1996, \"expected\" : true}]}");
@@ -0,0 +1,57 @@
1
+ ## Code Style and Linting
2
+
3
+ If you are looking for good general advices regarding Perl coding,
4
+ Damian Conway's [Perl Best Practices][PBP] is a good reference.
5
+
6
+ To prettify your code, you can use the module
7
+ [Perl-Tidy][PerlTidy].
8
+
9
+ To install with [cpanminus][]:
10
+
11
+ cpanm Perl-Tidy
12
+
13
+ or via the regular `cpan` install utility:
14
+
15
+ cpan Perl-Tidy
16
+
17
+ And then, you can use the provided `perltidy` utility program
18
+ to reformat your code.
19
+
20
+ # modify file in-place and save old version as some_script.pl.bak
21
+ $ perltidy -b some_script.pl
22
+
23
+ `perltidy` has a *lot* of configuration options to cater to every taste. They
24
+ are documented [here][perltidyDocs].
25
+
26
+ There is also [tidyview], a visual interface that allows you to
27
+ tweak the different options and immediately see the result.
28
+
29
+ If you want to enforce coding practices, there is also
30
+ [Perl::Critic][perlcritic]. It comes with the rules described in
31
+ the book *Perl Best Practices* mentioned previously, but plenty of
32
+ plugins exist, and it can be customized to fit any in-house coding
33
+ rules.
34
+
35
+ To install:
36
+
37
+ # via cpanminus
38
+ cpanm Perl-Critic
39
+
40
+ # via the classic 'cpan' installation tool
41
+ cpan Perl-Critic
42
+
43
+ To use:
44
+
45
+ $ perlcritic some_script.pl
46
+
47
+ The tool has many, many configuration tweaks, see its
48
+ [documentation][perlcriticdocs] for the full scoop on them.
49
+
50
+
51
+ [PBP]: http://shop.oreilly.com/product/9780596001735.do
52
+ [PerlTidy]: https://metacpan.org/release/Perl-Tidy
53
+ [cpanminus]: http://search.cpan.org/~miyagawa/App-cpanminus-1.7042
54
+ [perltidyDocs]: https://metacpan.org/pod/distribution/Perl-Tidy/docs/stylekey.pod
55
+ [tidyview]: https://sourceforge.net/projects/tidyview/
56
+ [perlcritic]: https://metacpan.org/release/Perl-Critic
57
+ [perlcriticdocs]: https://metacpan.org/pod/distribution/Perl-Critic/bin/perlcritic
@@ -3,10 +3,17 @@ package Example;
3
3
  use strict;
4
4
  use warnings;
5
5
 
6
+ use Carp;
7
+
6
8
  sub compute {
7
9
  my ($strand_a, $strand_b) = @_;
10
+
11
+ croak "DNA strands must be of equal length"
12
+ unless length $strand_a == length $strand_b;
13
+
8
14
  my $distance = $strand_a ^ $strand_b;
9
15
  $distance =~ s/\0//g;
16
+
10
17
  return (length $distance) - abs(length($strand_a) - length($strand_b));
11
18
  }
12
19
 
@@ -10,19 +10,32 @@ use lib $dir;
10
10
 
11
11
  my $module = $ENV{EXERCISM} ? 'Example' : 'Hamming';
12
12
 
13
- plan tests => 11;
13
+ plan tests => 12;
14
14
 
15
15
  ok -e "${dir}${module}.pm", "Missing $module.pm" or BAIL_OUT "You need to create file: $module.pm";
16
16
  eval "use $module";
17
17
  ok !$@, "Cannot load $module" or BAIL_OUT "Cannot load $module. Does it compile? Does it end with 1;?";
18
18
  can_ok $module, 'compute' or BAIL_OUT "Missing package $module; or missing sub compute()?";
19
19
 
20
+ sub dies_like(&$$) {
21
+ my( $code, $expected, $message ) = @_;
22
+ eval { $code->() };
23
+ like $@ => $expected, $message;
24
+ }
25
+
20
26
  my $sub = \&{"$module" . "::compute"};
21
27
  is $sub->('A', 'A'), 0, "identical strands";
28
+ is $sub->('A', 'G'), 1, "different strands";
22
29
  is $sub->('AG', 'CT'), 2, "completely different strands";
23
30
  is $sub->('AT', 'CT'), 1, "one hamming distance";
24
31
  is $sub->('GGACG', 'GGTCG'), 1, "one hamming distance, longer strands";
25
- is $sub->('AAAG', 'AAA'), 0, "ignore extra length on 1st strand";
26
- is $sub->('AAA', 'AAAG'), 0, "ignore extra length on 2nd strand";
27
32
  is $sub->('GATACA', 'GCATAA'), 4, "4 hamming distance";
28
- is $sub->('GGACGGATTCTG', 'AGGACGGATTCT'), 9, "9 hamming distance"
33
+ is $sub->('GGACGGATTCTG', 'AGGACGGATTCT'), 9, "9 hamming distance";
34
+
35
+ dies_like { $sub->('AAAG', 'AAA') }
36
+ qr/DNA strands must be of equal length/,
37
+ "extra length on 1st strand";
38
+
39
+ dies_like { $sub->('AAA', 'AAAG') }
40
+ qr/DNA strands must be of equal length/,
41
+ "extra length on 2nd strand";
@@ -11,10 +11,10 @@ use lib $dir;
11
11
  my $module = $ENV{EXERCISM} ? 'Example' : 'DNA';
12
12
 
13
13
  my @cases = (
14
- ['C', 'G', 'cytidine unchanged'],
15
- ['G', 'C', 'guanosine unchanged'],
16
- ['T', 'A', 'adenosine unchanged'],
17
- ['A', 'U', 'thymidine to uracil'],
14
+ ['C', 'G', 'cytosine unchanged'],
15
+ ['G', 'C', 'guanine unchanged'],
16
+ ['T', 'A', 'adenine unchanged'],
17
+ ['A', 'U', 'thymine to uracil'],
18
18
  ['ACGTGGTCTTAA', 'UGCACCAGAAUU', 'transcribes all occurences'],
19
19
  );
20
20
 
@@ -1,2 +1,4 @@
1
1
  bin/configlet
2
2
  bin/configlet.exe
3
+ # dir created when a Perl 6 module is used
4
+ .precomp
@@ -61,6 +61,11 @@
61
61
  "slug": "accumulate",
62
62
  "topics": []
63
63
  },
64
+ {
65
+ "difficulty": 1,
66
+ "slug": "phone-number",
67
+ "topics": []
68
+ },
64
69
  {
65
70
  "difficulty": 1,
66
71
  "slug": "rna-transcription",
@@ -0,0 +1,30 @@
1
+ use v6;
2
+
3
+ class X::Phone::Invalid is Exception {
4
+ has $.payload;
5
+ method message {"'$!payload' is not valid."}
6
+ }
7
+
8
+ class Phone {
9
+ has $.number;
10
+
11
+ method new (:$number!) {
12
+ my $validated = $number;
13
+ $validated ~~ s:g/<:!Decimal_Number>//;
14
+ $validated ~~ /^ 1? (\d ** 10) $/ ?? ($validated = ~$0) !! X::Phone::Invalid.new(:payload«$number»).throw;
15
+ self.bless(:number«$validated»);
16
+ }
17
+
18
+ method area-code {
19
+ $!number ~~ /\d**3/ and return ~$/;
20
+ }
21
+
22
+ method pretty {
23
+ $!number ~~ /
24
+ $<area-code> = \d**3
25
+ $<central-office-code> = \d**3
26
+ $<station-number> = \d**4
27
+ / and return "($<area-code>) $<central-office-code>-$<station-number>";
28
+ }
29
+ }
30
+
@@ -0,0 +1,47 @@
1
+ {
2
+ "valid": [
3
+ {
4
+ "input": 1234567890,
5
+ "number": "1234567890",
6
+ "area-code": "123",
7
+ "pretty": "(123) 456-7890",
8
+ "test": "10 digit integer"
9
+ },
10
+ {
11
+ "input": "+1 (234) 555-6789",
12
+ "number": "2345556789",
13
+ "area-code": "234",
14
+ "pretty": "(234) 555-6789",
15
+ "test": "11 digit formatted number"
16
+ },
17
+ {
18
+ "input": "1.379.555.2468",
19
+ "number": "3795552468",
20
+ "area-code": "379",
21
+ "pretty": "(379) 555-2468",
22
+ "test": "11 digit number containing separators"
23
+ }
24
+ ],
25
+ "invalid": [
26
+ {
27
+ "input": "",
28
+ "test": "empty input"
29
+ },
30
+ {
31
+ "input": "13579",
32
+ "test": "5 digit number"
33
+ },
34
+ {
35
+ "input": "123456789011",
36
+ "test": "12 digit number"
37
+ },
38
+ {
39
+ "input": "+2 (468) 555-1379",
40
+ "test": "11 digit number not beginning with 1"
41
+ },
42
+ {
43
+ "input": "phone number",
44
+ "test": "not a number"
45
+ }
46
+ ]
47
+ }