trackler 2.0.6.0 → 2.0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/csharp/.gitignore +3 -1
  4. data/tracks/csharp/README.md +1 -1
  5. data/tracks/csharp/build.fsx +6 -0
  6. data/tracks/csharp/circle.yml +16 -0
  7. data/tracks/csharp/paket.dependencies +2 -1
  8. data/tracks/csharp/paket.lock +3 -0
  9. data/tracks/ecmascript/exercises/phone-number/example.js +15 -28
  10. data/tracks/ecmascript/exercises/phone-number/phone-number.spec.js +28 -13
  11. data/tracks/fsharp/.gitignore +3 -1
  12. data/tracks/fsharp/README.md +1 -1
  13. data/tracks/fsharp/build.fsx +7 -1
  14. data/tracks/fsharp/circle.yml +16 -0
  15. data/tracks/fsharp/paket.dependencies +2 -1
  16. data/tracks/fsharp/paket.lock +3 -0
  17. data/tracks/ocaml/tools/test-generator/src/controller.ml +5 -5
  18. data/tracks/ocaml/tools/test-generator/src/model.ml +2 -0
  19. data/tracks/ocaml/tools/test-generator/src/parser.ml +35 -31
  20. data/tracks/ocaml/tools/test-generator/src/special_cases.ml +27 -23
  21. data/tracks/ocaml/tools/test-generator/src/utils.ml +2 -2
  22. data/tracks/ocaml/tools/test-generator/templates/dominoes/template.ml +40 -0
  23. data/tracks/ocaml/tools/test-generator/test/parser_test.ml +27 -21
  24. data/tracks/pony/config.json +5 -0
  25. data/tracks/pony/docs/ABOUT.md +12 -0
  26. data/tracks/pony/docs/INSTALLATION.md +4 -6
  27. data/tracks/pony/docs/LEARNING.md +7 -0
  28. data/tracks/pony/docs/RESOURCES.md +7 -0
  29. data/tracks/pony/docs/TESTS.md +11 -0
  30. data/tracks/pony/exercises/hamming/test.pony +2 -2
  31. data/tracks/pony/exercises/rna-transcription/example.pony +13 -0
  32. data/tracks/pony/exercises/rna-transcription/test.pony +32 -0
  33. data/tracks/r/exercises/anagram/example.R +18 -2
  34. data/tracks/r/exercises/bob/example.R +16 -1
  35. data/tracks/r/exercises/luhn/example.R +23 -7
  36. data/tracks/r/exercises/luhn/luhn.R +6 -0
  37. data/tracks/r/exercises/word-count/example.R +5 -0
  38. data/tracks/ruby/exercises/series/example.rb +12 -22
  39. data/tracks/ruby/exercises/series/series_test.rb +19 -12
  40. data/tracks/ruby/test/test_helper.rb +3 -3
  41. data/tracks/scala/config.json +7 -0
  42. data/tracks/scala/exercises/sieve/build.sbt +2 -2
  43. data/tracks/scala/exercises/simple-cipher/build.sbt +2 -2
  44. metadata +10 -1
@@ -3,18 +3,18 @@ open Core.Std
3
3
  open Model
4
4
 
5
5
  let optional_int ~(none: int) = function
6
- | Int n when n = none -> "None"
7
- | Int n -> "(Some " ^ Int.to_string n ^ ")"
8
- | x -> parameter_to_string x
6
+ | Int n when n = none -> "None"
7
+ | Int n -> "(Some " ^ Int.to_string n ^ ")"
8
+ | x -> parameter_to_string x
9
9
 
10
10
  let optional_int_list = function
11
- | IntList xs -> "(Some [" ^ String.concat ~sep:"; " (List.map ~f:Int.to_string xs) ^ "])"
12
- | _ -> "None"
11
+ | IntList xs -> "(Some [" ^ String.concat ~sep:"; " (List.map ~f:Int.to_string xs) ^ "])"
12
+ | _ -> "None"
13
13
 
14
14
  let optional_int_or_string ~(none: int) = function
15
- | String s -> "(Some \"" ^ s ^ "\")"
16
- | Int n when n = none -> "None"
17
- | x -> parameter_to_string x
15
+ | String s -> "(Some \"" ^ s ^ "\")"
16
+ | Int n when n = none -> "None"
17
+ | x -> parameter_to_string x
18
18
 
19
19
  let default_value ~(key: string) ~(value: string) (parameters: (string * string) list): (string * string) list =
20
20
  if List.exists ~f:(fun (k, _) -> k = key) parameters
@@ -30,28 +30,32 @@ let optional_strings ~(f: string -> bool) (parameters: (string * string) list):
30
30
  List.map ~f:replace parameters
31
31
 
32
32
  let edit_expected ~(stringify: parameter -> string) ~(slug: string) ~(value: parameter) = match slug with
33
- | "hamming" -> optional_int ~none:(-1) value
34
- | "all-your-base" -> optional_int_list value
35
- | "say" -> optional_int_or_string ~none:(-1) value
36
- | _ -> stringify value
33
+ | "hamming" -> optional_int ~none:(-1) value
34
+ | "all-your-base" -> optional_int_list value
35
+ | "say" -> optional_int_or_string ~none:(-1) value
36
+ | _ -> stringify value
37
37
 
38
38
  let edit_say (ps: (string * string) list) =
39
39
  let edit = function
40
- | ("input", v) -> ("input", if Int.of_string v >= 0 then "(" ^ v ^ "L)" else v ^ "L")
41
- | x -> x in
40
+ | ("input", v) -> ("input", if Int.of_string v >= 0 then "(" ^ v ^ "L)" else v ^ "L")
41
+ | x -> x in
42
42
  List.map ps ~f:edit
43
43
 
44
44
  let edit_all_your_base (ps: (string * string) list) =
45
45
  let edit = function
46
- | ("output_base", v) -> ("output_base", if Int.of_string v >= 0 then v else "(" ^ v ^ ")")
47
- | ("input_base", v) -> ("input_base", if Int.of_string v >= 0 then v else "(" ^ v ^ ")")
48
- | x -> x in
46
+ | ("output_base", v) -> ("output_base", if Int.of_string v >= 0 then v else "(" ^ v ^ ")")
47
+ | ("input_base", v) -> ("input_base", if Int.of_string v >= 0 then v else "(" ^ v ^ ")")
48
+ | x -> x in
49
49
  List.map ps ~f:edit
50
50
 
51
51
  let edit_parameters ~(slug: string) (parameters: (string * string) list) = match (slug, parameters) with
52
- | ("hello-world", ps) -> default_value ~key:"name" ~value:"None"
53
- @@ optional_strings ~f:(fun _x -> true)
54
- @@ parameters
55
- | ("say", ps) -> edit_say ps
56
- | ("all-your-base", ps) -> edit_all_your_base ps
57
- | (_, ps) -> ps
52
+ | ("hello-world", ps) -> default_value ~key:"name" ~value:"None"
53
+ @@ optional_strings ~f:(fun _x -> true)
54
+ @@ parameters
55
+ | ("say", ps) -> edit_say ps
56
+ | ("all-your-base", ps) -> edit_all_your_base ps
57
+ | (_, ps) -> ps
58
+
59
+ let expected_key_name slug = match slug with
60
+ | "dominoes" -> "can_chain"
61
+ | _ -> "expected"
@@ -1,6 +1,6 @@
1
1
  open Core.Std
2
- open Yojson.Safe
3
- open Yojson.Safe.Util
2
+ open Yojson.Basic
3
+ open Yojson.Basic.Util
4
4
 
5
5
  let map2 (f: 'a -> 'b -> 'c) (r1: ('a, 'e) Result.t) (r2: ('b, 'e) Result.t): ('c, 'e) Result.t = match (r1, r2) with
6
6
  | (Error x, _) -> Error x
@@ -0,0 +1,40 @@
1
+ open Core.Std
2
+ open OUnit2
3
+ open Dominoes
4
+
5
+ let print_dominoe (d1, d2) = sprintf "(%d,%d)" d1 d2
6
+
7
+ let option_printer = function
8
+ | None -> "None"
9
+ | Some xs -> "Some [" ^ String.concat ~sep:";" (List.map xs ~f:print_dominoe) ^ "]"
10
+
11
+ let drop_1_right xs = List.rev xs |> List.tl_exn |> List.rev
12
+
13
+ let check_chain (chained: dominoe list) =
14
+ let assert_dominoes_match d1 d2 =
15
+ if snd d1 <> fst d2 then failwith @@ sprintf "%s and %s cannot be chained together" (print_dominoe d1) (print_dominoe d2) else () in
16
+ let consecutives = List.zip_exn (drop_1_right chained) (List.tl_exn chained) in
17
+ List.iter consecutives ~f:(fun (d1, d2) -> assert_dominoes_match d1 d2)
18
+
19
+ let assert_empty c = if List.is_empty c then () else failwith "Expected 0 length chain"
20
+
21
+ let assert_valid_chain input _ctxt =
22
+ match chain input with
23
+ | None -> failwith "Expecting a chain"
24
+ | Some(c) -> (if List.is_empty input then assert_empty else check_chain) c
25
+
26
+ let assert_no_chain input _ctxt =
27
+ assert_equal None (chain input) ~printer:option_printer
28
+
29
+ let assert_chain input hasChain =
30
+ if hasChain then assert_valid_chain input else assert_no_chain input
31
+
32
+ let tests = [
33
+ (* TEST
34
+ "$description" >::
35
+ assert_chain $input $expected;
36
+ END TEST *)
37
+ ]
38
+
39
+ let () =
40
+ run_test_tt_main ("dominoes tests" >::: tests)
@@ -12,101 +12,107 @@ let ae exp got _test_ctxt = assert_equal exp got ~printer:show_cases
12
12
 
13
13
  let single x = Ok (Single x)
14
14
 
15
+ let call_parser json = parse_json_text json "expected"
16
+
15
17
  let parser_tests = [
16
18
  "parses empty json as empty list" >::
17
- ae (single []) (parse_json_text "{\"cases\" : []}");
19
+ ae (single []) (call_parser "{\"cases\" : []}");
18
20
 
19
21
  "gives an error with a json map that does not have the key cases in" >::
20
22
  ae (Error (TestMustHaveKeyCalledCases "case"))
21
- (parse_json_text "{\"case\" : [{\"description\" : \"d1\", \"expected\" : 100}]}");
23
+ (call_parser "{\"case\" : [{\"description\" : \"d1\", \"expected\" : 100}]}");
22
24
 
23
25
  "gives an error with cases that is not a json list" >::
24
26
  ae (Error ExpectingListOfCases)
25
- (parse_json_text "{\"cases\" : 11}");
27
+ (call_parser "{\"cases\" : 11}");
26
28
 
27
29
  "gives an error with a case that is not a json map" >::
28
30
  ae (Error ExpectingMapForCase)
29
- (parse_json_text "{\"cases\" : [\"key\"]}");
31
+ (call_parser "{\"cases\" : [\"key\"]}");
30
32
 
31
33
  "parses a single element with a description and expected string output" >::
32
34
  ae (single [{description = "d1"; parameters = []; expected = String "value"}])
33
- (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : \"value\"}]}");
35
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : \"value\"}]}");
34
36
 
35
37
  "parses a single element with a description and expected float output" >::
36
38
  ae (single [{description = "d1"; parameters = []; expected = Float 100.}])
37
- (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : 100.0}]}");
39
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : 100.0}]}");
38
40
 
39
41
  "parses a single element with a description and expected bool output" >::
40
42
  ae (single [{description = "d1"; parameters = []; expected = Bool true}])
41
- (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : true}]}");
43
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : true}]}");
42
44
 
43
45
  "parses a single element with a description and expected int list output" >::
44
46
  ae (single [{description = "d1"; parameters = []; expected = IntList [1;2;3]}])
45
- (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : [1, 2, 3]}]}");
47
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : [1, 2, 3]}]}");
46
48
 
47
49
  "parses a single element with a description and expected null output" >::
48
50
  ae (single [{description = "d1"; parameters = []; expected = Null}])
49
- (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : null}]}");
51
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : null}]}");
50
52
 
51
53
  "parses a single element with an int key value pair" >::
52
54
  ae (single [{description = "d1"; parameters = [("input", Int 1996)]; expected = Bool true}])
53
- (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"input\" : 1996, \"expected\" : true}]}");
55
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"input\" : 1996, \"expected\" : true}]}");
54
56
 
55
57
  "parses a single element with a string key value pair" >::
56
58
  ae (single [{description = "d1"; parameters = [("input", String "some-string")]; expected = Int 85}])
57
- (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"input\" : \"some-string\", \"expected\" : 85}]}");
59
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"input\" : \"some-string\", \"expected\" : 85}]}");
58
60
 
59
61
  "parses a single element with a string list key value pair" >::
60
62
  ae (single [{description = "d1"; parameters = [("input", StringList ["s1"; "s2"])]; expected = Int 85}])
61
- (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"input\" : [\"s1\", \"s2\"], \"expected\" : 85}]}");
63
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"input\" : [\"s1\", \"s2\"], \"expected\" : 85}]}");
64
+
65
+ "parses a single element with a int tuple list (modelled as an int list) key value pair" >::
66
+ ae (single [{description = "d1"; parameters = [("input", IntTupleList [(1,2);(3,4)])]; expected = Int 85}])
67
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"input\" : [[1,2],[3,4]], \"expected\" : 85}]}");
62
68
 
63
69
  "an element without a description is an Error" >::
64
70
  ae (Error NoDescription)
65
- (parse_json_text "{\"cases\" : [{\"input\" : 11, \"expected\" : 85}]}");
71
+ (call_parser "{\"cases\" : [{\"input\" : 11, \"expected\" : 85}]}");
66
72
 
67
73
  "an element with a description which is an int is an Error" >::
68
74
  ae (Error BadDescription)
69
- (parse_json_text "{\"cases\" : [{\"description\" : 1, \"input\" : 11, \"expected\" : 85}]}");
75
+ (call_parser "{\"cases\" : [{\"description\" : 1, \"input\" : 11, \"expected\" : 85}]}");
70
76
 
71
77
  "an element without description is an Error" >::
72
78
  ae (Error NoDescription)
73
- (parse_json_text "{\"cases\" : [{\"input\" : 11}]}");
79
+ (call_parser "{\"cases\" : [{\"input\" : 11}]}");
74
80
 
75
81
  "parses a map in the expected parameter" >::(fun _ctx ->
76
82
  assert_equal (single [{description = "d1"; parameters = []; expected = IntStringMap [("one", 1); ("two", 2)]}])
77
- (parse_json_text "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : {\"one\": 1, \"two\": 2}}]}");
83
+ (call_parser "{\"cases\" : [{\"description\" : \"d1\", \"expected\" : {\"one\": 1, \"two\": 2}}]}");
78
84
  );
79
85
 
80
86
  "parses leap.json" >::(fun ctxt ->
81
- match parse_json_text @@ In_channel.read_all "test/leap.json" with
87
+ match call_parser @@ In_channel.read_all "test/leap.json" with
82
88
  | Ok (Single p) -> assert_equal 7 (List.length p)
83
89
  | Ok (Suite p) -> assert_failure "was suite"
84
90
  | Error e -> assert_failure ("failed to parse leap.json: " ^ show_error e)
85
91
  );
86
92
 
87
93
  "parses hello_world.json which has a # element as documentation" >::(fun ctxt ->
88
- match parse_json_text @@ In_channel.read_all "test/hello_world.json" with
94
+ match call_parser @@ In_channel.read_all "test/hello_world.json" with
89
95
  | Ok (Single p) -> ()
90
96
  | Ok (Suite p) -> assert_failure "was suite"
91
97
  | Error e -> assert_failure ("failed to parse hello_world.json: " ^ show_error e)
92
98
  );
93
99
 
94
100
  "parses difference_of_squares.json" >::(fun ctxt ->
95
- match parse_json_text @@ In_channel.read_all "test/difference_of_squares.json" with
101
+ match call_parser @@ In_channel.read_all "test/difference_of_squares.json" with
96
102
  | Ok (Suite p) -> assert_equal ["square_of_sum"; "sum_of_squares"; "difference_of_squares"] (List.map ~f:(fun x -> x.name) p)
97
103
  | Ok (Single p) -> assert_failure "was single"
98
104
  | Error e -> assert_failure ("failed to parse difference_of_squares.json: " ^ show_error e)
99
105
  );
100
106
 
101
107
  "parses clock.json" >::(fun ctxt ->
102
- match parse_json_text @@ In_channel.read_all "test/clock.json" with
108
+ match call_parser @@ In_channel.read_all "test/clock.json" with
103
109
  | Ok (Suite p) -> assert_equal ["create"; "add"; "equal"] (List.map ~f:(fun x -> x.name) p)
104
110
  | Ok (Single p) -> assert_failure "was single"
105
111
  | Error e -> assert_failure ("failed to parse clock.json: " ^ show_error e)
106
112
  );
107
113
 
108
114
  "parses json with a methods key for dynamic languages" >::(fun ctxt ->
109
- match parse_json_text @@ In_channel.read_all "test/with-methods-key.json" with
115
+ match call_parser @@ In_channel.read_all "test/with-methods-key.json" with
110
116
  | Ok (Suite p) -> assert_failure "was suite"
111
117
  | Ok (Single p) -> ()
112
118
  | Error e -> assert_failure ("failed to parse with-methods-key.json: " ^ show_error e)
@@ -45,6 +45,11 @@
45
45
  "difficulty": 1,
46
46
  "slug": "anagram",
47
47
  "topics": []
48
+ },
49
+ {
50
+ "difficulty": 1,
51
+ "slug": "rna-transcription",
52
+ "topics": []
48
53
  }
49
54
  ]
50
55
  }
@@ -0,0 +1,12 @@
1
+ [Pony](http://www.ponylang.org) is an object-oriented, actor-model, capabilities-secure programming language focused on geting stuff done.
2
+
3
+ It's object-oriented because it has classes and objects, like Python, Java, C++, and many other languages. It's actor-model because it has actors (similar to Erlang or Akka). These behave like objects, but they can also execute code asynchronously. Actors make Pony awesome.
4
+ When we say Pony is capabilities-secure, we mean a few things:
5
+
6
+ - It's type safe. Really type safe. There's a mathematical proof and everything.
7
+ - It's memory safe. Ok, this comes with type safe, but it's still interesting. There are no dangling pointers, no buffer overruns, heck, the language doesn't even have the concept of null!
8
+ - It's exception safe. There are no runtime exceptions. All exceptions have defined semantics, and they are always handled.
9
+ - It's data-race free. Pony doesn't have locks or atomic operations or anything like that. Instead, the type system ensures at compile time that your concurrent program can never have data races. So you can write highly concurrent code and never get it wrong.
10
+ - It's deadlock free. This one is easy, because Pony has no locks at all! So they definitely don't deadlock, because they don't exist.
11
+
12
+ Newcomers should start with the [tutorial](https://tutorial.ponylang.org/).
@@ -1,14 +1,12 @@
1
- ## Installation from Package
1
+ ## Installing the Pony Compiler
2
2
 
3
- ### Mac OS X
4
-
5
- The Pony compiler (ponyc) is available for install using Homebrew!
3
+ ### Homebrew on Mac OS X
6
4
 
7
5
  ```bash
8
6
  brew update
9
7
  brew install ponyc
10
8
  ```
11
9
 
12
- ## Installation from Source
10
+ ### Other Platforms
13
11
 
14
- Instructions for installing Pony from source on Windows, Mac OS X, Linux, and FreeBSD can be found in the [installation instructions in the Pony tutorial.]( http://tutorial.ponylang.org/getting-started/installation.html)
12
+ Instructions for installing Pony can be found in the [ponyc installation](https://github.com/ponylang/ponyc/blob/master/README.md#installation)
@@ -0,0 +1,7 @@
1
+ ## Resources for Learning Pony:
2
+
3
+ - [The Pony Tutorial](https://tutorial.ponylang.org/)
4
+ - [Pony Patterns](https://patterns.ponylang.org/)
5
+ - [Standard Library Documentation](http://www.ponylang.org/ponyc/)
6
+ - [Mailing List](https://pony.groups.io/g/pony)
7
+ - [IRC Channel](https://webchat.freenode.net/?channels=%23ponylang)
@@ -0,0 +1,7 @@
1
+ ## Resources for Learning Pony
2
+
3
+ - [The Pony Tutorial](https://tutorial.ponylang.org/)
4
+ - [Pony Patterns](https://patterns.ponylang.org/)
5
+ - [Standard Library Documentation](http://www.ponylang.org/ponyc/)
6
+ - [Mailing List](https://pony.groups.io/g/pony)
7
+ - [IRC Channel](https://webchat.freenode.net/?channels=%23ponylang)
@@ -0,0 +1,11 @@
1
+ ## Running tests
2
+
3
+ To compile and run the tests, just run the following in your exercise directory:
4
+ ```bash
5
+ $ ponyc
6
+ $ ./exercise-name
7
+ ```
8
+
9
+ (Replace `exercise-name` with the name of the exercise directory)
10
+
11
+ The compiled binary runs the tests in its Main actor, so just run the binary and see if your tests passed. Pony checks all code at compile time, so you may find that your tests won't compile until you write the required code. You can comment out tests that won't compile by starting each line with a `//`. Then, when you're ready to work on that test, you can un-comment it.
@@ -36,5 +36,5 @@ class iso _HammingDistanceTest is UnitTest
36
36
  fun name(): String => "hamming/Hamming"
37
37
 
38
38
  fun apply(h: TestHelper) =>
39
- h.assert_error(lambda()? => Hamming("GAT", "GA") end)
40
- h.assert_error(lambda()? => Hamming("GA", "GAC") end)
39
+ h.assert_error({()? => Hamming("GAT", "GA")})
40
+ h.assert_error({()? => Hamming("GA", "GAC")})
@@ -0,0 +1,13 @@
1
+ primitive ToRNA
2
+ fun apply(dna: String): String ? =>
3
+ let rna = recover String(dna.size()) end
4
+ for b in dna.values() do
5
+ rna.push(match b
6
+ | 'A' => 'U'
7
+ | 'T' => 'A'
8
+ | 'C' => 'G'
9
+ | 'G' => 'C'
10
+ else error
11
+ end)
12
+ end
13
+ rna
@@ -0,0 +1,32 @@
1
+ use "ponytest"
2
+
3
+ actor Main is TestList
4
+ new create(env: Env) =>
5
+ PonyTest(env, this)
6
+
7
+ fun tag tests(test: PonyTest) =>
8
+ test(_TestRNATrancription)
9
+
10
+ class iso _TestRNATrancription is UnitTest
11
+ fun name(): String => "rna-transcription"
12
+
13
+ fun apply(h: TestHelper) ? =>
14
+ let tests = [
15
+ // rna complement of cytosine is guanine
16
+ ("C", "G"),
17
+ // rna complement of guanine is cytosine
18
+ ("G", "C"),
19
+ // rna complement of thymine is adenine
20
+ ("T", "A"),
21
+ // rna complement of adenine is uracil
22
+ ("A", "U"),
23
+ // rna complement
24
+ ("ACGTGGTCTTAA", "UGCACCAGAAUU")
25
+ ]
26
+
27
+ for (input, expected) in tests.values() do
28
+ h.assert_eq[String](ToRNA(input), expected)
29
+ end
30
+
31
+ h.assert_error({() ? => ToRNA("U")})
32
+ h.assert_error({() ? => ToRNA("ACGTXXXCTTAA")})
@@ -1,3 +1,19 @@
1
- anagram <- function() {
2
-
1
+ anagram <- function(subject,candidates) {
2
+ # subject is a string
3
+ # candidates is a character vector
4
+ # break subject into vector of characters
5
+ subject <- tolower(subject)
6
+ test_candidates <- tolower(candidates)
7
+ l <- strsplit(subject,"")[[1]]
8
+ # sub out each character from l in candidates
9
+ for (i in l) {
10
+ test_candidates <- sub(i,"",test_candidates)
11
+ }
12
+ result <- candidates[test_candidates=="" &
13
+ tolower(candidates) != subject &
14
+ nchar(candidates) == length(l)]
15
+ if (length(result)==0) {
16
+ return(c())
17
+ }
18
+ return(result)
3
19
  }
@@ -1,3 +1,18 @@
1
- bob <- function() {
1
+ bob <- function(input) {
2
+ # function bob takes a character input and responds
3
+ # with a couple different sentences
2
4
 
5
+ # strip white space
6
+ input <- gsub("[[:space:]]","",input)
7
+
8
+ if (input == "") {
9
+ return("Fine. Be that way!")
10
+ }
11
+ if (toupper(input) == input && tolower(input) != input) {
12
+ return("Whoa, chill out!")
13
+ }
14
+ if (endsWith(input,"?")) {
15
+ return("Sure.")
16
+ }
17
+ return("Whatever.")
3
18
  }
@@ -1,19 +1,35 @@
1
1
  # Convert a number to a valid number, if it isn't already.
2
- luhn <- function() {
3
-
2
+ luhn <- function(input) {
3
+ if (is_valid(input)) {
4
+ return(input)
5
+ }
6
+ diff <- (10 - checksum(10*input)) %% 10
7
+ return(10 * input + diff)
4
8
  }
5
9
 
6
10
  # Get the check digit
7
- check_digit <- function() {
8
-
11
+ check_digit <- function(input) {
12
+ as.numeric(substring(input,nchar(input)))
9
13
  }
10
14
 
11
15
  # Compute the checksum
12
- checksum <- function() {
13
-
16
+ checksum <- function(input) {
17
+ sum(addends(input))
14
18
  }
15
19
 
16
20
  # Determine whether the number is valid.
17
- is_valid <- function() {
21
+ is_valid <- function(input) {
22
+ checksum(input) %% 10 == 0
23
+ }
18
24
 
25
+ # addends returns the vector of numbers that follow the luhn algorithm
26
+ addends <- function(input) {
27
+ check <- check_digit(input)
28
+ v <- as.numeric(strsplit(as.character(input),"")[[1]])
29
+ # counting from right double value of every second digit
30
+ start_seq <- ifelse(length(v) %% 2 == 1, 0, 1)
31
+ v2 <- replace(v,seq(start_seq,length(v),2),v[seq(start_seq,length(v),2)]*2)
32
+ v2 <- ifelse(v2 > 9, v2 - 9, v2)
33
+ replace_vals <- v2[seq(start_seq,length(v),2)]
34
+ replace(v,seq(start_seq,length(v),2),replace_vals)
19
35
  }