trackler 2.0.6.41 → 2.0.6.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/common/CONTRIBUTING.md +15 -3
  3. data/common/README.md +7 -2
  4. data/common/exercises/binary/.deprecated +3 -0
  5. data/common/exercises/counter/.deprecated +2 -0
  6. data/common/exercises/hexadecimal/.deprecated +3 -0
  7. data/common/exercises/luhn/description.md +9 -31
  8. data/common/exercises/octal/.deprecated +3 -0
  9. data/common/exercises/point-mutations/.deprecated +2 -0
  10. data/common/exercises/trinary/.deprecated +3 -0
  11. data/lib/trackler/version.rb +1 -1
  12. data/tracks/c/exercises/rna-transcription/test/test_rna_transcription.c +2 -3
  13. data/tracks/ceylon/config.json +8 -0
  14. data/tracks/ceylon/docs/ABOUT.md +15 -0
  15. data/tracks/ceylon/docs/INSTALLATION.md +9 -0
  16. data/tracks/ceylon/docs/LEARNING.md +7 -0
  17. data/tracks/ceylon/docs/TESTS.md +11 -0
  18. data/tracks/ceylon/exercises/TRACK_HINTS.md +11 -0
  19. data/tracks/ceylon/exercises/hamming/example/Hamming.ceylon +8 -0
  20. data/tracks/ceylon/exercises/hamming/source/hamming/Hamming.ceylon +5 -0
  21. data/tracks/ceylon/exercises/hamming/source/hamming/HammingTest.ceylon +30 -0
  22. data/tracks/ceylon/exercises/hamming/source/hamming/module.ceylon +3 -0
  23. data/tracks/erlang/_test/check-exercises.escript +2 -2
  24. data/tracks/erlang/exercises/{circular-buffer/rebar.conf → accumulate/rebar.config} +1 -1
  25. data/tracks/erlang/exercises/allergies/{rebar.conf → rebar.config} +1 -1
  26. data/tracks/erlang/exercises/{accumulate/rebar.conf → anagram/rebar.config} +3 -1
  27. data/tracks/erlang/exercises/{bob/rebar.conf → atbash-cipher/rebar.config} +1 -1
  28. data/tracks/erlang/exercises/{binary/rebar.conf → bank-account/rebar.config} +1 -1
  29. data/tracks/erlang/exercises/beer-song/rebar.conf +1 -1
  30. data/tracks/erlang/exercises/binary/rebar.config +30 -0
  31. data/tracks/erlang/exercises/bob/rebar.config +30 -0
  32. data/tracks/erlang/exercises/circular-buffer/rebar.config +30 -0
  33. data/tracks/erlang/exercises/clock/rebar.config +30 -0
  34. data/tracks/erlang/exercises/difference-of-squares/rebar.config +30 -0
  35. data/tracks/erlang/exercises/etl/rebar.config +30 -0
  36. data/tracks/erlang/exercises/gigasecond/rebar.config +30 -0
  37. data/tracks/erlang/exercises/grade-school/rebar.config +30 -0
  38. data/tracks/erlang/exercises/grains/rebar.config +30 -0
  39. data/tracks/erlang/exercises/hamming/rebar.config +30 -0
  40. data/tracks/erlang/exercises/hello-world/rebar.config +30 -0
  41. data/tracks/erlang/exercises/largest-series-product/rebar.config +30 -0
  42. data/tracks/erlang/exercises/leap/rebar.config +30 -0
  43. data/tracks/erlang/exercises/luhn/rebar.config +30 -0
  44. data/tracks/erlang/exercises/meetup/rebar.config +30 -0
  45. data/tracks/erlang/exercises/nucleotide-count/rebar.config +30 -0
  46. data/tracks/erlang/exercises/parallel-letter-frequency/rebar.config +30 -0
  47. data/tracks/erlang/exercises/phone-number/rebar.config +30 -0
  48. data/tracks/erlang/exercises/rna-transcription/rebar.config +30 -0
  49. data/tracks/erlang/exercises/robot-simulator/HINTS.md +9 -0
  50. data/tracks/erlang/exercises/robot-simulator/rebar.config +30 -0
  51. data/tracks/erlang/exercises/roman-numerals/rebar.config +30 -0
  52. data/tracks/erlang/exercises/scrabble-score/rebar.config +30 -0
  53. data/tracks/erlang/exercises/series/rebar.config +30 -0
  54. data/tracks/erlang/exercises/space-age/rebar.config +30 -0
  55. data/tracks/erlang/exercises/strain/rebar.config +30 -0
  56. data/tracks/erlang/exercises/sum-of-multiples/rebar.config +30 -0
  57. data/tracks/erlang/exercises/triangle/rebar.config +30 -0
  58. data/tracks/erlang/exercises/trinary/rebar.config +30 -0
  59. data/tracks/erlang/exercises/word-count/rebar.config +30 -0
  60. data/tracks/erlang/exercises/zipper/rebar.config +30 -0
  61. data/tracks/go/README.md +2 -1
  62. data/tracks/go/exercises/diamond/diamond_test.go +8 -8
  63. data/tracks/go/exercises/difference-of-squares/difference_of_squares_test.go +8 -0
  64. data/tracks/go/exercises/difference-of-squares/example.go +2 -0
  65. data/tracks/go/exercises/diffie-hellman/diffie_hellman_test.go +8 -0
  66. data/tracks/go/exercises/diffie-hellman/example.go +2 -0
  67. data/tracks/go/exercises/error-handling/error_handling_test.go +8 -8
  68. data/tracks/go/exercises/etl/etl_test.go +8 -0
  69. data/tracks/go/exercises/etl/example.go +2 -0
  70. data/tracks/go/exercises/food-chain/food_chain_test.go +6 -6
  71. data/tracks/go/exercises/hello-world/hello_world.go +2 -2
  72. data/tracks/go/exercises/hexadecimal/hexadecimal_test.go +6 -6
  73. data/tracks/go/exercises/house/house_test.go +6 -6
  74. data/tracks/go/exercises/isogram/isogram_test.go +8 -8
  75. data/tracks/go/exercises/kindergarten-garden/kindergarten_garden_test.go +6 -6
  76. data/tracks/go/exercises/leap/leap_test.go +4 -1
  77. data/tracks/go/exercises/ledger/ledger_test.go +4 -1
  78. data/tracks/go/exercises/matrix/matrix_test.go +6 -6
  79. data/tracks/go/exercises/meetup/meetup_test.go +4 -1
  80. data/tracks/go/exercises/nth-prime/example.go +2 -0
  81. data/tracks/go/exercises/nth-prime/nth_prime_test.go +8 -0
  82. data/tracks/go/exercises/nucleotide-count/nucleotide_count_test.go +8 -8
  83. data/tracks/idris/.gitignore +2 -0
  84. data/tracks/idris/_src/Makefile.template +23 -0
  85. data/tracks/idris/config.json +9 -2
  86. data/tracks/idris/exercises/hello-world/HelloWorld.ipkg +5 -0
  87. data/tracks/idris/exercises/hello-world/Makefile +23 -0
  88. data/tracks/idris/exercises/hello-world/src/Test/HelloWorld.idr +25 -0
  89. data/tracks/idris/exercises/hello-world/src/example.idr +5 -0
  90. data/tracks/java/.travis.yml +5 -0
  91. data/tracks/java/bin/build-jq.sh +11 -0
  92. data/tracks/java/exercises/allergies/src/test/java/AllergiesTest.java +14 -13
  93. data/tracks/java/exercises/hamming/src/test/java/HammingTest.java +2 -2
  94. data/tracks/java/exercises/nth-prime/src/test/java/PrimeTest.java +8 -1
  95. data/tracks/java/exercises/nucleotide-count/src/test/java/NucleotideTest.java +12 -6
  96. data/tracks/java/exercises/pascals-triangle/src/test/java/PascalsTriangleTest.java +8 -2
  97. data/tracks/java/exercises/series/src/test/java/SeriesTest.java +10 -4
  98. data/tracks/java/exercises/simple-linked-list/src/test/java/SimpleLinkedListTest.java +7 -2
  99. data/tracks/java/exercises/triangle/src/test/java/TriangleTest.java +29 -20
  100. data/tracks/kotlin/config.json +5 -0
  101. data/tracks/kotlin/exercises/build.gradle +17 -0
  102. data/tracks/kotlin/exercises/perfect-numbers/build.gradle +28 -0
  103. data/tracks/kotlin/exercises/perfect-numbers/src/example/kotlin/NaturalNumber.kt +17 -0
  104. data/tracks/kotlin/exercises/perfect-numbers/src/main/kotlin/NaturalNumber.kt +8 -0
  105. data/tracks/kotlin/exercises/perfect-numbers/src/test/kotlin/PerfectNumbersTest.kt +67 -0
  106. data/tracks/kotlin/exercises/settings.gradle +1 -0
  107. data/tracks/lua/exercises/hamming/example.lua +1 -0
  108. data/tracks/lua/exercises/hamming/hamming_spec.lua +19 -11
  109. data/tracks/ocaml/config.json +5 -0
  110. data/tracks/ocaml/exercises/beer-song/beer_song.mli +1 -1
  111. data/tracks/ocaml/exercises/beer-song/example.ml +3 -3
  112. data/tracks/ocaml/exercises/beer-song/test.ml +45 -22
  113. data/tracks/ocaml/exercises/run-length-encoding/.merlin +5 -0
  114. data/tracks/ocaml/exercises/run-length-encoding/Makefile +11 -0
  115. data/tracks/ocaml/exercises/run-length-encoding/example.ml +37 -0
  116. data/tracks/ocaml/exercises/run-length-encoding/run_length_encoding.mli +3 -0
  117. data/tracks/ocaml/exercises/run-length-encoding/test.ml +38 -0
  118. data/tracks/ocaml/tools/test-generator/src/template.ml +0 -2
  119. data/tracks/ocaml/tools/test-generator/templates/beer-song/template.ml +19 -0
  120. data/tracks/ocaml/tools/test-generator/templates/run-length-encoding/template.ml +19 -0
  121. data/tracks/php/config.json +17 -0
  122. data/tracks/php/exercises/queen-attack/example.php +86 -0
  123. data/tracks/php/exercises/queen-attack/queen-attack_test.php +125 -0
  124. data/tracks/php/exercises/scrabble-score/example.php +27 -0
  125. data/tracks/php/exercises/scrabble-score/scrabble-score_test.php +120 -0
  126. data/tracks/r/exercises/luhn/example.R +20 -32
  127. data/tracks/r/exercises/luhn/luhn.R +1 -22
  128. data/tracks/r/exercises/luhn/test_luhn.R +43 -55
  129. metadata +67 -37
  130. data/tracks/erlang/exercises/anagram/rebar.conf +0 -32
  131. data/tracks/erlang/exercises/atbash-cipher/rebar.conf +0 -30
  132. data/tracks/erlang/exercises/bank-account/rebar.conf +0 -30
  133. data/tracks/erlang/exercises/clock/rebar.conf +0 -30
  134. data/tracks/erlang/exercises/difference-of-squares/rebar.conf +0 -30
  135. data/tracks/erlang/exercises/etl/rebar.conf +0 -30
  136. data/tracks/erlang/exercises/gigasecond/rebar.conf +0 -30
  137. data/tracks/erlang/exercises/grade-school/rebar.conf +0 -30
  138. data/tracks/erlang/exercises/grains/rebar.conf +0 -30
  139. data/tracks/erlang/exercises/hamming/rebar.conf +0 -30
  140. data/tracks/erlang/exercises/hello-world/rebar.conf +0 -30
  141. data/tracks/erlang/exercises/largest-series-product/rebar.conf +0 -30
  142. data/tracks/erlang/exercises/leap/rebar.conf +0 -30
  143. data/tracks/erlang/exercises/luhn/rebar.conf +0 -30
  144. data/tracks/erlang/exercises/meetup/rebar.conf +0 -30
  145. data/tracks/erlang/exercises/nucleotide-count/rebar.conf +0 -30
  146. data/tracks/erlang/exercises/parallel-letter-frequency/rebar.conf +0 -30
  147. data/tracks/erlang/exercises/phone-number/rebar.conf +0 -30
  148. data/tracks/erlang/exercises/rna-transcription/rebar.conf +0 -30
  149. data/tracks/erlang/exercises/robot-simulator/rebar.conf +0 -30
  150. data/tracks/erlang/exercises/roman-numerals/rebar.conf +0 -30
  151. data/tracks/erlang/exercises/scrabble-score/rebar.conf +0 -30
  152. data/tracks/erlang/exercises/series/rebar.conf +0 -30
  153. data/tracks/erlang/exercises/space-age/rebar.conf +0 -30
  154. data/tracks/erlang/exercises/strain/rebar.conf +0 -30
  155. data/tracks/erlang/exercises/sum-of-multiples/rebar.conf +0 -30
  156. data/tracks/erlang/exercises/triangle/rebar.conf +0 -30
  157. data/tracks/erlang/exercises/trinary/rebar.conf +0 -30
  158. data/tracks/erlang/exercises/word-count/rebar.conf +0 -30
  159. data/tracks/erlang/exercises/zipper/rebar.conf +0 -30
@@ -2,46 +2,54 @@ local compute = require('hamming').compute
2
2
 
3
3
  describe('hamming', function ()
4
4
  it('no difference between identical strands', function ()
5
- assert.are.equals(0, compute('A', 'A'))
5
+ assert.are.equal(0, compute('A', 'A'))
6
6
  end)
7
7
 
8
8
  it('long identical strands', function ()
9
- assert.are.equals(0, compute('GGACTGA', 'GGACTGA'))
9
+ assert.are.equal(0, compute('GGACTGA', 'GGACTGA'))
10
10
  end)
11
11
 
12
12
  it('complete hamming distance of for single nucleotide strand', function ()
13
- assert.are.equals(1, compute('A', 'G'))
13
+ assert.are.equal(1, compute('A', 'G'))
14
14
  end)
15
15
 
16
16
  it('complete hamming distance of for small strand', function ()
17
- assert.are.equals(2, compute('AG', 'CT'))
17
+ assert.are.equal(2, compute('AG', 'CT'))
18
18
  end)
19
19
 
20
20
  it('small hamming distance', function ()
21
- assert.are.equals(1, compute('AT', 'CT'))
21
+ assert.are.equal(1, compute('AT', 'CT'))
22
22
  end)
23
23
 
24
24
  it('small hamming distance in longer strand', function ()
25
- assert.are.equals(1, compute('GGACG', 'GGTCG'))
25
+ assert.are.equal(1, compute('GGACG', 'GGTCG'))
26
26
  end)
27
27
 
28
28
  it('non unique character in first strand', function ()
29
- assert.are.equals(1, compute('AGA', 'AGG'))
29
+ assert.are.equal(1, compute('AGA', 'AGG'))
30
30
  end)
31
31
 
32
32
  it('non unique character in second strand', function ()
33
- assert.are.equals(1, compute('AGG', 'AGA'))
33
+ assert.are.equal(1, compute('AGG', 'AGA'))
34
34
  end)
35
35
 
36
36
  it('large hamming distance', function ()
37
- assert.are.equals(4, compute('GATACA', 'GCATAA'))
37
+ assert.are.equal(4, compute('GATACA', 'GCATAA'))
38
38
  end)
39
39
 
40
40
  it('hamming distance in very long strand', function ()
41
- assert.are.equals(9, compute('GGACGGATTCTG', 'AGGACGGATTCT'))
41
+ assert.are.equal(9, compute('GGACGGATTCTG', 'AGGACGGATTCT'))
42
42
  end)
43
43
 
44
44
  it('empty strands', function ()
45
- assert.are.equals(0, compute('', ''))
45
+ assert.are.equal(0, compute('', ''))
46
+ end)
47
+
48
+ it('disallow first strand longer', function ()
49
+ assert.are.equal(-1, compute('AATG', 'AAA'))
50
+ end)
51
+
52
+ it('disallow second strand longer', function ()
53
+ assert.are.equal(-1, compute('ATA', 'AGTG'))
46
54
  end)
47
55
  end)
@@ -111,6 +111,11 @@
111
111
  "difficulty": 4,
112
112
  "topics": []
113
113
  },
114
+ {
115
+ "slug": "run-length-encoding",
116
+ "difficulty": 5,
117
+ "topics": ["Algorithms", "Transforming"]
118
+ },
114
119
  {
115
120
  "slug": "roman-numerals",
116
121
  "difficulty": 5,
@@ -4,4 +4,4 @@
4
4
  val verse : int -> string
5
5
 
6
6
  (** Return multiple verses, concatenated, from [from] until [until] (inclusive). *)
7
- val sing : from:int -> until:int -> string
7
+ val lyrics : from:int -> until:int -> string
@@ -18,7 +18,7 @@ let verse = function
18
18
  "Go to the store and buy some more, 99 bottles of beer on the wall.\n"
19
19
  | n -> line1 n ^ line2 (n-1)
20
20
 
21
- let sing ~from:from ~until:until =
21
+ let lyrics ~from:from ~until:until =
22
22
  List.map (List.range ~stride:(-1) ~stop:`inclusive from until)
23
- ~f:(fun n -> verse n ^ "\n")
24
- |> String.concat ~sep:""
23
+ ~f:(fun n -> verse n)
24
+ |> String.concat ~sep:"\n"
@@ -2,28 +2,51 @@ open Core.Std
2
2
  open OUnit2
3
3
  open Beer_song
4
4
 
5
- let ae exp got = assert_equal ~printer:String.to_string exp got
5
+ let zip s1 s2 =
6
+ let rec go s1 s2 acc = match (s1,s2) with
7
+ | ([], _) -> acc
8
+ | (_, []) -> acc
9
+ | (x::xs, y::ys) -> go xs ys ((x,y)::acc) in
10
+ List.rev @@ go s1 s2 []
6
11
 
7
- let tests =
8
- ["a verse">:: (fun _ ->
9
- let exp = "8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n" in
10
- ae exp (verse 8));
11
- "verse 1">:: (fun _ ->
12
- let exp = "1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n" in
13
- ae exp (verse 1));
14
- "verse 2">:: (fun _ ->
15
- let exp = "2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n" in
16
- ae exp (verse 2));
17
- "verse 0">:: (fun _ ->
18
- let exp = "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n" in
19
- ae exp (verse 0));
20
- "singing several verses">:: (fun _ ->
21
- let exp = "8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n\n7 bottles of beer on the wall, 7 bottles of beer.\nTake one down and pass it around, 6 bottles of beer on the wall.\n\n6 bottles of beer on the wall, 6 bottles of beer.\nTake one down and pass it around, 5 bottles of beer on the wall.\n\n" in
22
- ae exp (sing ~from:8 ~until:6));
23
- "sing all the rest of the verses">:: (fun _ ->
24
- let exp = "3 bottles of beer on the wall, 3 bottles of beer.\nTake one down and pass it around, 2 bottles of beer on the wall.\n\n2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n\n1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n\n" in
25
- ae exp (sing ~from:3 ~until:0))
26
- ]
12
+ let find_diffs s1 s2 =
13
+ let s1 = String.to_list s1 in
14
+ let s2 = String.to_list s2 in
15
+ let both = zip s1 s2 in
16
+ List.find_mapi both ~f:(fun i (c1, c2) -> if c1 = c2 then None else Some (sprintf "Diff at index %d: %c <> %c" i c1 c2))
17
+
18
+ let diff_message s1 s2 = match find_diffs s1 s2 with
19
+ | None -> if String.length s1 = String.length s2 then "" else "Lengths of expected and actual differ but have a common prefix."
20
+ | Some m -> m
21
+
22
+ let ae exp got _test_ctxt =
23
+ if exp = got
24
+ then ()
25
+ else failwith @@ "Expected differs from actual: " ^ (diff_message exp got)
26
+
27
+ let verse_tests = [
28
+ "first verse" >::
29
+ ae "99 bottles of beer on the wall, 99 bottles of beer.\nTake one down and pass it around, 98 bottles of beer on the wall.\n" (verse 99);
30
+ "middle verse" >::
31
+ ae "44 bottles of beer on the wall, 44 bottles of beer.\nTake one down and pass it around, 43 bottles of beer on the wall.\n" (verse 44);
32
+ "third to last verse" >::
33
+ ae "2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n" (verse 2);
34
+ "penultimate verse" >::
35
+ ae "1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n" (verse 1);
36
+ "last verse" >::
37
+ ae "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n" (verse 0);
38
+ ]
39
+
40
+ let lyrics_tests = [
41
+ "last 4 verses" >::
42
+ ae "3 bottles of beer on the wall, 3 bottles of beer.\nTake one down and pass it around, 2 bottles of beer on the wall.\n\n2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n\n1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n" (lyrics ~from:3 ~until:0);
43
+ "all verses" >::
44
+ ae "99 bottles of beer on the wall, 99 bottles of beer.\nTake one down and pass it around, 98 bottles of beer on the wall.\n\n98 bottles of beer on the wall, 98 bottles of beer.\nTake one down and pass it around, 97 bottles of beer on the wall.\n\n97 bottles of beer on the wall, 97 bottles of beer.\nTake one down and pass it around, 96 bottles of beer on the wall.\n\n96 bottles of beer on the wall, 96 bottles of beer.\nTake one down and pass it around, 95 bottles of beer on the wall.\n\n95 bottles of beer on the wall, 95 bottles of beer.\nTake one down and pass it around, 94 bottles of beer on the wall.\n\n94 bottles of beer on the wall, 94 bottles of beer.\nTake one down and pass it around, 93 bottles of beer on the wall.\n\n93 bottles of beer on the wall, 93 bottles of beer.\nTake one down and pass it around, 92 bottles of beer on the wall.\n\n92 bottles of beer on the wall, 92 bottles of beer.\nTake one down and pass it around, 91 bottles of beer on the wall.\n\n91 bottles of beer on the wall, 91 bottles of beer.\nTake one down and pass it around, 90 bottles of beer on the wall.\n\n90 bottles of beer on the wall, 90 bottles of beer.\nTake one down and pass it around, 89 bottles of beer on the wall.\n\n89 bottles of beer on the wall, 89 bottles of beer.\nTake one down and pass it around, 88 bottles of beer on the wall.\n\n88 bottles of beer on the wall, 88 bottles of beer.\nTake one down and pass it around, 87 bottles of beer on the wall.\n\n87 bottles of beer on the wall, 87 bottles of beer.\nTake one down and pass it around, 86 bottles of beer on the wall.\n\n86 bottles of beer on the wall, 86 bottles of beer.\nTake one down and pass it around, 85 bottles of beer on the wall.\n\n85 bottles of beer on the wall, 85 bottles of beer.\nTake one down and pass it around, 84 bottles of beer on the wall.\n\n84 bottles of beer on the wall, 84 bottles of beer.\nTake one down and pass it around, 83 bottles of beer on the wall.\n\n83 bottles of beer on the wall, 83 bottles of beer.\nTake one down and pass it around, 82 bottles of beer on the wall.\n\n82 bottles of beer on the wall, 82 bottles of beer.\nTake one down and pass it around, 81 bottles of beer on the wall.\n\n81 bottles of beer on the wall, 81 bottles of beer.\nTake one down and pass it around, 80 bottles of beer on the wall.\n\n80 bottles of beer on the wall, 80 bottles of beer.\nTake one down and pass it around, 79 bottles of beer on the wall.\n\n79 bottles of beer on the wall, 79 bottles of beer.\nTake one down and pass it around, 78 bottles of beer on the wall.\n\n78 bottles of beer on the wall, 78 bottles of beer.\nTake one down and pass it around, 77 bottles of beer on the wall.\n\n77 bottles of beer on the wall, 77 bottles of beer.\nTake one down and pass it around, 76 bottles of beer on the wall.\n\n76 bottles of beer on the wall, 76 bottles of beer.\nTake one down and pass it around, 75 bottles of beer on the wall.\n\n75 bottles of beer on the wall, 75 bottles of beer.\nTake one down and pass it around, 74 bottles of beer on the wall.\n\n74 bottles of beer on the wall, 74 bottles of beer.\nTake one down and pass it around, 73 bottles of beer on the wall.\n\n73 bottles of beer on the wall, 73 bottles of beer.\nTake one down and pass it around, 72 bottles of beer on the wall.\n\n72 bottles of beer on the wall, 72 bottles of beer.\nTake one down and pass it around, 71 bottles of beer on the wall.\n\n71 bottles of beer on the wall, 71 bottles of beer.\nTake one down and pass it around, 70 bottles of beer on the wall.\n\n70 bottles of beer on the wall, 70 bottles of beer.\nTake one down and pass it around, 69 bottles of beer on the wall.\n\n69 bottles of beer on the wall, 69 bottles of beer.\nTake one down and pass it around, 68 bottles of beer on the wall.\n\n68 bottles of beer on the wall, 68 bottles of beer.\nTake one down and pass it around, 67 bottles of beer on the wall.\n\n67 bottles of beer on the wall, 67 bottles of beer.\nTake one down and pass it around, 66 bottles of beer on the wall.\n\n66 bottles of beer on the wall, 66 bottles of beer.\nTake one down and pass it around, 65 bottles of beer on the wall.\n\n65 bottles of beer on the wall, 65 bottles of beer.\nTake one down and pass it around, 64 bottles of beer on the wall.\n\n64 bottles of beer on the wall, 64 bottles of beer.\nTake one down and pass it around, 63 bottles of beer on the wall.\n\n63 bottles of beer on the wall, 63 bottles of beer.\nTake one down and pass it around, 62 bottles of beer on the wall.\n\n62 bottles of beer on the wall, 62 bottles of beer.\nTake one down and pass it around, 61 bottles of beer on the wall.\n\n61 bottles of beer on the wall, 61 bottles of beer.\nTake one down and pass it around, 60 bottles of beer on the wall.\n\n60 bottles of beer on the wall, 60 bottles of beer.\nTake one down and pass it around, 59 bottles of beer on the wall.\n\n59 bottles of beer on the wall, 59 bottles of beer.\nTake one down and pass it around, 58 bottles of beer on the wall.\n\n58 bottles of beer on the wall, 58 bottles of beer.\nTake one down and pass it around, 57 bottles of beer on the wall.\n\n57 bottles of beer on the wall, 57 bottles of beer.\nTake one down and pass it around, 56 bottles of beer on the wall.\n\n56 bottles of beer on the wall, 56 bottles of beer.\nTake one down and pass it around, 55 bottles of beer on the wall.\n\n55 bottles of beer on the wall, 55 bottles of beer.\nTake one down and pass it around, 54 bottles of beer on the wall.\n\n54 bottles of beer on the wall, 54 bottles of beer.\nTake one down and pass it around, 53 bottles of beer on the wall.\n\n53 bottles of beer on the wall, 53 bottles of beer.\nTake one down and pass it around, 52 bottles of beer on the wall.\n\n52 bottles of beer on the wall, 52 bottles of beer.\nTake one down and pass it around, 51 bottles of beer on the wall.\n\n51 bottles of beer on the wall, 51 bottles of beer.\nTake one down and pass it around, 50 bottles of beer on the wall.\n\n50 bottles of beer on the wall, 50 bottles of beer.\nTake one down and pass it around, 49 bottles of beer on the wall.\n\n49 bottles of beer on the wall, 49 bottles of beer.\nTake one down and pass it around, 48 bottles of beer on the wall.\n\n48 bottles of beer on the wall, 48 bottles of beer.\nTake one down and pass it around, 47 bottles of beer on the wall.\n\n47 bottles of beer on the wall, 47 bottles of beer.\nTake one down and pass it around, 46 bottles of beer on the wall.\n\n46 bottles of beer on the wall, 46 bottles of beer.\nTake one down and pass it around, 45 bottles of beer on the wall.\n\n45 bottles of beer on the wall, 45 bottles of beer.\nTake one down and pass it around, 44 bottles of beer on the wall.\n\n44 bottles of beer on the wall, 44 bottles of beer.\nTake one down and pass it around, 43 bottles of beer on the wall.\n\n43 bottles of beer on the wall, 43 bottles of beer.\nTake one down and pass it around, 42 bottles of beer on the wall.\n\n42 bottles of beer on the wall, 42 bottles of beer.\nTake one down and pass it around, 41 bottles of beer on the wall.\n\n41 bottles of beer on the wall, 41 bottles of beer.\nTake one down and pass it around, 40 bottles of beer on the wall.\n\n40 bottles of beer on the wall, 40 bottles of beer.\nTake one down and pass it around, 39 bottles of beer on the wall.\n\n39 bottles of beer on the wall, 39 bottles of beer.\nTake one down and pass it around, 38 bottles of beer on the wall.\n\n38 bottles of beer on the wall, 38 bottles of beer.\nTake one down and pass it around, 37 bottles of beer on the wall.\n\n37 bottles of beer on the wall, 37 bottles of beer.\nTake one down and pass it around, 36 bottles of beer on the wall.\n\n36 bottles of beer on the wall, 36 bottles of beer.\nTake one down and pass it around, 35 bottles of beer on the wall.\n\n35 bottles of beer on the wall, 35 bottles of beer.\nTake one down and pass it around, 34 bottles of beer on the wall.\n\n34 bottles of beer on the wall, 34 bottles of beer.\nTake one down and pass it around, 33 bottles of beer on the wall.\n\n33 bottles of beer on the wall, 33 bottles of beer.\nTake one down and pass it around, 32 bottles of beer on the wall.\n\n32 bottles of beer on the wall, 32 bottles of beer.\nTake one down and pass it around, 31 bottles of beer on the wall.\n\n31 bottles of beer on the wall, 31 bottles of beer.\nTake one down and pass it around, 30 bottles of beer on the wall.\n\n30 bottles of beer on the wall, 30 bottles of beer.\nTake one down and pass it around, 29 bottles of beer on the wall.\n\n29 bottles of beer on the wall, 29 bottles of beer.\nTake one down and pass it around, 28 bottles of beer on the wall.\n\n28 bottles of beer on the wall, 28 bottles of beer.\nTake one down and pass it around, 27 bottles of beer on the wall.\n\n27 bottles of beer on the wall, 27 bottles of beer.\nTake one down and pass it around, 26 bottles of beer on the wall.\n\n26 bottles of beer on the wall, 26 bottles of beer.\nTake one down and pass it around, 25 bottles of beer on the wall.\n\n25 bottles of beer on the wall, 25 bottles of beer.\nTake one down and pass it around, 24 bottles of beer on the wall.\n\n24 bottles of beer on the wall, 24 bottles of beer.\nTake one down and pass it around, 23 bottles of beer on the wall.\n\n23 bottles of beer on the wall, 23 bottles of beer.\nTake one down and pass it around, 22 bottles of beer on the wall.\n\n22 bottles of beer on the wall, 22 bottles of beer.\nTake one down and pass it around, 21 bottles of beer on the wall.\n\n21 bottles of beer on the wall, 21 bottles of beer.\nTake one down and pass it around, 20 bottles of beer on the wall.\n\n20 bottles of beer on the wall, 20 bottles of beer.\nTake one down and pass it around, 19 bottles of beer on the wall.\n\n19 bottles of beer on the wall, 19 bottles of beer.\nTake one down and pass it around, 18 bottles of beer on the wall.\n\n18 bottles of beer on the wall, 18 bottles of beer.\nTake one down and pass it around, 17 bottles of beer on the wall.\n\n17 bottles of beer on the wall, 17 bottles of beer.\nTake one down and pass it around, 16 bottles of beer on the wall.\n\n16 bottles of beer on the wall, 16 bottles of beer.\nTake one down and pass it around, 15 bottles of beer on the wall.\n\n15 bottles of beer on the wall, 15 bottles of beer.\nTake one down and pass it around, 14 bottles of beer on the wall.\n\n14 bottles of beer on the wall, 14 bottles of beer.\nTake one down and pass it around, 13 bottles of beer on the wall.\n\n13 bottles of beer on the wall, 13 bottles of beer.\nTake one down and pass it around, 12 bottles of beer on the wall.\n\n12 bottles of beer on the wall, 12 bottles of beer.\nTake one down and pass it around, 11 bottles of beer on the wall.\n\n11 bottles of beer on the wall, 11 bottles of beer.\nTake one down and pass it around, 10 bottles of beer on the wall.\n\n10 bottles of beer on the wall, 10 bottles of beer.\nTake one down and pass it around, 9 bottles of beer on the wall.\n\n9 bottles of beer on the wall, 9 bottles of beer.\nTake one down and pass it around, 8 bottles of beer on the wall.\n\n8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n\n7 bottles of beer on the wall, 7 bottles of beer.\nTake one down and pass it around, 6 bottles of beer on the wall.\n\n6 bottles of beer on the wall, 6 bottles of beer.\nTake one down and pass it around, 5 bottles of beer on the wall.\n\n5 bottles of beer on the wall, 5 bottles of beer.\nTake one down and pass it around, 4 bottles of beer on the wall.\n\n4 bottles of beer on the wall, 4 bottles of beer.\nTake one down and pass it around, 3 bottles of beer on the wall.\n\n3 bottles of beer on the wall, 3 bottles of beer.\nTake one down and pass it around, 2 bottles of beer on the wall.\n\n2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n\n1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n\nNo more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n"
45
+ (lyrics ~from:99 ~until:0);
46
+ ]
27
47
 
28
48
  let () =
29
- run_test_tt_main ("beer-song tests" >::: tests)
49
+ run_test_tt_main (
50
+ "beer song tests" >:::
51
+ List.concat [verse_tests; lyrics_tests]
52
+ )
@@ -0,0 +1,5 @@
1
+ PKG findlib
2
+ PKG core
3
+ PKG ounit
4
+ S *
5
+ B *
@@ -0,0 +1,11 @@
1
+ test: test.native
2
+ @./test.native
3
+
4
+ test.native: *.ml *.mli
5
+ @corebuild -r -quiet -pkg oUnit test.native
6
+
7
+ clean:
8
+ rm -rf _build
9
+ rm -f test.native
10
+
11
+ .PHONY: clean
@@ -0,0 +1,37 @@
1
+ open Core.Std
2
+
3
+ let (>|>) f g x = g (f x)
4
+
5
+ let repeat n ch =
6
+ Array.init n ~f:(fun _ -> ch)
7
+ |> Array.to_list
8
+ |> String.of_char_list
9
+
10
+ let collapse = function
11
+ | [] -> failwith "empty string not expected here"
12
+ | [x] -> Char.to_string x
13
+ | (x::_) as g -> sprintf "%d%c" (List.length g) x
14
+
15
+ let to_int = String.of_char_list >|> Int.of_string
16
+
17
+ let decode_to_tuple (s: 'a list): ((int * 'a) * 'a list) =
18
+ match List.split_while ~f:Char.is_digit s with
19
+ | ([], (x::xs)) -> ((1, x), xs)
20
+ | (ds, (x::xs)) -> let count = to_int ds in ((count, x), xs)
21
+ | _ -> failwith "case not expected"
22
+
23
+ let encode =
24
+ String.to_list
25
+ >|> List.group ~break:((<>))
26
+ >|> List.map ~f:collapse
27
+ >|> String.concat ~sep:""
28
+
29
+ let decode =
30
+ let rec go acc input =
31
+ if List.is_empty input then acc
32
+ else let (t, rest) = decode_to_tuple input in go (t :: acc) rest in
33
+ String.to_list
34
+ >|> go []
35
+ >|> List.rev
36
+ >|> List.map ~f:(fun (cnt, c) -> repeat cnt c)
37
+ >|> String.concat ~sep:""
@@ -0,0 +1,3 @@
1
+ val encode : string -> string
2
+
3
+ val decode : string -> string
@@ -0,0 +1,38 @@
1
+ open Core.Std
2
+ open OUnit2
3
+ open Run_length_encoding
4
+
5
+ let ae exp got _test_ctxt = assert_equal exp got ~printer:Fn.id
6
+
7
+ let encode_tests = [
8
+ "empty string" >::
9
+ ae "" (encode "");
10
+ "single characters only are encoded without count" >::
11
+ ae "XYZ" (encode "XYZ");
12
+ "string with no single characters" >::
13
+ ae "2A3B4C" (encode "AABBBCCCC");
14
+ "single characters mixed with repeated characters" >::
15
+ ae "12WB12W3B24WB" (encode "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB");
16
+ ]
17
+
18
+ let decode_tests = [
19
+ "empty string" >::
20
+ ae "" (decode "");
21
+ "single characters only" >::
22
+ ae "XYZ" (decode "XYZ");
23
+ "string with no single characters" >::
24
+ ae "AABBBCCCC" (decode "2A3B4C");
25
+ "single characters with repeated characters" >::
26
+ ae "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" (decode "12WB12W3B24WB");
27
+ ]
28
+
29
+ let consistency_tests = [
30
+ "encode followed by decode gives original string" >::
31
+ ae "zzz ZZ zZ" (decode (encode "zzz ZZ zZ"));
32
+ ]
33
+
34
+ let () =
35
+ run_test_tt_main (
36
+ "run length encoding tests" >:::
37
+ List.concat [encode_tests; decode_tests; consistency_tests]
38
+ )
@@ -40,7 +40,6 @@ let fill_tests (template: t) (substs: subst list): string =
40
40
  let join = String.concat_array ~sep:"\n" in
41
41
  String.concat [join before; join subst; join after] ~sep:"\n"
42
42
 
43
- (* HACKS HERE *)
44
43
  let fill_single_suite (template: t) (suite_substs: string * subst list): string =
45
44
  let (suite_name, substs) = suite_substs in
46
45
  let suite_name_line = Option.value_exn template.suite_name_line in
@@ -53,7 +52,6 @@ let fill_single_suite (template: t) (suite_substs: string * subst list): string
53
52
  let join = String.concat_array ~sep:"\n" in
54
53
  String.concat [join before; join subst; join after] ~sep:"\n"
55
54
 
56
- (* HACKS HERE *)
57
55
  let fill_suite (template: t) (suite_substs: (string * subst list) list): string =
58
56
  let fills = List.map suite_substs ~f:(fun x -> (fill_single_suite template x) ^ "\n") in
59
57
  let suite_name_line = Option.value_exn template.suite_name_line in
@@ -0,0 +1,19 @@
1
+ open Core.Std
2
+ open OUnit2
3
+ open Beer_song
4
+
5
+ let ae exp got _test_ctxt = assert_equal exp got ~printer:Fn.id
6
+
7
+ let (* SUITE *)$(suite_name)_tests = [
8
+ (* TEST
9
+ "$description" >::
10
+ ae $expected ($suite-name $number);
11
+ END TEST *)
12
+ ]
13
+ (* END SUITE *)
14
+
15
+ let () =
16
+ run_test_tt_main (
17
+ "beer song tests" >:::
18
+ List.concat [(* suite-all-names *)]
19
+ )
@@ -0,0 +1,19 @@
1
+ open Core.Std
2
+ open OUnit2
3
+ open Run_length_encoding
4
+
5
+ let ae exp got _test_ctxt = assert_equal exp got ~printer:Fn.id
6
+
7
+ let (* SUITE *)$(suite_name)_tests = [
8
+ (* TEST
9
+ "$description" >::
10
+ ae $expected ($suite-name $input);
11
+ END TEST *)
12
+ ]
13
+ (* END SUITE *)
14
+
15
+ let () =
16
+ run_test_tt_main (
17
+ "run length encoding tests" >:::
18
+ List.concat [(* suite-all-names *)]
19
+ )
@@ -338,6 +338,23 @@
338
338
  "topics": [
339
339
  "Algorithms"
340
340
  ]
341
+ },
342
+ {
343
+ "slug": "queen-attack",
344
+ "difficulty": 2,
345
+ "topics": [
346
+ "Integers",
347
+ "Mathematics"
348
+ ]
349
+ },
350
+ {
351
+ "slug": "scrabble-score",
352
+ "difficulty": 2,
353
+ "topics": [
354
+ "Strings",
355
+ "Control-flow (loops)",
356
+ "Integers"
357
+ ]
341
358
  }
342
359
  ]
343
360
  }
@@ -0,0 +1,86 @@
1
+ <?php
2
+
3
+ /**
4
+ * Check if the queen is placed on a valid square.
5
+ *
6
+ * @param int $xCoordinate
7
+ * @param int $yCoordinate
8
+ *
9
+ * @return bool
10
+ *
11
+ * @throws InvalidArgumentException
12
+ */
13
+ function placeQueen($xCoordinate, $yCoordinate)
14
+ {
15
+ if ($xCoordinate < 0 || $yCoordinate < 0) {
16
+ throw new InvalidArgumentException('The rank and file numbers must be positive.');
17
+ }
18
+
19
+ if ($xCoordinate > 7 || $yCoordinate > 7) {
20
+ throw new InvalidArgumentException('The position must be on a standard size chess board.');
21
+ }
22
+
23
+ return true;
24
+ }
25
+
26
+ /**
27
+ * Check if 2 queens can attack each other from their current positions.
28
+ *
29
+ * @param array $whiteQueen The queen's x,y coordinates on the board.
30
+ * @param array $blackQueen The queen's x,y coordinates on the board.
31
+ *
32
+ * @return bool
33
+ */
34
+ function canAttack($whiteQueen, $blackQueen)
35
+ {
36
+ placeQueen($whiteQueen[0], $whiteQueen[1]);
37
+ placeQueen($blackQueen[0], $blackQueen[1]);
38
+
39
+ if (onRankOrFile($whiteQueen[0], $blackQueen[0]) ||
40
+ onRankOrFile($whiteQueen[1], $blackQueen[1]) ||
41
+ onDiagonal($whiteQueen[0], $whiteQueen[1], $blackQueen[0], $blackQueen[1])
42
+ ) {
43
+ return true;
44
+ }
45
+
46
+ return false;
47
+ }
48
+
49
+ /**
50
+ * Check if to coordinates or on the same rank or file.
51
+ *
52
+ * @param int $whiteCoordinate
53
+ * @param int $blackCoordinate
54
+ *
55
+ * @return bool
56
+ */
57
+ function onRankOrFile($whiteCoordinate, $blackCoordinate)
58
+ {
59
+ if ($whiteCoordinate === $blackCoordinate) {
60
+ return true;
61
+ }
62
+
63
+ return false;
64
+ }
65
+
66
+ /**
67
+ * Check if coordinates or on a straight diagonal.
68
+ *
69
+ * @param int $whiteRank
70
+ * @param int $whiteFile
71
+ * @param int $blackRank
72
+ * @param int $blackFile
73
+ *
74
+ * @return bool
75
+ */
76
+ function onDiagonal($whiteRank, $whiteFile, $blackRank, $blackFile)
77
+ {
78
+ $whitePosition = abs(($whiteRank - $blackRank));
79
+ $blackPosition = abs(($whiteFile - $blackFile));
80
+
81
+ if ($whitePosition === $blackPosition) {
82
+ return true;
83
+ }
84
+
85
+ return false;
86
+ }
@@ -0,0 +1,125 @@
1
+ <?php
2
+
3
+ require "queen-attack.php";
4
+
5
+ class QueenAttackTest extends PHPUnit\Framework\TestCase
6
+ {
7
+ /**
8
+ * Test a queen is placed in a valid position.
9
+ */
10
+ public function testCreateQueenWithValidPosition()
11
+ {
12
+ $this->assertTrue(placeQueen(2, 2));
13
+ }
14
+
15
+ /**
16
+ * Test the queen is placed on a positive rank.
17
+ *
18
+ * @expectedException InvalidArgumentException
19
+ * @expectedExceptionMessage The rank and file numbers must be positive.
20
+ */
21
+ public function testQueenHasPositiveRank()
22
+ {
23
+ $this->markTestSkipped();
24
+ placeQueen(-2, 2);
25
+ }
26
+
27
+ /**
28
+ * Test the queen has a rank on the board.
29
+ *
30
+ * @expectedException InvalidArgumentException
31
+ * @expectedExceptionMessage The position must be on a standard size chess board.
32
+ */
33
+ public function testQueenHasRankOnBoard()
34
+ {
35
+ $this->markTestSkipped();
36
+ placeQueen(8, 4);
37
+ }
38
+
39
+ /**
40
+ * Test the queen is placed on a positive file.
41
+ *
42
+ * @expectedException InvalidArgumentException
43
+ * @expectedExceptionMessage The rank and file numbers must be positive.
44
+ */
45
+ public function testQueenHasPositiveFile()
46
+ {
47
+ $this->markTestSkipped();
48
+ placeQueen(2, -2);
49
+ }
50
+
51
+ /**
52
+ * Test the queen has a file on the board.
53
+ *
54
+ * @expectedException InvalidArgumentException
55
+ * @expectedExceptionMessage The position must be on a standard size chess board.
56
+ */
57
+ public function testQueenHasFileOnBoard()
58
+ {
59
+ $this->markTestSkipped();
60
+ placeQueen(4, 8);
61
+ }
62
+
63
+ /**
64
+ * Test if queens can attack each other.
65
+ */
66
+ public function testQueensCanAttack()
67
+ {
68
+ $this->markTestSkipped();
69
+ $this->assertFalse(canAttack([2, 4], [6, 6]));
70
+ }
71
+
72
+ /**
73
+ * Test if queens can attack each other on the same rank.
74
+ */
75
+ public function testQueensCanAttackOnSameRank()
76
+ {
77
+ $this->markTestSkipped();
78
+ $this->assertTrue(canAttack([2, 4], [2, 6]));
79
+ }
80
+
81
+ /**
82
+ * Test if queens can attack each other on the same file.
83
+ */
84
+ public function testQueensCanAttackOnSameFile()
85
+ {
86
+ $this->markTestSkipped();
87
+ $this->assertTrue(canAttack([4, 5], [2, 5]));
88
+ }
89
+
90
+ /**
91
+ * Test if queens can attack each other on the first diagonal.
92
+ */
93
+ public function testQueensCanAttackOnFirstDiagonal()
94
+ {
95
+ $this->markTestSkipped();
96
+ $this->assertTrue(canAttack([2, 2], [0, 4]));
97
+ }
98
+
99
+ /**
100
+ * Test if queens can attack each other on the second diagonal.
101
+ */
102
+ public function testQueensCanAttackOnSecondDiagonal()
103
+ {
104
+ $this->markTestSkipped();
105
+ $this->assertTrue(canAttack([2, 2], [3, 1]));
106
+ }
107
+
108
+ /**
109
+ * Test if queens can attack each other on the third diagonal.
110
+ */
111
+ public function testQueensCanAttackOnThirdDiagonal()
112
+ {
113
+ $this->markTestSkipped();
114
+ $this->assertTrue(canAttack([2, 2], [1, 1]));
115
+ }
116
+
117
+ /**
118
+ * Test if queens can attack each other on the fourth diagonal.
119
+ */
120
+ public function testQueensCanAttackOnFourthDiagonal()
121
+ {
122
+ $this->markTestSkipped();
123
+ $this->assertTrue(canAttack([2, 2], [5, 5]));
124
+ }
125
+ }
@@ -0,0 +1,27 @@
1
+ <?php
2
+
3
+ function score($word)
4
+ {
5
+ if (strlen($word) === 0 || $word === ' ') {
6
+ return 0;
7
+ }
8
+
9
+ $scrabbleScore = [
10
+ 'a' => 1, 'b' => 3, 'c' => 3, 'd' => 2,
11
+ 'e' => 1, 'f' => 4, 'g' => 2, 'h' => 4,
12
+ 'i' => 1, 'j' => 8, 'k' => 5, 'l' => 1,
13
+ 'm' => 3, 'n' => 1, 'o' => 1, 'p' => 3,
14
+ 'q' => 10, 'r' => 1, 's' => 1, 't' => 1,
15
+ 'u' => 1, 'v' => 4, 'w' => 4, 'x' => 8,
16
+ 'y' => 4, 'z' => 10,
17
+ ];
18
+
19
+ $score = 0;
20
+ $letters = str_split(strtolower($word));
21
+
22
+ foreach ($letters as $letter) {
23
+ $score += $scrabbleScore[$letter];
24
+ }
25
+
26
+ return $score;
27
+ }