trackler 2.2.1.87 → 2.2.1.88
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 +4 -4
 - data/lib/trackler/version.rb +1 -1
 - data/tracks/bash/.travis.yml +6 -2
 - data/tracks/bash/bin/validate-exercises +37 -0
 - data/tracks/bash/exercises/reverse-string/example.sh +1 -1
 - data/tracks/bash/exercises/reverse-string/reverse_string_test.sh +7 -7
 - data/tracks/csharp/exercises/bracket-push/BracketPush.cs +2 -15
 - data/tracks/elisp/.travis.yml +2 -2
 - data/tracks/elisp/config.json +8 -0
 - data/tracks/elisp/exercises/pangram/README.md +16 -0
 - data/tracks/elisp/exercises/pangram/example.el +17 -0
 - data/tracks/elisp/exercises/pangram/pangram-test.el +41 -0
 - data/tracks/elisp/exercises/pangram/pangram.el +9 -0
 - data/tracks/gnu-apl/config.json +6 -6
 - data/tracks/java/exercises/phone-number/.meta/hints.md +58 -0
 - data/tracks/java/exercises/phone-number/README.md +62 -0
 - data/tracks/java/exercises/rna-transcription/.meta/version +1 -1
 - data/tracks/java/exercises/rna-transcription/src/test/java/RnaTranscriptionTest.java +0 -29
 - data/tracks/python/.travis.yml +2 -2
 - data/tracks/python/exercises/complex-numbers/.meta/hints.md +3 -0
 - data/tracks/python/exercises/complex-numbers/README.md +4 -0
 - data/tracks/python/exercises/complex-numbers/complex_numbers.py +5 -5
 - data/tracks/python/exercises/complex-numbers/complex_numbers_test.py +28 -32
 - data/tracks/python/exercises/complex-numbers/example.py +8 -5
 - data/tracks/python/exercises/difference-of-squares/difference_of_squares.py +3 -3
 - data/tracks/python/exercises/difference-of-squares/example.py +6 -6
 - data/tracks/python/exercises/palindrome-products/example.py +112 -11
 - data/tracks/python/exercises/palindrome-products/palindrome_products_test.py +55 -14
 - data/tracks/python/exercises/pangram/pangram_test.py +9 -6
 - data/tracks/python/exercises/phone-number/phone_number_test.py +2 -2
 - data/tracks/python/exercises/secret-handshake/example.py +14 -47
 - data/tracks/python/exercises/secret-handshake/secret_handshake.py +2 -2
 - data/tracks/python/exercises/secret-handshake/secret_handshake_test.py +56 -25
 - data/tracks/python/exercises/transpose/example.py +5 -5
 - data/tracks/python/exercises/transpose/transpose_test.py +37 -74
 - data/tracks/python/exercises/word-search/example.py +1 -1
 - data/tracks/python/exercises/word-search/word_search_test.py +63 -63
 - metadata +9 -2
 
| 
         @@ -1,16 +1,11 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            import org.junit.Before;
         
     | 
| 
       2 
2 
     | 
    
         
             
            import org.junit.Ignore;
         
     | 
| 
       3 
     | 
    
         
            -
            import org.junit.Rule;
         
     | 
| 
       4 
3 
     | 
    
         
             
            import org.junit.Test;
         
     | 
| 
       5 
     | 
    
         
            -
            import org.junit.rules.ExpectedException;
         
     | 
| 
       6 
4 
     | 
    
         | 
| 
       7 
5 
     | 
    
         
             
            import static org.junit.Assert.assertEquals;
         
     | 
| 
       8 
6 
     | 
    
         | 
| 
       9 
7 
     | 
    
         
             
            public class RnaTranscriptionTest {
         
     | 
| 
       10 
8 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                @Rule
         
     | 
| 
       12 
     | 
    
         
            -
                public ExpectedException expectedException = ExpectedException.none();
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
9 
     | 
    
         
             
                private RnaTranscription rnaTranscription;
         
     | 
| 
       15 
10 
     | 
    
         | 
| 
       16 
11 
     | 
    
         
             
                @Before
         
     | 
| 
         @@ -47,28 +42,4 @@ public class RnaTranscriptionTest { 
     | 
|
| 
       47 
42 
     | 
    
         
             
                    assertEquals("UGCACCAGAAUU", rnaTranscription.transcribe("ACGTGGTCTTAA"));
         
     | 
| 
       48 
43 
     | 
    
         
             
                }
         
     | 
| 
       49 
44 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
                @Ignore("Remove to run test")
         
     | 
| 
       51 
     | 
    
         
            -
                @Test
         
     | 
| 
       52 
     | 
    
         
            -
                public void testRnaTranscriptionOfRnaThrowsAnError() {
         
     | 
| 
       53 
     | 
    
         
            -
                    expectedException.expect(IllegalArgumentException.class);
         
     | 
| 
       54 
     | 
    
         
            -
                    expectedException.expectMessage("Invalid input");
         
     | 
| 
       55 
     | 
    
         
            -
                    rnaTranscription.transcribe("U");
         
     | 
| 
       56 
     | 
    
         
            -
                }
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
                @Ignore("Remove to run test")
         
     | 
| 
       59 
     | 
    
         
            -
                @Test
         
     | 
| 
       60 
     | 
    
         
            -
                public void testRnaTranscriptionOfInvalidInputThrowsAnError() {
         
     | 
| 
       61 
     | 
    
         
            -
                    expectedException.expect(IllegalArgumentException.class);
         
     | 
| 
       62 
     | 
    
         
            -
                    expectedException.expectMessage("Invalid input");
         
     | 
| 
       63 
     | 
    
         
            -
                    rnaTranscription.transcribe("XXX");
         
     | 
| 
       64 
     | 
    
         
            -
                }
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                @Ignore("Remove to run test")
         
     | 
| 
       67 
     | 
    
         
            -
                @Test
         
     | 
| 
       68 
     | 
    
         
            -
                public void testRnaTranscriptionOfPartiallyInvalidInput() {
         
     | 
| 
       69 
     | 
    
         
            -
                    expectedException.expect(IllegalArgumentException.class);
         
     | 
| 
       70 
     | 
    
         
            -
                    expectedException.expectMessage("Invalid input");
         
     | 
| 
       71 
     | 
    
         
            -
                    rnaTranscription.transcribe("ACGTXXXCTTAA");
         
     | 
| 
       72 
     | 
    
         
            -
                }
         
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
45 
     | 
    
         
             
            }
         
     | 
    
        data/tracks/python/.travis.yml
    CHANGED
    
    
| 
         @@ -31,6 +31,10 @@ Implement the following operations: 
     | 
|
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
            Assume the programming language you are using does not have an implementation of complex numbers.
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
      
 34 
     | 
    
         
            +
            ## Hints
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            See [Emulating numeric types](https://docs.python.org/2/reference/datamodel.html#emulating-numeric-types) for help on operator overloading.
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
       34 
38 
     | 
    
         
             
            ## Exception messages
         
     | 
| 
       35 
39 
     | 
    
         | 
| 
       36 
40 
     | 
    
         
             
            Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to
         
     | 
| 
         @@ -2,19 +2,19 @@ class ComplexNumber(object): 
     | 
|
| 
       2 
2 
     | 
    
         
             
                def __init__(self, real, imaginary):
         
     | 
| 
       3 
3 
     | 
    
         
             
                    pass
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
                def  
     | 
| 
      
 5 
     | 
    
         
            +
                def __add__(self, other):
         
     | 
| 
       6 
6 
     | 
    
         
             
                    pass
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
                def  
     | 
| 
      
 8 
     | 
    
         
            +
                def __mul__(self, other):
         
     | 
| 
       9 
9 
     | 
    
         
             
                    pass
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                def  
     | 
| 
      
 11 
     | 
    
         
            +
                def __sub__(self, other):
         
     | 
| 
       12 
12 
     | 
    
         
             
                    pass
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                def  
     | 
| 
      
 14 
     | 
    
         
            +
                def __truediv__(self, other):
         
     | 
| 
       15 
15 
     | 
    
         
             
                    pass
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                def  
     | 
| 
      
 17 
     | 
    
         
            +
                def __abs__(self):
         
     | 
| 
       18 
18 
     | 
    
         
             
                    pass
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
                def conjugate(self):
         
     | 
| 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            from __future__ import division
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            import unittest
         
     | 
| 
       2 
4 
     | 
    
         | 
| 
       3 
5 
     | 
    
         
             
            import math
         
     | 
| 
         @@ -13,95 +15,89 @@ class ComplexNumbersTest(unittest.TestCase): 
     | 
|
| 
       13 
15 
     | 
    
         
             
                def test_add_purely_real_numbers(self):
         
     | 
| 
       14 
16 
     | 
    
         
             
                    first_input = ComplexNumber(1, 0)
         
     | 
| 
       15 
17 
     | 
    
         
             
                    second_input = ComplexNumber(2, 0)
         
     | 
| 
       16 
     | 
    
         
            -
                     
     | 
| 
       17 
     | 
    
         
            -
                    self.assertEqual(first_input 
     | 
| 
      
 18 
     | 
    
         
            +
                    expected = ComplexNumber(3, 0)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.assertEqual(first_input + second_input, expected)
         
     | 
| 
       18 
20 
     | 
    
         | 
| 
       19 
21 
     | 
    
         
             
                def test_add_purely_imaginary_numbers(self):
         
     | 
| 
       20 
22 
     | 
    
         
             
                    first_input = ComplexNumber(0, 1)
         
     | 
| 
       21 
23 
     | 
    
         
             
                    second_input = ComplexNumber(0, 2)
         
     | 
| 
       22 
     | 
    
         
            -
                     
     | 
| 
       23 
     | 
    
         
            -
                    self.assertEqual(first_input 
     | 
| 
      
 24 
     | 
    
         
            +
                    expected = ComplexNumber(0, 3)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    self.assertEqual(first_input + second_input, expected)
         
     | 
| 
       24 
26 
     | 
    
         | 
| 
       25 
27 
     | 
    
         
             
                def test_add_numbers_with_real_and_imaginary_part(self):
         
     | 
| 
       26 
28 
     | 
    
         
             
                    first_input = ComplexNumber(1, 2)
         
     | 
| 
       27 
29 
     | 
    
         
             
                    second_input = ComplexNumber(3, 4)
         
     | 
| 
       28 
     | 
    
         
            -
                     
     | 
| 
       29 
     | 
    
         
            -
                    self.assertEqual(first_input 
     | 
| 
      
 30 
     | 
    
         
            +
                    expected = ComplexNumber(4, 6)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    self.assertEqual(first_input + second_input, expected)
         
     | 
| 
       30 
32 
     | 
    
         | 
| 
       31 
33 
     | 
    
         
             
                def test_subtract_purely_real_numbers(self):
         
     | 
| 
       32 
34 
     | 
    
         
             
                    first_input = ComplexNumber(1, 0)
         
     | 
| 
       33 
35 
     | 
    
         
             
                    second_input = ComplexNumber(2, 0)
         
     | 
| 
       34 
     | 
    
         
            -
                     
     | 
| 
       35 
     | 
    
         
            -
                    self.assertEqual(first_input 
     | 
| 
      
 36 
     | 
    
         
            +
                    expected = ComplexNumber(-1, 0)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    self.assertEqual(first_input - second_input, expected)
         
     | 
| 
       36 
38 
     | 
    
         | 
| 
       37 
39 
     | 
    
         
             
                def test_subtract_purely_imaginary_numbers(self):
         
     | 
| 
       38 
40 
     | 
    
         
             
                    first_input = ComplexNumber(0, 1)
         
     | 
| 
       39 
41 
     | 
    
         
             
                    second_input = ComplexNumber(0, 2)
         
     | 
| 
       40 
     | 
    
         
            -
                     
     | 
| 
       41 
     | 
    
         
            -
                    self.assertEqual(first_input 
     | 
| 
      
 42 
     | 
    
         
            +
                    expected = ComplexNumber(0, -1)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    self.assertEqual(first_input - second_input, expected)
         
     | 
| 
       42 
44 
     | 
    
         | 
| 
       43 
45 
     | 
    
         
             
                def test_subtract_numbers_with_real_and_imaginary_part(self):
         
     | 
| 
       44 
46 
     | 
    
         
             
                    first_input = ComplexNumber(1, 2)
         
     | 
| 
       45 
47 
     | 
    
         
             
                    second_input = ComplexNumber(3, 4)
         
     | 
| 
       46 
     | 
    
         
            -
                     
     | 
| 
       47 
     | 
    
         
            -
                    self.assertEqual(first_input 
     | 
| 
      
 48 
     | 
    
         
            +
                    expected = ComplexNumber(-2, -2)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    self.assertEqual(first_input - second_input, expected)
         
     | 
| 
       48 
50 
     | 
    
         | 
| 
       49 
51 
     | 
    
         
             
                def test_multiply_purely_real_numbers(self):
         
     | 
| 
       50 
52 
     | 
    
         
             
                    first_input = ComplexNumber(1, 0)
         
     | 
| 
       51 
53 
     | 
    
         
             
                    second_input = ComplexNumber(2, 0)
         
     | 
| 
       52 
     | 
    
         
            -
                     
     | 
| 
       53 
     | 
    
         
            -
                    self.assertEqual(first_input 
     | 
| 
      
 54 
     | 
    
         
            +
                    expected = ComplexNumber(2, 0)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    self.assertEqual(first_input * second_input, expected)
         
     | 
| 
       54 
56 
     | 
    
         | 
| 
       55 
57 
     | 
    
         
             
                def test_multiply_purely_imaginary_numbers(self):
         
     | 
| 
       56 
58 
     | 
    
         
             
                    first_input = ComplexNumber(0, 1)
         
     | 
| 
       57 
59 
     | 
    
         
             
                    second_input = ComplexNumber(0, 2)
         
     | 
| 
       58 
     | 
    
         
            -
                     
     | 
| 
       59 
     | 
    
         
            -
                    self.assertEqual(first_input 
     | 
| 
      
 60 
     | 
    
         
            +
                    expected = ComplexNumber(-2, 0)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    self.assertEqual(first_input * second_input, expected)
         
     | 
| 
       60 
62 
     | 
    
         | 
| 
       61 
63 
     | 
    
         
             
                def test_multiply_numbers_with_real_and_imaginary_part(self):
         
     | 
| 
       62 
64 
     | 
    
         
             
                    first_input = ComplexNumber(1, 2)
         
     | 
| 
       63 
65 
     | 
    
         
             
                    second_input = ComplexNumber(3, 4)
         
     | 
| 
       64 
     | 
    
         
            -
                     
     | 
| 
       65 
     | 
    
         
            -
                    self.assertEqual(first_input 
     | 
| 
      
 66 
     | 
    
         
            +
                    expected = ComplexNumber(-5, 10)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    self.assertEqual(first_input * second_input, expected)
         
     | 
| 
       66 
68 
     | 
    
         | 
| 
       67 
69 
     | 
    
         
             
                def test_divide_purely_real_numbers(self):
         
     | 
| 
       68 
70 
     | 
    
         
             
                    input_number = ComplexNumber(1.0, 0.0)
         
     | 
| 
       69 
71 
     | 
    
         
             
                    expected = ComplexNumber(0.5, 0.0)
         
     | 
| 
       70 
72 
     | 
    
         
             
                    divider = ComplexNumber(2.0, 0.0)
         
     | 
| 
       71 
     | 
    
         
            -
                    self.assertEqual(input_number 
     | 
| 
       72 
     | 
    
         
            -
                    self.assertEqual(input_number.div(divider).imaginary,
         
     | 
| 
       73 
     | 
    
         
            -
                                     expected.imaginary)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    self.assertEqual(input_number / divider, expected)
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
       75 
75 
     | 
    
         
             
                def test_divide_purely_imaginary_numbers(self):
         
     | 
| 
       76 
76 
     | 
    
         
             
                    input_number = ComplexNumber(0, 1)
         
     | 
| 
       77 
77 
     | 
    
         
             
                    expected = ComplexNumber(0.5, 0)
         
     | 
| 
       78 
78 
     | 
    
         
             
                    divider = ComplexNumber(0, 2)
         
     | 
| 
       79 
     | 
    
         
            -
                    self.assertEqual(input_number 
     | 
| 
       80 
     | 
    
         
            -
                    self.assertEqual(input_number.div(divider).imaginary,
         
     | 
| 
       81 
     | 
    
         
            -
                                     expected.imaginary)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    self.assertEqual(input_number / divider, expected)
         
     | 
| 
       82 
80 
     | 
    
         | 
| 
       83 
81 
     | 
    
         
             
                def test_divide_numbers_with_real_and_imaginary_part(self):
         
     | 
| 
       84 
82 
     | 
    
         
             
                    input_number = ComplexNumber(1, 2)
         
     | 
| 
       85 
83 
     | 
    
         
             
                    expected = ComplexNumber(0.44, 0.08)
         
     | 
| 
       86 
84 
     | 
    
         
             
                    divider = ComplexNumber(3, 4)
         
     | 
| 
       87 
     | 
    
         
            -
                    self.assertEqual(input_number 
     | 
| 
       88 
     | 
    
         
            -
                    self.assertEqual(input_number.div(divider).imaginary,
         
     | 
| 
       89 
     | 
    
         
            -
                                     expected.imaginary)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    self.assertEqual(input_number / divider, expected)
         
     | 
| 
       90 
86 
     | 
    
         | 
| 
       91 
87 
     | 
    
         
             
                def test_absolute_value_of_a_positive_purely_real_number(self):
         
     | 
| 
       92 
     | 
    
         
            -
                    self.assertEqual(ComplexNumber(5, 0) 
     | 
| 
      
 88 
     | 
    
         
            +
                    self.assertEqual(abs(ComplexNumber(5, 0)), 5)
         
     | 
| 
       93 
89 
     | 
    
         | 
| 
       94 
90 
     | 
    
         
             
                def test_absolute_value_of_a_negative_purely_real_number(self):
         
     | 
| 
       95 
     | 
    
         
            -
                    self.assertEqual(ComplexNumber(-5, 0) 
     | 
| 
      
 91 
     | 
    
         
            +
                    self.assertEqual(abs(ComplexNumber(-5, 0)), 5)
         
     | 
| 
       96 
92 
     | 
    
         | 
| 
       97 
93 
     | 
    
         
             
                def test_absolute_value_of_imaginary_number_positive_imaginary_part(self):
         
     | 
| 
       98 
     | 
    
         
            -
                    self.assertEqual(ComplexNumber(0, 5) 
     | 
| 
      
 94 
     | 
    
         
            +
                    self.assertEqual(abs(ComplexNumber(0, 5)), 5)
         
     | 
| 
       99 
95 
     | 
    
         | 
| 
       100 
96 
     | 
    
         
             
                def test_absolute_value_of_imaginary_number_negative_imaginary_part(self):
         
     | 
| 
       101 
     | 
    
         
            -
                    self.assertEqual(ComplexNumber(0, -5) 
     | 
| 
      
 97 
     | 
    
         
            +
                    self.assertEqual(abs(ComplexNumber(0, -5)), 5)
         
     | 
| 
       102 
98 
     | 
    
         | 
| 
       103 
99 
     | 
    
         
             
                def test_absolute_value_of_a_number_with_real_and_imaginary_part(self):
         
     | 
| 
       104 
     | 
    
         
            -
                    self.assertEqual(ComplexNumber(3, 4) 
     | 
| 
      
 100 
     | 
    
         
            +
                    self.assertEqual(abs(ComplexNumber(3, 4)), 5)
         
     | 
| 
       105 
101 
     | 
    
         | 
| 
       106 
102 
     | 
    
         
             
                def test_conjugate_a_purely_real_number(self):
         
     | 
| 
       107 
103 
     | 
    
         
             
                    input_number = ComplexNumber(5, 0)
         
     | 
| 
         @@ -6,22 +6,25 @@ class ComplexNumber(object): 
     | 
|
| 
       6 
6 
     | 
    
         
             
                    self.real = real
         
     | 
| 
       7 
7 
     | 
    
         
             
                    self.imaginary = imaginary
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                def  
     | 
| 
      
 9 
     | 
    
         
            +
                def __eq__(self, other):
         
     | 
| 
      
 10 
     | 
    
         
            +
                    return self.real == other.real and self.imaginary == other.imaginary
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def __add__(self, other):
         
     | 
| 
       10 
13 
     | 
    
         
             
                    r = self.real + other.real
         
     | 
| 
       11 
14 
     | 
    
         
             
                    i = self.imaginary + other.imaginary
         
     | 
| 
       12 
15 
     | 
    
         
             
                    return ComplexNumber(r, i)
         
     | 
| 
       13 
16 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                def  
     | 
| 
      
 17 
     | 
    
         
            +
                def __mul__(self, other):
         
     | 
| 
       15 
18 
     | 
    
         
             
                    r = self.real * other.real - self.imaginary * other.imaginary
         
     | 
| 
       16 
19 
     | 
    
         
             
                    i = self.real * other.imaginary + self.imaginary * other.real
         
     | 
| 
       17 
20 
     | 
    
         
             
                    return ComplexNumber(r, i)
         
     | 
| 
       18 
21 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
                def  
     | 
| 
      
 22 
     | 
    
         
            +
                def __sub__(self, other):
         
     | 
| 
       20 
23 
     | 
    
         
             
                    r = self.real - other.real
         
     | 
| 
       21 
24 
     | 
    
         
             
                    i = self.imaginary - other.imaginary
         
     | 
| 
       22 
25 
     | 
    
         
             
                    return ComplexNumber(r, i)
         
     | 
| 
       23 
26 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                def  
     | 
| 
      
 27 
     | 
    
         
            +
                def __truediv__(self, other):
         
     | 
| 
       25 
28 
     | 
    
         
             
                    d = other.real * other.real + other.imaginary * other.imaginary
         
     | 
| 
       26 
29 
     | 
    
         
             
                    r = (self.real * other.real + self.imaginary *
         
     | 
| 
       27 
30 
     | 
    
         
             
                         other.imaginary) / float(d)
         
     | 
| 
         @@ -29,7 +32,7 @@ class ComplexNumber(object): 
     | 
|
| 
       29 
32 
     | 
    
         
             
                         self.real * other.imaginary) / float(d)
         
     | 
| 
       30 
33 
     | 
    
         
             
                    return ComplexNumber(r, i)
         
     | 
| 
       31 
34 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                def  
     | 
| 
      
 35 
     | 
    
         
            +
                def __abs__(self):
         
     | 
| 
       33 
36 
     | 
    
         
             
                    square_sum = self.real * self.real + self.imaginary * self.imaginary
         
     | 
| 
       34 
37 
     | 
    
         
             
                    return math.sqrt(square_sum)
         
     | 
| 
       35 
38 
     | 
    
         | 
| 
         @@ -1,11 +1,11 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            def square_of_sum( 
     | 
| 
       2 
     | 
    
         
            -
                sum_ =  
     | 
| 
      
 1 
     | 
    
         
            +
            def square_of_sum(count):
         
     | 
| 
      
 2 
     | 
    
         
            +
                sum_ = count * (count + 1) / 2
         
     | 
| 
       3 
3 
     | 
    
         
             
                return sum_ * sum_
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
            def sum_of_squares( 
     | 
| 
       7 
     | 
    
         
            -
                return sum(m * m for m in range( 
     | 
| 
      
 6 
     | 
    
         
            +
            def sum_of_squares(count):
         
     | 
| 
      
 7 
     | 
    
         
            +
                return sum(m * m for m in range(count + 1))
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
            def difference( 
     | 
| 
       11 
     | 
    
         
            -
                return square_of_sum( 
     | 
| 
      
 10 
     | 
    
         
            +
            def difference(count):
         
     | 
| 
      
 11 
     | 
    
         
            +
                return square_of_sum(count) - sum_of_squares(count)
         
     | 
| 
         @@ -1,18 +1,119 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            from __future__ import division
         
     | 
| 
      
 2 
     | 
    
         
            +
            from itertools import chain
         
     | 
| 
      
 3 
     | 
    
         
            +
            from math import log10, floor, ceil
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            def largest_palindrome(max_factor, min_factor):
         
     | 
| 
      
 7 
     | 
    
         
            +
                return get_extreme_palindrome_with_factors(max_factor, min_factor,
         
     | 
| 
      
 8 
     | 
    
         
            +
                                                           "largest")
         
     | 
| 
       3 
9 
     | 
    
         | 
| 
       4 
10 
     | 
    
         | 
| 
       5 
11 
     | 
    
         
             
            def smallest_palindrome(max_factor, min_factor):
         
     | 
| 
       6 
     | 
    
         
            -
                return  
     | 
| 
      
 12 
     | 
    
         
            +
                return get_extreme_palindrome_with_factors(max_factor, min_factor,
         
     | 
| 
      
 13 
     | 
    
         
            +
                                                           "smallest")
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            def get_extreme_palindrome_with_factors(max_factor, min_factor, extreme):
         
     | 
| 
      
 17 
     | 
    
         
            +
                palindromes_found = palindromes(max_factor, min_factor,
         
     | 
| 
      
 18 
     | 
    
         
            +
                                                reverse=(extreme == "largest"))
         
     | 
| 
      
 19 
     | 
    
         
            +
                factor_pairs = None
         
     | 
| 
      
 20 
     | 
    
         
            +
                for palin in palindromes_found:
         
     | 
| 
      
 21 
     | 
    
         
            +
                    factor_pairs = ((fact, palin // fact)
         
     | 
| 
      
 22 
     | 
    
         
            +
                                    for fact in range(min_factor, max_factor + 1)
         
     | 
| 
      
 23 
     | 
    
         
            +
                                    if palin % fact == 0)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    factor_pairs = list(pair for pair in factor_pairs
         
     | 
| 
      
 25 
     | 
    
         
            +
                                        if min_factor <= pair[1] <= max_factor)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    if len(factor_pairs) > 0:
         
     | 
| 
      
 27 
     | 
    
         
            +
                        break
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                if factor_pairs is None or len(factor_pairs) == 0:
         
     | 
| 
      
 30 
     | 
    
         
            +
                    raise ValueError("no palindrome with factors in the "
         
     | 
| 
      
 31 
     | 
    
         
            +
                                     "range {min_factor} to {max_factor}"
         
     | 
| 
      
 32 
     | 
    
         
            +
                                     .format(min_factor=min_factor,
         
     | 
| 
      
 33 
     | 
    
         
            +
                                             max_factor=max_factor))
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                return (palin, factor_pairs)
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            def reverse_num(n):
         
     | 
| 
      
 39 
     | 
    
         
            +
                rev = 0
         
     | 
| 
      
 40 
     | 
    
         
            +
                while n > 0:
         
     | 
| 
      
 41 
     | 
    
         
            +
                    rev *= 10
         
     | 
| 
      
 42 
     | 
    
         
            +
                    rev += (n % 10)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    n //= 10
         
     | 
| 
      
 44 
     | 
    
         
            +
                return rev
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            def num_digits(n):
         
     | 
| 
      
 48 
     | 
    
         
            +
                return int(floor(log10(n) + 1))
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            def palindromes(max_factor, min_factor, reverse=False):
         
     | 
| 
      
 52 
     | 
    
         
            +
                """Generates all palindromes between `min_factor`**2 and max_factor`**2
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                If `reverse` is True, will produce the palindromes in decreasing order,
         
     | 
| 
      
 55 
     | 
    
         
            +
                from `max_factor`**2 down to `min_factor`**2. This is needed for
         
     | 
| 
      
 56 
     | 
    
         
            +
                `largest_palindrome`, since it won't have to iterate through a
         
     | 
| 
      
 57 
     | 
    
         
            +
                most of the palindromes just to find the one it needs.
         
     | 
| 
      
 58 
     | 
    
         
            +
                """
         
     | 
| 
      
 59 
     | 
    
         
            +
                if max_factor < min_factor:
         
     | 
| 
      
 60 
     | 
    
         
            +
                    raise ValueError("invalid input: min is {min_factor} "
         
     | 
| 
      
 61 
     | 
    
         
            +
                                     "and max is {max_factor}"
         
     | 
| 
      
 62 
     | 
    
         
            +
                                     .format(min_factor=min_factor,
         
     | 
| 
      
 63 
     | 
    
         
            +
                                             max_factor=max_factor))
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                minimum = min_factor ** 2
         
     | 
| 
      
 66 
     | 
    
         
            +
                maximum = max_factor ** 2
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def gen_palins_of_length(nd, reverse=reverse):
         
     | 
| 
      
 69 
     | 
    
         
            +
                    """Generates all palindromes with `nd` number of digits that are
         
     | 
| 
      
 70 
     | 
    
         
            +
                    within the desired range.
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    Again, if `reverse` is True, the palindromes are generated in
         
     | 
| 
      
 73 
     | 
    
         
            +
                    reverse order.
         
     | 
| 
      
 74 
     | 
    
         
            +
                    """
         
     | 
| 
      
 75 
     | 
    
         
            +
                    even_nd = (nd % 2 == 0)
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                    min_left_half = max(10 ** (int(ceil(nd / 2)) - 1),
         
     | 
| 
      
 78 
     | 
    
         
            +
                                        minimum // (10 ** (nd // 2)))
         
     | 
| 
      
 79 
     | 
    
         
            +
                    max_left_half = min((10 ** int(ceil(nd / 2))) - 1,
         
     | 
| 
      
 80 
     | 
    
         
            +
                                        maximum // (10 ** (nd // 2)))
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    current_left_half = min_left_half if not reverse else max_left_half
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    def make_palindrome(left_half, even_nd=False):
         
     | 
| 
      
 85 
     | 
    
         
            +
                        right_half = (reverse_num(left_half)
         
     | 
| 
      
 86 
     | 
    
         
            +
                                      if even_nd
         
     | 
| 
      
 87 
     | 
    
         
            +
                                      else reverse_num(left_half // 10))
         
     | 
| 
      
 88 
     | 
    
         
            +
                        return (left_half * (10 ** (nd // 2))) + right_half
         
     | 
| 
       7 
89 
     | 
    
         | 
| 
      
 90 
     | 
    
         
            +
                    if not reverse:
         
     | 
| 
      
 91 
     | 
    
         
            +
                        while current_left_half <= max_left_half:
         
     | 
| 
      
 92 
     | 
    
         
            +
                            palin = make_palindrome(current_left_half, even_nd)
         
     | 
| 
      
 93 
     | 
    
         
            +
                            if minimum <= palin <= maximum:
         
     | 
| 
      
 94 
     | 
    
         
            +
                                yield palin
         
     | 
| 
      
 95 
     | 
    
         
            +
                            elif palin > maximum:
         
     | 
| 
      
 96 
     | 
    
         
            +
                                # since palindromes are generated in increasing order,
         
     | 
| 
      
 97 
     | 
    
         
            +
                                #   we break out of the loop once we've exceeded the
         
     | 
| 
      
 98 
     | 
    
         
            +
                                #   maximum value
         
     | 
| 
      
 99 
     | 
    
         
            +
                                break
         
     | 
| 
      
 100 
     | 
    
         
            +
                            current_left_half += 1
         
     | 
| 
      
 101 
     | 
    
         
            +
                    else:
         
     | 
| 
      
 102 
     | 
    
         
            +
                        while current_left_half >= min_left_half:
         
     | 
| 
      
 103 
     | 
    
         
            +
                            palin = make_palindrome(current_left_half, even_nd)
         
     | 
| 
      
 104 
     | 
    
         
            +
                            if minimum <= palin <= maximum:
         
     | 
| 
      
 105 
     | 
    
         
            +
                                yield palin
         
     | 
| 
      
 106 
     | 
    
         
            +
                            elif palin < minimum:
         
     | 
| 
      
 107 
     | 
    
         
            +
                                # since palindromes are generated in decreasing order,
         
     | 
| 
      
 108 
     | 
    
         
            +
                                #   we break out of the loop once we've gone below the
         
     | 
| 
      
 109 
     | 
    
         
            +
                                #   minimum value
         
     | 
| 
      
 110 
     | 
    
         
            +
                                break
         
     | 
| 
      
 111 
     | 
    
         
            +
                            current_left_half -= 1
         
     | 
| 
       8 
112 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                return ((a * b, (a, b))
         
     | 
| 
       11 
     | 
    
         
            -
                        for a in range(min_factor, max_factor + 1)
         
     | 
| 
       12 
     | 
    
         
            -
                        for b in range(min_factor, a + 1)
         
     | 
| 
       13 
     | 
    
         
            -
                        if is_palindrome(a * b))
         
     | 
| 
      
 113 
     | 
    
         
            +
                min_nd, max_nd = num_digits(minimum), num_digits(maximum)
         
     | 
| 
       14 
114 
     | 
    
         | 
| 
      
 115 
     | 
    
         
            +
                lengths = (range(min_nd, max_nd + 1)
         
     | 
| 
      
 116 
     | 
    
         
            +
                           if not reverse
         
     | 
| 
      
 117 
     | 
    
         
            +
                           else range(max_nd, min_nd - 1, -1))
         
     | 
| 
       15 
118 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                s = str(n)
         
     | 
| 
       18 
     | 
    
         
            -
                return s == s[::-1]
         
     | 
| 
      
 119 
     | 
    
         
            +
                return chain(*map(gen_palins_of_length, lengths))
         
     | 
| 
         @@ -16,31 +16,72 @@ import unittest 
     | 
|
| 
       16 
16 
     | 
    
         
             
            from palindrome_products import smallest_palindrome, largest_palindrome
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         | 
| 
      
 19 
     | 
    
         
            +
            # Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       19 
21 
     | 
    
         
             
            class PalindromesTests(unittest.TestCase):
         
     | 
| 
      
 22 
     | 
    
         
            +
                def test_smallest_palindrome_from_single_digit_factors(self):
         
     | 
| 
      
 23 
     | 
    
         
            +
                    value, factors = smallest_palindrome(min_factor=1, max_factor=9)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.assertEqual(value, 1)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    self.assertFactorsEqual(factors, {(1, 1)})
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       20 
27 
     | 
    
         
             
                def test_largest_palindrome_from_single_digit_factors(self):
         
     | 
| 
       21 
     | 
    
         
            -
                    value, factors = largest_palindrome(max_factor=9)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    value, factors = largest_palindrome(min_factor=1, max_factor=9)
         
     | 
| 
       22 
29 
     | 
    
         
             
                    self.assertEqual(value, 9)
         
     | 
| 
       23 
     | 
    
         
            -
                    self. 
     | 
| 
      
 30 
     | 
    
         
            +
                    self.assertFactorsEqual(factors, {(1, 9), (3, 3)})
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def test_smallest_palindrome_from_double_digit_factors(self):
         
     | 
| 
      
 33 
     | 
    
         
            +
                    value, factors = smallest_palindrome(min_factor=10, max_factor=99)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    self.assertEqual(value, 121)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    self.assertFactorsEqual(factors, {(11, 11)})
         
     | 
| 
       24 
36 
     | 
    
         | 
| 
       25 
37 
     | 
    
         
             
                def test_largest_palindrome_from_double_digit_factors(self):
         
     | 
| 
       26 
     | 
    
         
            -
                    value, factors = largest_palindrome( 
     | 
| 
      
 38 
     | 
    
         
            +
                    value, factors = largest_palindrome(min_factor=10, max_factor=99)
         
     | 
| 
       27 
39 
     | 
    
         
             
                    self.assertEqual(value, 9009)
         
     | 
| 
       28 
     | 
    
         
            -
                    self. 
     | 
| 
      
 40 
     | 
    
         
            +
                    self.assertFactorsEqual(factors, {(91, 99)})
         
     | 
| 
       29 
41 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                def  
     | 
| 
       31 
     | 
    
         
            -
                    value, factors = smallest_palindrome( 
     | 
| 
       32 
     | 
    
         
            -
                    self.assertEqual(value,  
     | 
| 
       33 
     | 
    
         
            -
                    self. 
     | 
| 
      
 42 
     | 
    
         
            +
                def test_smallest_palindrome_from_triple_digit_factors(self):
         
     | 
| 
      
 43 
     | 
    
         
            +
                    value, factors = smallest_palindrome(min_factor=100, max_factor=999)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    self.assertEqual(value, 10201)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    self.assertFactorsEqual(factors, {(101, 101)})
         
     | 
| 
       34 
46 
     | 
    
         | 
| 
       35 
47 
     | 
    
         
             
                def test_largest_palindrome_from_triple_digit_factors(self):
         
     | 
| 
       36 
     | 
    
         
            -
                    value, factors = largest_palindrome( 
     | 
| 
      
 48 
     | 
    
         
            +
                    value, factors = largest_palindrome(min_factor=100, max_factor=999)
         
     | 
| 
       37 
49 
     | 
    
         
             
                    self.assertEqual(value, 906609)
         
     | 
| 
       38 
     | 
    
         
            -
                    self. 
     | 
| 
      
 50 
     | 
    
         
            +
                    self.assertFactorsEqual(factors, {(913, 993)})
         
     | 
| 
       39 
51 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                def  
     | 
| 
       41 
     | 
    
         
            -
                    value, factors = smallest_palindrome( 
     | 
| 
       42 
     | 
    
         
            -
                    self.assertEqual(value,  
     | 
| 
       43 
     | 
    
         
            -
                    self. 
     | 
| 
      
 52 
     | 
    
         
            +
                def test_smallest_palindrome_from_four_digit_factors(self):
         
     | 
| 
      
 53 
     | 
    
         
            +
                    value, factors = smallest_palindrome(min_factor=1000, max_factor=9999)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    self.assertEqual(value, 1002001)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    self.assertFactorsEqual(factors, {(1001, 1001)})
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                def test_largest_palindrome_from_four_digit_factors(self):
         
     | 
| 
      
 58 
     | 
    
         
            +
                    value, factors = largest_palindrome(min_factor=1000, max_factor=9999)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    self.assertEqual(value, 99000099)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    self.assertFactorsEqual(factors, {(9901, 9999)})
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                def test_empty_for_smallest_palindrome_if_none_in_range(self):
         
     | 
| 
      
 63 
     | 
    
         
            +
                    with self.assertRaises(ValueError):
         
     | 
| 
      
 64 
     | 
    
         
            +
                        value, factors = smallest_palindrome(min_factor=1002,
         
     | 
| 
      
 65 
     | 
    
         
            +
                                                             max_factor=1003)
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                def test_empty_for_largest_palindrome_if_none_in_range(self):
         
     | 
| 
      
 68 
     | 
    
         
            +
                    with self.assertRaises(ValueError):
         
     | 
| 
      
 69 
     | 
    
         
            +
                        value, factors = largest_palindrome(min_factor=15, max_factor=15)
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                def test_error_for_smallest_if_min_is_more_than_max(self):
         
     | 
| 
      
 72 
     | 
    
         
            +
                    with self.assertRaises(ValueError):
         
     | 
| 
      
 73 
     | 
    
         
            +
                        value, factors = smallest_palindrome(min_factor=10000,
         
     | 
| 
      
 74 
     | 
    
         
            +
                                                             max_factor=1)
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def test_error_for_largest_if_min_is_more_than_max(self):
         
     | 
| 
      
 77 
     | 
    
         
            +
                    with self.assertRaises(ValueError):
         
     | 
| 
      
 78 
     | 
    
         
            +
                        value, factors = largest_palindrome(min_factor=2, max_factor=1)
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                # Utility methods
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def assertFactorsEqual(self, actual, expected):
         
     | 
| 
      
 83 
     | 
    
         
            +
                    self.assertEqual(set(map(frozenset, actual)),
         
     | 
| 
      
 84 
     | 
    
         
            +
                                     set(map(frozenset, expected)))
         
     | 
| 
       44 
85 
     | 
    
         | 
| 
       45 
86 
     | 
    
         | 
| 
       46 
87 
     | 
    
         
             
            if __name__ == '__main__':
         
     |