Домашни > Pitches love the D > Решения > Решението на Анна Данова

Резултати
8 точки от тестове
0 точки от учител

8 точки общо

31 успешни теста
6 неуспешни теста
Код

  1CHORD_ERROR_MESSAGE = "Cannot have a chord made of only 1 unique tone"
  2INVALID_OPERATION_MESSAGE = "Invalid operation"
  3TONES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
  4INTERVALS = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"]
  5
  6class Tone:
  7    def __init__(self, tone):
  8        self.tone = tone
  9
 10    def __str__(self):
 11        return str(self.tone)
 12    
 13    def __iter__(self):
 14        return iter(self.tone)
 15
 16    def __add__(self, other):
 17        if isinstance(other, Tone):
 18            return Chord(self, other)
 19        if isinstance(other, Interval): 
 20            return Tone(TONES[(TONES.index(str(self)) + other.num_of_semitones) % len(TONES)])
 21
 22    def __sub__(self, other):
 23        if isinstance(other, Tone):
 24            return Interval(abs(TONES.index(str(self)) - TONES.index(str(other))))
 25        if isinstance(other, Interval): 
 26            return Tone(TONES[(TONES.index(str(self)) - other.num_of_semitones) % len(TONES)])
 27        
 28
 29class Interval:
 30    def __init__(self, num_of_tones):
 31        self.is_positive = num_of_tones >= 0
 32        num_of_tones = abs(num_of_tones)
 33        self.num_of_semitones = num_of_tones % len(INTERVALS)
 34    
 35    def __str__(self):
 36        return str(INTERVALS[self.num_of_semitones])
 37    
 38    def __int__(self):
 39        return self.num_of_semitones
 40    
 41    def __add__(self, other):
 42        if isinstance(other, Tone):
 43            raise TypeError(INVALID_OPERATION_MESSAGE)
 44        if isinstance(other, Interval):
 45            return Interval(int(self) + int(other))
 46
 47    def __sub__(self, other):
 48        if isinstance(other, Tone):
 49            raise TypeError(INVALID_OPERATION_MESSAGE)
 50        
 51    def __neg__(self):
 52        return Interval(-self.num_of_semitones)
 53
 54class Chord:
 55    def __init__(self, *tones):
 56        self.tones = []
 57        for tone in tones:
 58            if str(tone) not in self.tones:
 59                self.tones.append(str(tone))
 60        self.root = self.tones[0]
 61        if len(self.tones) == 1:
 62            raise TypeError(CHORD_ERROR_MESSAGE)
 63        tone_index = TONES.index(str(self.root))
 64        self.scale = TONES[tone_index:] + TONES[:tone_index]
 65        self.tones = sorted(self.tones, key=lambda tone: self.scale.index(str(tone))) 
 66        
 67    def __str__(self):
 68        return '-'.join(map(str, self.tones))
 69
 70    def is_major(self):
 71        for tone in self.tones:
 72            if abs(TONES.index(str(self.root)) - TONES.index(str(tone))) == INTERVALS.index("major 3rd"):
 73                return True
 74        return False
 75    
 76    def is_minor(self):
 77        for tone in self.tones:
 78            if abs(TONES.index(str(self.root)) - TONES.index(str(tone))) == INTERVALS.index("minor 3rd"):
 79                return True
 80        return False
 81    
 82    def is_power_chord(self):
 83        if self.is_minor() or self.is_major():
 84            return False
 85        return True
 86    
 87    def __add__(self, other):
 88        if isinstance(other, Tone):
 89            new_tones = self.tones + [other]
 90        if isinstance(other, Chord):
 91            new_tones = self.tones + other.tones
 92        return Chord(*new_tones)
 93
 94    def __sub__(self, other):
 95        if isinstance(other, Tone):
 96            if str(other) not in self.tones:
 97                raise TypeError(f"Cannot remove tone {other} from chord {str(self)}")
 98            if len(self.tones) < 3:
 99                raise TypeError("Cannot have a chord made of only 1 unique tone")
100            to_return = Chord(*self.tones)
101            if str(other) == str(to_return.root):
102                to_return.root = to_return.tones[1]
103                del to_return.tones[0]
104            else:
105                other_index = to_return.tones.index(str(other))
106                del to_return.tones[other_index]
107            return to_return
108
109    def transposed(self, interval):
110        if isinstance(interval, Interval):
111            new_tones = []
112            direction = 1 if interval.is_positive else -1
113            for tone in self.tones:
114                new_index = self.scale.index(str(tone)) + direction*int(interval)
115                new_tones.append(str(self.scale[new_index]))
116            return Chord(*new_tones)

....FFF...EF.......................F.
======================================================================
ERROR: test_transposed_overflow (test.TestBasicChordFunctionality.test_transposed_overflow)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 143, in test_transposed_overflow
result_chord = d_major_chord.transposed(Interval(8))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 115, in transposed
new_tones.append(str(self.scale[new_index]))
~~~~~~~~~~^^^^^^^^^^^
IndexError: list index out of range

======================================================================
FAIL: test_is_major (test.TestBasicChordFunctionality.test_is_major)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 107, in test_is_major
self.assertTrue(a_major_chord.is_major())
AssertionError: False is not true

======================================================================
FAIL: test_is_minor (test.TestBasicChordFunctionality.test_is_minor)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 90, in test_is_minor
self.assertTrue(a_minor_chord.is_minor())
AssertionError: False is not true

======================================================================
FAIL: test_is_power_chord (test.TestBasicChordFunctionality.test_is_power_chord)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 116, in test_is_power_chord
self.assertFalse(a_minor_chord.is_power_chord())
AssertionError: True is not false

======================================================================
FAIL: test_interval_negative (test.TestBasicIntervalFunctionality.test_interval_negative)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 51, in test_interval_negative
self.assertEqual(str(minor_2nd), "minor 2nd")
AssertionError: 'major 7th' != 'minor 2nd'
- major 7th
+ minor 2nd

======================================================================
FAIL: test_tone_subtraction_inverse (test.TestOperations.test_tone_subtraction_inverse)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 178, in test_tone_subtraction_inverse
self.assertEqual(str(perfect_4th), "perfect 4th")
AssertionError: 'perfect 5th' != 'perfect 4th'
- perfect 5th
? ^
+ perfect 4th
? ^

----------------------------------------------------------------------
Ran 37 tests in 0.003s

FAILED (failures=5, errors=1)

Дискусия
История

f1CHORD_ERROR_MESSAGE = "Cannot have a chord made of only 1 unique tone"f1CHORD_ERROR_MESSAGE = "Cannot have a chord made of only 1 unique tone"
2INVALID_OPERATION_MESSAGE = "Invalid operation"2INVALID_OPERATION_MESSAGE = "Invalid operation"
3TONES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]3TONES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
4INTERVALS = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"]4INTERVALS = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"]
55
6class Tone:6class Tone:
7    def __init__(self, tone):7    def __init__(self, tone):
8        self.tone = tone8        self.tone = tone
99
10    def __str__(self):10    def __str__(self):
11        return str(self.tone)11        return str(self.tone)
12    12    
13    def __iter__(self):13    def __iter__(self):
14        return iter(self.tone)14        return iter(self.tone)
1515
16    def __add__(self, other):16    def __add__(self, other):
17        if isinstance(other, Tone):17        if isinstance(other, Tone):
18            return Chord(self, other)18            return Chord(self, other)
19        if isinstance(other, Interval): 19        if isinstance(other, Interval): 
n20            return Tone(TONES[(TONES.index(str(self)) + other.num_of_semitones)%len(TONES)])n20            return Tone(TONES[(TONES.index(str(self)) + other.num_of_semitones) % len(TONES)])
2121
22    def __sub__(self, other):22    def __sub__(self, other):
23        if isinstance(other, Tone):23        if isinstance(other, Tone):
n24            return Interval(abs(TONES.index(str(self))-TONES.index(str(other))))n24            return Interval(abs(TONES.index(str(self)) - TONES.index(str(other))))
25        if isinstance(other, Interval): 25        if isinstance(other, Interval): 
n26            return Tone(TONES[(TONES.index(str(self)) - other.num_of_semitones)%len(TONES)])n26            return Tone(TONES[(TONES.index(str(self)) - other.num_of_semitones) % len(TONES)])
27        27        
2828
29class Interval:29class Interval:
30    def __init__(self, num_of_tones):30    def __init__(self, num_of_tones):
n31        if num_of_tones >= 0:n31        self.is_positive = num_of_tones >= 0
32            self.is_positive = True
33        else:
34            self.is_positive = False
35            num_of_tones = abs(num_of_tones)32        num_of_tones = abs(num_of_tones)
36        self.num_of_semitones = num_of_tones % len(INTERVALS)33        self.num_of_semitones = num_of_tones % len(INTERVALS)
37    34    
38    def __str__(self):35    def __str__(self):
39        return str(INTERVALS[self.num_of_semitones])36        return str(INTERVALS[self.num_of_semitones])
40    37    
41    def __int__(self):38    def __int__(self):
42        return self.num_of_semitones39        return self.num_of_semitones
43    40    
44    def __add__(self, other):41    def __add__(self, other):
45        if isinstance(other, Tone):42        if isinstance(other, Tone):
46            raise TypeError(INVALID_OPERATION_MESSAGE)43            raise TypeError(INVALID_OPERATION_MESSAGE)
47        if isinstance(other, Interval):44        if isinstance(other, Interval):
48            return Interval(int(self) + int(other))45            return Interval(int(self) + int(other))
4946
50    def __sub__(self, other):47    def __sub__(self, other):
51        if isinstance(other, Tone):48        if isinstance(other, Tone):
52            raise TypeError(INVALID_OPERATION_MESSAGE)49            raise TypeError(INVALID_OPERATION_MESSAGE)
53        50        
54    def __neg__(self):51    def __neg__(self):
n55        return Interval(-1*(self.num_of_semitones))n52        return Interval(-self.num_of_semitones)
5653
57class Chord:54class Chord:
58    def __init__(self, *tones):55    def __init__(self, *tones):
59        self.tones = []56        self.tones = []
60        for tone in tones:57        for tone in tones:
61            if str(tone) not in self.tones:58            if str(tone) not in self.tones:
62                self.tones.append(str(tone))59                self.tones.append(str(tone))
63        self.root = self.tones[0]60        self.root = self.tones[0]
64        if len(self.tones) == 1:61        if len(self.tones) == 1:
65            raise TypeError(CHORD_ERROR_MESSAGE)62            raise TypeError(CHORD_ERROR_MESSAGE)
66        tone_index = TONES.index(str(self.root))63        tone_index = TONES.index(str(self.root))
67        self.scale = TONES[tone_index:] + TONES[:tone_index]64        self.scale = TONES[tone_index:] + TONES[:tone_index]
68        self.tones = sorted(self.tones, key=lambda tone: self.scale.index(str(tone))) 65        self.tones = sorted(self.tones, key=lambda tone: self.scale.index(str(tone))) 
69        66        
n70    def sort_tones(self):n
71        self.tones = sorted(self.tones, key=lambda tone: self.scale.index(str(tone))) 
72 
73    def __str__(self):67    def __str__(self):
74        return '-'.join(map(str, self.tones))68        return '-'.join(map(str, self.tones))
7569
76    def is_major(self):70    def is_major(self):
77        for tone in self.tones:71        for tone in self.tones:
78            if abs(TONES.index(str(self.root)) - TONES.index(str(tone))) == INTERVALS.index("major 3rd"):72            if abs(TONES.index(str(self.root)) - TONES.index(str(tone))) == INTERVALS.index("major 3rd"):
79                return True73                return True
80        return False74        return False
81    75    
82    def is_minor(self):76    def is_minor(self):
83        for tone in self.tones:77        for tone in self.tones:
84            if abs(TONES.index(str(self.root)) - TONES.index(str(tone))) == INTERVALS.index("minor 3rd"):78            if abs(TONES.index(str(self.root)) - TONES.index(str(tone))) == INTERVALS.index("minor 3rd"):
85                return True79                return True
86        return False80        return False
87    81    
88    def is_power_chord(self):82    def is_power_chord(self):
89        if self.is_minor() or self.is_major():83        if self.is_minor() or self.is_major():
90            return False84            return False
91        return True85        return True
92    86    
93    def __add__(self, other):87    def __add__(self, other):
94        if isinstance(other, Tone):88        if isinstance(other, Tone):
95            new_tones = self.tones + [other]89            new_tones = self.tones + [other]
n96            return Chord(*new_tones)n
97        if isinstance(other, Chord):90        if isinstance(other, Chord):
98            new_tones = self.tones + other.tones91            new_tones = self.tones + other.tones
n99            return Chord(*new_tones)n92        return Chord(*new_tones)
10093
101    def __sub__(self, other):94    def __sub__(self, other):
102        if isinstance(other, Tone):95        if isinstance(other, Tone):
103            if str(other) not in self.tones:96            if str(other) not in self.tones:
104                raise TypeError(f"Cannot remove tone {other} from chord {str(self)}")97                raise TypeError(f"Cannot remove tone {other} from chord {str(self)}")
105            if len(self.tones) < 3:98            if len(self.tones) < 3:
106                raise TypeError("Cannot have a chord made of only 1 unique tone")99                raise TypeError("Cannot have a chord made of only 1 unique tone")
107            to_return = Chord(*self.tones)100            to_return = Chord(*self.tones)
108            if str(other) == str(to_return.root):101            if str(other) == str(to_return.root):
109                to_return.root = to_return.tones[1]102                to_return.root = to_return.tones[1]
110                del to_return.tones[0]103                del to_return.tones[0]
111            else:104            else:
112                other_index = to_return.tones.index(str(other))105                other_index = to_return.tones.index(str(other))
113                del to_return.tones[other_index]106                del to_return.tones[other_index]
114            return to_return107            return to_return
115108
116    def transposed(self, interval):109    def transposed(self, interval):
117        if isinstance(interval, Interval):110        if isinstance(interval, Interval):
118            new_tones = []111            new_tones = []
t119            if interval.is_positive:t112            direction = 1 if interval.is_positive else -1
120                for tone in self.tones:113            for tone in self.tones:
121                    new_index = self.scale.index(str(tone)) + int(interval)114                new_index = self.scale.index(str(tone)) + direction*int(interval)
122                    new_tones.append(str(self.scale[new_index]))115                new_tones.append(str(self.scale[new_index]))
123            else:
124                for tone in self.tones:
125                    new_index = self.scale.index(str(tone)) - int(interval)
126                    new_tones.append(str(self.scale[new_index]))
127            return Chord(*new_tones)116            return Chord(*new_tones)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op