trackler 2.0.3.4 → 2.0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/common/exercises/all-your-base/canonical-data.json +21 -21
- data/common/exercises/wordy/description.md +24 -38
- data/common/exercises/wordy/metadata.yml +1 -1
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +10 -0
- data/tracks/c/exercises/meetup/makefile +15 -0
- data/tracks/c/exercises/meetup/src/example.c +139 -0
- data/tracks/c/exercises/meetup/src/example.h +7 -0
- data/tracks/c/exercises/meetup/test/test_meetup.c +223 -0
- data/tracks/c/exercises/meetup/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/meetup/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/meetup/test/vendor/unity_internals.h +701 -0
- data/tracks/crystal/config.json +12 -0
- data/tracks/crystal/exercises/pascals-triangle/spec/pascals_triangle_spec.cr +30 -0
- data/tracks/crystal/exercises/pascals-triangle/src/example.cr +19 -0
- data/tracks/crystal/exercises/pascals-triangle/src/pascals_triangle.cr +1 -0
- data/tracks/crystal/exercises/run-length-encoding/spec/run_length_encoding_spec.cr +36 -0
- data/tracks/crystal/exercises/run-length-encoding/src/example.cr +40 -0
- data/tracks/crystal/src/generator/exercises/pascals-triangle.cr +58 -0
- data/tracks/crystal/src/generator/exercises/run_length_encoding.cr +42 -0
- data/tracks/javascript/config.json +8 -1
- data/tracks/javascript/exercises/all-your-base/all-your-base.spec.js +141 -0
- data/tracks/javascript/exercises/all-your-base/example.js +59 -0
- data/tracks/javascript/exercises/word-count/example.js +5 -5
- data/tracks/javascript/exercises/word-count/word-count.spec.js +23 -8
- data/tracks/lua/SETUP.md +60 -7
- data/tracks/lua/config.json +9 -0
- data/tracks/lua/exercises/say/example.lua +4 -4
- data/tracks/lua/exercises/variable-length-quantity/example.lua +36 -0
- data/tracks/lua/exercises/variable-length-quantity/variable-length-quantity_spec.lua +73 -0
- data/tracks/objective-c/.travis.yml +1 -0
- data/tracks/objective-c/config.json +8 -0
- data/tracks/objective-c/docs/TESTS.md +1 -1
- data/tracks/objective-c/exercises/transpose/TransposeExample.h +7 -0
- data/tracks/objective-c/exercises/transpose/TransposeExample.m +59 -0
- data/tracks/objective-c/exercises/transpose/TransposeTest.m +150 -0
- data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
- data/tracks/ocaml/.gitignore +1 -0
- data/tracks/ocaml/tools/test-generator/Makefile +3 -0
- data/tracks/ocaml/tools/test-generator/src/controller.ml +11 -16
- data/tracks/ocaml/tools/test-generator/src/model.ml +4 -0
- data/tracks/ocaml/tools/test-generator/src/parser.ml +8 -1
- data/tracks/ocaml/tools/test-generator/src/special_cases.ml +5 -0
- data/tracks/ocaml/tools/test-generator/templates/all-your-base/template.ml +16 -0
- data/tracks/ocaml/tools/test-generator/test/model_test.ml +2 -0
- data/tracks/ocaml/tools/test-generator/test/parser_test.ml +8 -0
- data/tracks/perl5/docs/RESOURCES.md +57 -0
- data/tracks/perl5/exercises/hamming/Example.pm +7 -0
- data/tracks/perl5/exercises/hamming/hamming.t +17 -4
- data/tracks/perl5/exercises/rna-transcription/rna.t +4 -4
- data/tracks/perl6/.gitignore +2 -0
- data/tracks/perl6/config.json +5 -0
- data/tracks/perl6/exercises/phone-number/Example.pm +30 -0
- data/tracks/perl6/exercises/phone-number/cases.json +47 -0
- data/tracks/perl6/exercises/phone-number/phone.t +48 -0
- data/tracks/purescript/.gitignore +8 -0
- data/tracks/purescript/config.json +8 -3
- data/tracks/purescript/exercises/hello-world/bower.json +17 -0
- data/tracks/purescript/exercises/hello-world/examples/src/HelloWorld.purs +8 -0
- data/tracks/purescript/exercises/hello-world/src/HelloWorld.purs +6 -0
- data/tracks/purescript/exercises/hello-world/test/Main.purs +18 -0
- data/tracks/scala/exercises/leap/HINTS.md +4 -0
- data/tracks/scala/exercises/robot-name/HINTS.md +5 -0
- data/tracks/swift/docs/INSTALLATION.md +4 -1
- data/tracks/swift/exercises/accumulate/AccumulateTest.swift +1 -1
- data/tracks/swift/exercises/binary/BinaryExample.swift +4 -1
- data/tracks/swift/exercises/crypto-square/CryptoSquareExample.swift +3 -2
- data/tracks/swift/exercises/leap/LeapExample.swift +1 -3
- data/tracks/swift/exercises/pascals-triangle/PascalsTriangleTest.swift +1 -1
- data/tracks/swift/exercises/poker/PokerExample.swift +3 -3
- data/tracks/swift/exercises/poker/PokerTest.swift +38 -38
- data/tracks/swift/exercises/saddle-points/SaddlePointsTest.swift +1 -1
- data/tracks/swift/exercises/scrabble-score/ScrabbleScoreExample.swift +6 -3
- data/tracks/swift/exercises/series/SeriesTest.swift +1 -1
- data/tracks/swift/exercises/simple-linked-list/SimpleLinkedListExample.swift +2 -2
- data/tracks/swift/exercises/space-age/SpaceAgeExample.swift +10 -12
- data/tracks/swift/exercises/strain/StrainTest.swift +1 -1
- data/tracks/swift/exercises/tournament/TournamentExample.swift +2 -2
- data/tracks/swift/exercises/triangle/TriangleExample.swift +7 -3
- data/tracks/swift/exercises/wordy/WordyExample.swift +1 -2
- metadata +34 -3
- 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
|
);
|
data/tracks/ocaml/.gitignore
CHANGED
@@ -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
|
31
|
+
parse_json_text canonical_data_file
|
32
|
+
|> Result.map_error ~f:show_error >>= (function
|
29
33
|
| Single cases ->
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
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 ->
|
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 =>
|
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', '
|
15
|
-
['G', 'C', '
|
16
|
-
['T', 'A', '
|
17
|
-
['A', 'U', '
|
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
|
|
data/tracks/perl6/.gitignore
CHANGED
data/tracks/perl6/config.json
CHANGED
@@ -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
|
+
}
|