trackler 2.1.0.31 → 2.1.0.32

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba0238c5efd0610f51d605a41a98489110c75117
4
- data.tar.gz: 3749d5108159a055ad4d2c68a99ed6297f01c272
3
+ metadata.gz: c5ad44a7e68d17060f904305997256916000928c
4
+ data.tar.gz: 262c51966c2eba2d2870792badd92f8f2f9ade76
5
5
  SHA512:
6
- metadata.gz: ba96c15d0f423acd0aee7ec87c11308d95bc8d634626361803a779bdbab47a278466de2baa348f698c628a95c3c0ab02e558f598aa6fcd4d65f19b2d9cdfbff4
7
- data.tar.gz: 70e84d13ae79a5d25eeba58d39ac848d2ae2b68c8d8c7f3d7c972e5beec589d58339005aa39fc1626242627fe1a041751b86e1bf7ff137c4a36621e73283ac2d
6
+ metadata.gz: 001fbb9c03793117bef7a7bad3c82ca75fe2ea41562b479a095dc505383e65edc6784a78de809a667ecd33c220f8789aa5f9a2889ca3c512682da5b0ff973545
7
+ data.tar.gz: 48e03ff57c34fa14be4bbef05786bcaf5928cc39feac666ce3c8139260bdbe9492e552f183c35a0829bd00f84b39d4d99629bf8196d014f72f768e269dc141c1
@@ -0,0 +1,3 @@
1
+ {
2
+ "slug": "coins"
3
+ }
@@ -0,0 +1 @@
1
+ This is the content of the docs/EXERCISE_README_INSERT.md file
@@ -1 +1 @@
1
- The SETUP.md file is deprecated, and exercises/TRACK_HINTS.md should be used.
1
+ The SETUP.md file is deprecated, and docs/EXERCISE_README_INSERT.md should be used.
@@ -119,15 +119,23 @@ module Trackler
119
119
  end
120
120
 
121
121
  def hints
122
- track_hints_filename = dir.join('exercises', 'TRACK_HINTS.md')
123
- unless File.exist?(track_hints_filename)
124
- track_hints_filename = dir.join('SETUP.md')
122
+ if File.exist?(track_hints_filename)
123
+ File.read(track_hints_filename)
124
+ else
125
+ ""
125
126
  end
126
- read track_hints_filename
127
127
  end
128
128
 
129
129
  private
130
130
 
131
+ def track_hints_filename
132
+ current = [File.join('docs', 'EXERCISE_README_INSERT.md')]
133
+ deprecated = [File.join('exercises', 'TRACK_HINTS.md'), 'SETUP.md']
134
+
135
+ filepaths = (current + deprecated).map { |name| dir.join(name) }
136
+ filepaths.find(-> { '' }) { |filepath| File.exist? filepath }
137
+ end
138
+
131
139
  # The slugs for the problems that are currently in the track.
132
140
  # We deprecated the old array of problem slugs in favor of an array
133
141
  # containing richer metadata about a given exercise.
@@ -202,13 +210,5 @@ module Trackler
202
210
  def png_icon
203
211
  @png_icon ||= Image.new(File.join(dir, "img/icon.png"))
204
212
  end
205
-
206
- def read(f)
207
- if File.exist?(f)
208
- File.read(f)
209
- else
210
- ""
211
- end
212
- end
213
213
  end
214
214
  end
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.1.0.31"
2
+ VERSION = "2.1.0.32"
3
3
  end
@@ -309,6 +309,15 @@
309
309
  "Parsing"
310
310
  ]
311
311
  },
312
+ {
313
+ "slug": "rotational-cipher",
314
+ "difficulty": 4,
315
+ "topics": [
316
+ "Strings",
317
+ "Algorithms",
318
+ "Transforming"
319
+ ]
320
+ },
312
321
  {
313
322
  "slug": "largest-series-product",
314
323
  "difficulty": 4,
@@ -210,6 +210,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZebraPuzzle", "zebra-puzzle
210
210
  EndProject
211
211
  Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Zipper", "zipper\Zipper.csproj", "{83504141-FF2A-427E-8A51-9FA0E9037A78}"
212
212
  EndProject
213
+ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RotationalCipher", "rotational-cipher\RotationalCipher.csproj", "{DF67FD2D-4897-43C5-A93E-7CCADBB29E75}"
214
+ EndProject
213
215
  Global
214
216
  GlobalSection(SolutionConfigurationPlatforms) = preSolution
215
217
  Debug|Any CPU = Debug|Any CPU
@@ -1468,6 +1470,18 @@ Global
1468
1470
  {83504141-FF2A-427E-8A51-9FA0E9037A78}.Release|x64.Build.0 = Release|Any CPU
1469
1471
  {83504141-FF2A-427E-8A51-9FA0E9037A78}.Release|x86.ActiveCfg = Release|Any CPU
1470
1472
  {83504141-FF2A-427E-8A51-9FA0E9037A78}.Release|x86.Build.0 = Release|Any CPU
1473
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1474
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Debug|Any CPU.Build.0 = Debug|Any CPU
1475
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Debug|x64.ActiveCfg = Debug|x64
1476
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Debug|x64.Build.0 = Debug|x64
1477
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Debug|x86.ActiveCfg = Debug|x86
1478
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Debug|x86.Build.0 = Debug|x86
1479
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Release|Any CPU.ActiveCfg = Release|Any CPU
1480
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Release|Any CPU.Build.0 = Release|Any CPU
1481
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Release|x64.ActiveCfg = Release|x64
1482
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Release|x64.Build.0 = Release|x64
1483
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Release|x86.ActiveCfg = Release|x86
1484
+ {DF67FD2D-4897-43C5-A93E-7CCADBB29E75}.Release|x86.Build.0 = Release|x86
1471
1485
  EndGlobalSection
1472
1486
  GlobalSection(SolutionProperties) = preSolution
1473
1487
  HideSolutionNode = FALSE
@@ -204,6 +204,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZebraPuzzle", "zebra-puzzle
204
204
  EndProject
205
205
  Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Zipper", "zipper\Zipper.csproj", "{83504141-FF2A-427E-8A51-9FA0E9037A78}"
206
206
  EndProject
207
+ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RotationalCipher", "rotational-cipher\RotationalCipher.csproj", "{F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}"
208
+ EndProject
207
209
  Global
208
210
  GlobalSection(SolutionConfigurationPlatforms) = preSolution
209
211
  Debug|Any CPU = Debug|Any CPU
@@ -1426,6 +1428,18 @@ Global
1426
1428
  {83504141-FF2A-427E-8A51-9FA0E9037A78}.Release|x64.Build.0 = Release|Any CPU
1427
1429
  {83504141-FF2A-427E-8A51-9FA0E9037A78}.Release|x86.ActiveCfg = Release|Any CPU
1428
1430
  {83504141-FF2A-427E-8A51-9FA0E9037A78}.Release|x86.Build.0 = Release|Any CPU
1431
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1432
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Debug|Any CPU.Build.0 = Debug|Any CPU
1433
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Debug|x64.ActiveCfg = Debug|x64
1434
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Debug|x64.Build.0 = Debug|x64
1435
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Debug|x86.ActiveCfg = Debug|x86
1436
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Debug|x86.Build.0 = Debug|x86
1437
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Release|Any CPU.ActiveCfg = Release|Any CPU
1438
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Release|Any CPU.Build.0 = Release|Any CPU
1439
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Release|x64.ActiveCfg = Release|x64
1440
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Release|x64.Build.0 = Release|x64
1441
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Release|x86.ActiveCfg = Release|x86
1442
+ {F72CEE93-2F93-4408-8FCC-FBEB3AF0C285}.Release|x86.Build.0 = Release|x86
1429
1443
  EndGlobalSection
1430
1444
  GlobalSection(SolutionProperties) = preSolution
1431
1445
  HideSolutionNode = FALSE
@@ -0,0 +1,22 @@
1
+ using System;
2
+ using System.Linq;
3
+
4
+ public static class RotationalCipher
5
+ {
6
+ private const string LowerCaseLetters = "abcdefghijklmnopqrstuvwxyz";
7
+ private const string UpperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
8
+
9
+ public static string Rotate(string text, int shiftKey)
10
+ => new string(text.Select(letter => Rotate(letter, shiftKey)).ToArray());
11
+
12
+ private static char Rotate(char letter, int shiftKey)
13
+ {
14
+ if (!char.IsLetter(letter))
15
+ return letter;
16
+
17
+ return Rotate(letter, shiftKey, char.IsLower(letter) ? LowerCaseLetters : UpperCaseLetters);
18
+ }
19
+
20
+ private static char Rotate(char letter, int shiftKey, string key)
21
+ => key[(key.IndexOf(letter) + shiftKey) % key.Length];
22
+ }
@@ -0,0 +1,9 @@
1
+ using System;
2
+
3
+ public static class RotationalCipher
4
+ {
5
+ public static string Rotate(string text, int shiftKey)
6
+ {
7
+ throw new NotImplementedException("You need to implement this function.");
8
+ }
9
+ }
@@ -0,0 +1,18 @@
1
+ <Project Sdk="Microsoft.NET.Sdk">
2
+
3
+ <PropertyGroup>
4
+ <OutputType>Exe</OutputType>
5
+ <TargetFramework>netcoreapp1.0</TargetFramework>
6
+ </PropertyGroup>
7
+
8
+ <ItemGroup>
9
+ <Compile Remove="Example.cs" />
10
+ </ItemGroup>
11
+
12
+ <ItemGroup>
13
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
14
+ <PackageReference Include="xunit" Version="2.2.0" />
15
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
16
+ </ItemGroup>
17
+
18
+ </Project>
@@ -0,0 +1,64 @@
1
+ using Xunit;
2
+
3
+ public class RotationalCipherTest
4
+ {
5
+ [Fact]
6
+ public void Rotate_a_by_1()
7
+ {
8
+ Assert.Equal("b", RotationalCipher.Rotate("a", 1));
9
+ }
10
+
11
+ [Fact(Skip = "Remove to run test")]
12
+ public void Rotate_a_by_26_same_output_as_input()
13
+ {
14
+ Assert.Equal("a", RotationalCipher.Rotate("a", 26));
15
+ }
16
+
17
+ [Fact(Skip = "Remove to run test")]
18
+ public void Rotate_a_by_0_same_output_as_input()
19
+ {
20
+ Assert.Equal("a", RotationalCipher.Rotate("a", 0));
21
+ }
22
+
23
+ [Fact(Skip = "Remove to run test")]
24
+ public void Rotate_m_by_13()
25
+ {
26
+ Assert.Equal("z", RotationalCipher.Rotate("m", 13));
27
+ }
28
+
29
+ [Fact(Skip = "Remove to run test")]
30
+ public void Rotate_n_by_13_with_wrap_around_alphabet()
31
+ {
32
+ Assert.Equal("a", RotationalCipher.Rotate("n", 13));
33
+ }
34
+
35
+ [Fact(Skip = "Remove to run test")]
36
+ public void Rotate_capital_letters()
37
+ {
38
+ Assert.Equal("TRL", RotationalCipher.Rotate("OMG", 5));
39
+ }
40
+
41
+ [Fact(Skip = "Remove to run test")]
42
+ public void Rotate_spaces()
43
+ {
44
+ Assert.Equal("T R L", RotationalCipher.Rotate("O M G", 5));
45
+ }
46
+
47
+ [Fact(Skip = "Remove to run test")]
48
+ public void Rotate_numbers()
49
+ {
50
+ Assert.Equal("Xiwxmrk 1 2 3 xiwxmrk", RotationalCipher.Rotate("Testing 1 2 3 testing", 4));
51
+ }
52
+
53
+ [Fact(Skip = "Remove to run test")]
54
+ public void Rotate_punctuation()
55
+ {
56
+ Assert.Equal("Gzo'n zvo, Bmviyhv!", RotationalCipher.Rotate("Let's eat, Grandma!", 21));
57
+ }
58
+
59
+ [Fact(Skip = "Remove to run test")]
60
+ public void Rotate_all_letters()
61
+ {
62
+ Assert.Equal("Gur dhvpx oebja sbk whzcf bire gur ynml qbt.", RotationalCipher.Rotate("The quick brown fox jumps over the lazy dog.", 13));
63
+ }
64
+ }
@@ -0,0 +1,23 @@
1
+ using Generators.Data;
2
+ using Generators.Methods;
3
+
4
+ namespace Generators.Exercises
5
+ {
6
+ public class RotationalCipherExercise : EqualityExercise
7
+ {
8
+ public RotationalCipherExercise() : base("rotational-cipher")
9
+ {
10
+ }
11
+
12
+ protected override TestMethodData CreateTestMethodData(CanonicalData canonicalData, CanonicalDataCase canonicalDataCase, int index)
13
+ {
14
+ var testMethodData = base.CreateTestMethodData(canonicalData, canonicalDataCase, index);
15
+ testMethodData.CanonicalDataCase.Input = new[]
16
+ {
17
+ testMethodData.CanonicalDataCase.Data["text"],
18
+ testMethodData.CanonicalDataCase.Data["shiftKey"]
19
+ };
20
+ return testMethodData;
21
+ }
22
+ }
23
+ }
@@ -52,8 +52,12 @@ private static TestClass CreateTestClass(Exercise exercise)
52
52
  return exercise.CreateTestClass(canonicalData);
53
53
  }
54
54
 
55
- private static void SaveTestClassContentsToFile(string testClassFilePath, string testClassContents) =>
55
+ private static void SaveTestClassContentsToFile(string testClassFilePath, string testClassContents)
56
+ {
57
+ Directory.CreateDirectory(Path.GetDirectoryName(testClassFilePath));
56
58
  File.WriteAllText(testClassFilePath, testClassContents);
59
+ }
60
+
57
61
 
58
62
  private static string TestFilePath(Exercise exercise, TestClass testClass) => Path.Combine("..", "exercises", exercise.Name, TestFileName(testClass));
59
63
 
@@ -7,7 +7,7 @@ import org.junit.rules.ExpectedException;
7
7
  import static org.junit.Assert.assertEquals;
8
8
 
9
9
  /*
10
- * version: 1.0.0
10
+ * version: 1.1.0
11
11
  */
12
12
  public class CollatzCalculatorTest {
13
13
 
@@ -38,6 +38,12 @@ public class CollatzCalculatorTest {
38
38
  assertEquals(9, collatzCalculator.computeStepCount(12));
39
39
  }
40
40
 
41
+ @Ignore("Remove to run test")
42
+ @Test
43
+ public void testAVeryLargeInput() {
44
+ assertEquals(152, collatzCalculator.computeStepCount(1000000));
45
+ }
46
+
41
47
  @Ignore("Remove to run test")
42
48
  @Test
43
49
  public void testZeroIsConsideredInvalidInput() {
@@ -24,17 +24,26 @@ subtest 'Class methods', {
24
24
  }
25
25
 
26
26
  my $c-data;
27
- is ::($exercise).new(hour => .<hour>, minute => .<minute>).?time, |.<expected description> for @($c-data<cases>[0]<cases>);
28
- for @($c-data<cases>[1,2]) {
29
- for @(.<cases>) {
30
- my $clock = ::($exercise).new(hour => .<hour>, minute => .<minute>);
31
- $clock.?add-minutes(.<add>);
32
- is $clock.?time, |.<expected description>;
27
+ for @($c-data<cases>) {
28
+ for @(.<cases>) -> $case {
29
+ given $case<property> {
30
+ when 'create' {
31
+ is ::($exercise).new(hour => $case<hour>, minute => $case<minute>).?time, |$case<expected description>;
32
+ }
33
+ when 'add' {
34
+ my $clock = ::($exercise).new(hour => $case<hour>, minute => $case<minute>);
35
+ $clock.?add-minutes($case<add>);
36
+ is $clock.?time, |$case<expected description>;
37
+ }
38
+ when 'equal' {
39
+ is ::($exercise).new(hour => $case<clock1><hour>, minute => $case<clock1><minute>).?time eq
40
+ ::($exercise).new(hour => $case<clock2><hour>, minute => $case<clock2><minute>).?time,
41
+ |$case<expected description>;
42
+ }
43
+ when %*ENV<EXERCISM>.so { bail-out "no case for property '$case<property>'" }
44
+ }
33
45
  }
34
46
  }
35
- is ::($exercise).new(hour => .<clock1><hour>, minute => .<clock1><minute>).?time eq
36
- ::($exercise).new(hour => .<clock2><hour>, minute => .<clock2><minute>).?time,
37
- |.<expected description> for @($c-data<cases>[3]<cases>);
38
47
  todo 'optional test' unless %*ENV<EXERCISM>;
39
48
  is ::($exercise).new(:0hour,:0minute).?add-minutes(65).?time, '01:05', 'add-minutes method can be chained';
40
49
 
@@ -3,16 +3,25 @@ version: 1
3
3
  methods: time add-minutes
4
4
  plan: 54
5
5
  tests: |
6
- is ::($exercise).new(hour => .<hour>, minute => .<minute>).?time, |.<expected description> for @($c-data<cases>[0]<cases>);
7
- for @($c-data<cases>[1,2]) {
8
- for @(.<cases>) {
9
- my $clock = ::($exercise).new(hour => .<hour>, minute => .<minute>);
10
- $clock.?add-minutes(.<add>);
11
- is $clock.?time, |.<expected description>;
6
+ for @($c-data<cases>) {
7
+ for @(.<cases>) -> $case {
8
+ given $case<property> {
9
+ when 'create' {
10
+ is ::($exercise).new(hour => $case<hour>, minute => $case<minute>).?time, |$case<expected description>;
11
+ }
12
+ when 'add' {
13
+ my $clock = ::($exercise).new(hour => $case<hour>, minute => $case<minute>);
14
+ $clock.?add-minutes($case<add>);
15
+ is $clock.?time, |$case<expected description>;
16
+ }
17
+ when 'equal' {
18
+ is ::($exercise).new(hour => $case<clock1><hour>, minute => $case<clock1><minute>).?time eq
19
+ ::($exercise).new(hour => $case<clock2><hour>, minute => $case<clock2><minute>).?time,
20
+ |$case<expected description>;
21
+ }
22
+ when %*ENV<EXERCISM>.so { bail-out "no case for property '$case<property>'" }
23
+ }
12
24
  }
13
25
  }
14
- is ::($exercise).new(hour => .<clock1><hour>, minute => .<clock1><minute>).?time eq
15
- ::($exercise).new(hour => .<clock2><hour>, minute => .<clock2><minute>).?time,
16
- |.<expected description> for @($c-data<cases>[3]<cases>);
17
26
  todo 'optional test' unless %*ENV<EXERCISM>;
18
27
  is ::($exercise).new(:0hour,:0minute).?add-minutes(65).?time, '01:05', 'add-minutes method can be chained';
@@ -488,6 +488,14 @@
488
488
  "topics": [
489
489
  ]
490
490
  },
491
+ {
492
+ "slug": "scale-generator",
493
+ "difficulty": 3,
494
+ "topics": [
495
+ "strings",
496
+ "pattern matching"
497
+ ]
498
+ },
491
499
  {
492
500
  "slug": "protein-translation",
493
501
  "difficulty": 3,
@@ -0,0 +1,33 @@
1
+ class Scale(object):
2
+
3
+ ASCENDING_INTERVALS = ['m', 'M', 'A']
4
+ CHROMATIC_SCALE = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A',
5
+ 'A#', 'B']
6
+ FLAT_CHROMATIC_SCALE = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab',
7
+ 'A', 'Bb', 'B']
8
+ FLAT_KEYS = ['F', 'Bb', 'Eb', 'Ab', 'Db', 'Gb', 'd', 'g', 'c', 'f', 'bb',
9
+ 'eb']
10
+
11
+ def __init__(self, tonic, scale_name, pattern=None):
12
+ self.tonic = tonic.capitalize()
13
+ self.name = self.tonic + ' ' + scale_name
14
+ self.pattern = pattern
15
+ self.chromatic_scale = (self.FLAT_CHROMATIC_SCALE
16
+ if tonic in self.FLAT_KEYS else
17
+ self.CHROMATIC_SCALE)
18
+ self.pitches = self._assign_pitches()
19
+
20
+ def _assign_pitches(self):
21
+ if self.pattern is None:
22
+ return self._reorder_chromatic_scale()
23
+ last_index = 0
24
+ pitches = []
25
+ scale = self._reorder_chromatic_scale()
26
+ for i, interval in enumerate(self.pattern):
27
+ pitches.append(scale[last_index])
28
+ last_index += self.ASCENDING_INTERVALS.index(interval) + 1
29
+ return pitches
30
+
31
+ def _reorder_chromatic_scale(self):
32
+ index = self.chromatic_scale.index(self.tonic)
33
+ return self.chromatic_scale[index:] + self.chromatic_scale[:index]
@@ -0,0 +1,3 @@
1
+ class Scale(object):
2
+ def __init__(self):
3
+ pass
@@ -0,0 +1,120 @@
1
+ import unittest
2
+
3
+ from scale_generator import Scale
4
+
5
+
6
+ class ScaleGeneratorTest(unittest.TestCase):
7
+
8
+ def test_naming_scale(self):
9
+ chromatic = Scale('c', 'chromatic')
10
+ expected = 'C chromatic'
11
+ actual = chromatic.name
12
+ self.assertEqual(expected, actual)
13
+
14
+ def test_chromatic_scale(self):
15
+ chromatic = Scale('C', 'chromatic')
16
+ expected = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#',
17
+ 'B']
18
+ actual = chromatic.pitches
19
+ self.assertEqual(expected, actual)
20
+
21
+ def test_another_chromatic_scale(self):
22
+ chromatic = Scale('F', 'chromatic')
23
+ expected = ['F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb',
24
+ 'E']
25
+ actual = chromatic.pitches
26
+ self.assertEqual(expected, actual)
27
+
28
+ def test_naming_major_scale(self):
29
+ major = Scale('G', 'major', 'MMmMMMm')
30
+ expected = 'G major'
31
+ actual = major.name
32
+ self.assertEqual(expected, actual)
33
+
34
+ def test_major_scale(self):
35
+ major = Scale('C', 'major', 'MMmMMMm')
36
+ expected = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
37
+ actual = major.pitches
38
+ self.assertEqual(expected, actual)
39
+
40
+ def test_another_major_scale(self):
41
+ major = Scale('G', 'major', 'MMmMMMm')
42
+ expected = ['G', 'A', 'B', 'C', 'D', 'E', 'F#']
43
+ actual = major.pitches
44
+ self.assertEqual(expected, actual)
45
+
46
+ def test_minor_scale(self):
47
+ minor = Scale('f#', 'minor', 'MmMMmMM')
48
+ expected = ['F#', 'G#', 'A', 'B', 'C#', 'D', 'E']
49
+ actual = minor.pitches
50
+ self.assertEqual(expected, actual)
51
+
52
+ def test_another_minor_scale(self):
53
+ minor = Scale('bb', 'minor', 'MmMMmMM')
54
+ expected = ['Bb', 'C', 'Db', 'Eb', 'F', 'Gb', 'Ab']
55
+ actual = minor.pitches
56
+ self.assertEqual(expected, actual)
57
+
58
+ def test_dorian_mode(self):
59
+ dorian = Scale('d', 'dorian', 'MmMMMmM')
60
+ expected = ['D', 'E', 'F', 'G', 'A', 'B', 'C']
61
+ actual = dorian.pitches
62
+ self.assertEqual(expected, actual)
63
+
64
+ def test_mixolydian_mode(self):
65
+ mixolydian = Scale('Eb', 'mixolydian', 'MMmMMmM')
66
+ expected = ['Eb', 'F', 'G', 'Ab', 'Bb', 'C', 'Db']
67
+ actual = mixolydian.pitches
68
+ self.assertEqual(expected, actual)
69
+
70
+ def test_lydian_mode(self):
71
+ lydian = Scale('a', 'lydian', 'MMMmMMm')
72
+ expected = ['A', 'B', 'C#', 'D#', 'E', 'F#', 'G#']
73
+ actual = lydian.pitches
74
+ self.assertEqual(expected, actual)
75
+
76
+ def test_phrygian_mode(self):
77
+ phrygian = Scale('e', 'phrygian', 'mMMMmMM')
78
+ expected = ['E', 'F', 'G', 'A', 'B', 'C', 'D']
79
+ actual = phrygian.pitches
80
+ self.assertEqual(expected, actual)
81
+
82
+ def test_locrian_mode(self):
83
+ locrian = Scale('g', 'locrian', 'mMMmMMM')
84
+ expected = ['G', 'Ab', 'Bb', 'C', 'Db', 'Eb', 'F']
85
+ actual = locrian.pitches
86
+ self.assertEqual(expected, actual)
87
+
88
+ def test_harmonic_minor(self):
89
+ harmonic_minor = Scale('d', 'harmonic_minor', 'MmMMmAm')
90
+ expected = ['D', 'E', 'F', 'G', 'A', 'Bb', 'Db']
91
+ actual = harmonic_minor.pitches
92
+ self.assertEqual(expected, actual)
93
+
94
+ def test_octatonic(self):
95
+ octatonic = Scale('C', 'octatonic', 'MmMmMmMm')
96
+ expected = ['C', 'D', 'D#', 'F', 'F#', 'G#', 'A', 'B']
97
+ actual = octatonic.pitches
98
+ self.assertEqual(expected, actual)
99
+
100
+ def test_hexatonic(self):
101
+ hexatonic = Scale('Db', 'hexatonic', 'MMMMMM')
102
+ expected = ['Db', 'Eb', 'F', 'G', 'A', 'B']
103
+ actual = hexatonic.pitches
104
+ self.assertEqual(expected, actual)
105
+
106
+ def test_pentatonic(self):
107
+ pentatonic = Scale('A', 'pentatonic', 'MMAMA')
108
+ expected = ['A', 'B', 'C#', 'E', 'F#']
109
+ actual = pentatonic.pitches
110
+ self.assertEqual(expected, actual)
111
+
112
+ def test_enigmatic(self):
113
+ enigmatic = Scale('G', 'enigmatic', 'mAMMMmM')
114
+ expected = ['G', 'G#', 'B', 'C#', 'D#', 'F', 'F#']
115
+ actual = enigmatic.pitches
116
+ self.assertEqual(expected, actual)
117
+
118
+
119
+ if __name__ == '__main__':
120
+ unittest.main()
@@ -1,9 +1,9 @@
1
1
  module BookKeeping
2
- VERSION = 3
2
+ VERSION = 4
3
3
  end
4
4
 
5
5
  class Isogram
6
- def self.is_isogram?(str)
6
+ def self.isogram?(str)
7
7
  letters = str.downcase.gsub(/[[:punct:]]| /, '').chars
8
8
  letters == letters.uniq
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trackler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0.31
4
+ version: 2.1.0.32
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katrina Owen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-08 00:00:00.000000000 Z
11
+ date: 2017-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -475,6 +475,8 @@ files:
475
475
  - fixtures/tracks/animal/exercises/fish/included-via-symlink.txt
476
476
  - fixtures/tracks/animal/global/some-vendored-library
477
477
  - fixtures/tracks/animal/global/sub-global/other-some-vendor
478
+ - fixtures/tracks/coins/config.json
479
+ - fixtures/tracks/coins/docs/EXERCISE_README_INSERT.md
478
480
  - fixtures/tracks/fake/config.json
479
481
  - fixtures/tracks/fake/docs/ABOUT.org
480
482
  - fixtures/tracks/fake/docs/INSTALLATION.org
@@ -1807,6 +1809,10 @@ files:
1807
1809
  - tracks/csharp/exercises/roman-numerals/RomanNumerals.cs
1808
1810
  - tracks/csharp/exercises/roman-numerals/RomanNumerals.csproj
1809
1811
  - tracks/csharp/exercises/roman-numerals/RomanNumeralsTest.cs
1812
+ - tracks/csharp/exercises/rotational-cipher/Example.cs
1813
+ - tracks/csharp/exercises/rotational-cipher/RotationalCipher.cs
1814
+ - tracks/csharp/exercises/rotational-cipher/RotationalCipher.csproj
1815
+ - tracks/csharp/exercises/rotational-cipher/RotationalCipherTest.cs
1810
1816
  - tracks/csharp/exercises/run-length-encoding/Example.cs
1811
1817
  - tracks/csharp/exercises/run-length-encoding/RunLengthEncoding.cs
1812
1818
  - tracks/csharp/exercises/run-length-encoding/RunLengthEncoding.csproj
@@ -1953,6 +1959,7 @@ files:
1953
1959
  - tracks/csharp/generators/Exercises/PigLatinExercise.cs
1954
1960
  - tracks/csharp/generators/Exercises/RaindropsExercise.cs
1955
1961
  - tracks/csharp/generators/Exercises/RomanNumeralsExercise.cs
1962
+ - tracks/csharp/generators/Exercises/RotationalCipherExercise.cs
1956
1963
  - tracks/csharp/generators/Exercises/WordyExercise.cs
1957
1964
  - tracks/csharp/generators/Generators.csproj
1958
1965
  - tracks/csharp/generators/Generators.csproj.user
@@ -7164,6 +7171,9 @@ files:
7164
7171
  - tracks/python/exercises/say/example.py
7165
7172
  - tracks/python/exercises/say/say.py
7166
7173
  - tracks/python/exercises/say/say_test.py
7174
+ - tracks/python/exercises/scale-generator/example.py
7175
+ - tracks/python/exercises/scale-generator/scale_generator.py
7176
+ - tracks/python/exercises/scale-generator/scale_generator_test.py
7167
7177
  - tracks/python/exercises/scrabble-score/example.py
7168
7178
  - tracks/python/exercises/scrabble-score/scrabble_score.py
7169
7179
  - tracks/python/exercises/scrabble-score/scrabble_score_test.py