Домашни > Pitches love the D > Решения > Решението на Николай Радилов

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

8 точки общо

31 успешни теста
6 неуспешни теста
Код
Скрий всички коментари

  1class Tone:
  2    tones = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
  3
  4    def __init__(self, tone):
  5        if not tone in self.tones:
  6            raise TypeError("Invalid tone type.")
  7        self.tone = tone
  8
  9    def __str__(self):
 10        return self.tone
 11    
 12    def __eq__(self, other):
 13        if isinstance(other, Tone):
 14            return self.tone == other.tone
 15        return False
 16
 17    def __hash__(self):
 18        return hash(self.tone)
 19    
 20    def __add__(self, other):
 21        if isinstance(other, Interval):
 22           return Tone(Tone.tones[(Tone.tones.index(self.tone) + other.interval) % len(Tone.tones)])
 23        
 24        if isinstance(other, Tone):
 25            return Chord(self, other)
 26        
 27        raise TypeError("Invalid operation.")
 28
 29
 30    def __sub__(self, other):
 31        if isinstance(other, Interval):
 32            return Tone(Tone.tones[(Tone.tones.index(self.tone) - other.interval) % len(Tone.tones)])
 33        
 34        if isinstance(other, Tone):
 35            return Interval(abs(Tone.tones.index(self.tone) - Tone.tones.index(other.tone)))
 36    
 37        raise TypeError("Invalid operation.")
 38
 39
 40
 41class Interval:
 42    intervals = ("unison", "minor 2nd", "major 2nd",
 43                "minor 3rd", "major 3rd", "perfect 4th",
 44                "diminished 5th", "perfect 5th", "minor 6th",
 45                "major 6th", "minor 7th", "major 7th")
 46
 47    def __init__(self, number_of_semitones):
 48        self.interval = number_of_semitones % len(Interval.intervals)
 49
 50    def __str__(self):
 51        return self.intervals[self.interval]
 52    
 53    def __add__(self, other):
 54        if isinstance(other, Interval):        
 55            return Interval(self.interval + other.interval)
 56        
 57        raise TypeError("Invald operation")
 58    
 59    def __sub__(self, other):
 60        raise TypeError("Invald operation")
 61    
 62    def __neg__(self):
 63        return Interval(12 - self.interval)
 64
 65
 66class Chord:
 67    def __init__(self, first_tone, *other_tones):
 68        tones = set(other_tones)
 69        tones.add(first_tone)
 70
 71        if len(tones) == 1:
 72            raise TypeError("Cannot have a chord made of only 1 unique tone")
 73
 74        self.tones = list()
 75        for tone in Tone.tones:
 76            curr_tone = Tone(tone)
 77            if curr_tone in tones and curr_tone not in self.tones:
 78                self.tones.append(Tone(tone))
 79
 80        for idx, tone in enumerate(self.tones):
 81            if tone == first_tone:
 82                new_tones = self.tones[idx:]
 83                new_tones.extend(self.tones[:idx])
 84                self.tones = new_tones
 85                break
 86
 87        self.root = first_tone
 88                
 89    def __str__(self):
 90        return "-".join(str(tone) for tone in self.tones)
 91    
 92    def _is_type(self, chord_type):
 93        for tone in self.tones:
 94            if tone == self.root:
 95                continue
 96            
 97            if str(tone - self.root) == chord_type:
 98                return True
 99
100        return False
101
102    def is_minor(self):
103        return self._is_type("minor 3rd")
104        
105    def is_major(self):
106        return self._is_type("major 3rd")
107
108    def is_power_chord(self):
109        return not self._is_type("minor 3rd") and not self._is_type("major 3rd")
110    
111    def __add__(self, other):
112        if isinstance(other, Tone):
113            return Chord(self.root, other, *self.tones)
114        
115        if isinstance(other, Chord):
116            new_tones = self.tones[::]
117            new_tones.extend(other.tones)
118            return Chord(self.root, *new_tones)
119        
120        raise TypeError("Invald operation")
121
122        
123    def __sub__(self, other):
124        if isinstance(other, Tone):
125            if other not in self.tones:
126                raise TypeError(f"Cannot remove tone {other} from chord {self}")
127            
128            new_tones = self.tones[::]
129            new_tones.remove(other)
130            return Chord(new_tones[0], *new_tones)
131
132        raise TypeError("Invald operation")
133
134    def transposed(self, interval):
135        if isinstance(interval, Interval):
136            new_tones = self.tones[::]
137            new_tones = list(map(lambda tone: tone + interval, new_tones))
138            return Chord(new_tones[0], *new_tones)
139
140        raise TypeError("Invald operation")

....FFF...........F........F.......F.
======================================================================
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_add_interval_to_tone_left_side_error (test.TestOperations.test_add_interval_to_tone_left_side_error)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 211, in test_add_interval_to_tone_left_side_error
self.assertEqual(str(err.exception), INVALID_OPERATION)
AssertionError: 'Invald operation' != 'Invalid operation'
- Invald operation
+ Invalid operation
? +

======================================================================
FAIL: test_subtract_interval_from_tone_left_side_error (test.TestOperations.test_subtract_interval_from_tone_left_side_error)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 235, in test_subtract_interval_from_tone_left_side_error
self.assertEqual(str(err.exception), INVALID_OPERATION)
AssertionError: 'Invald operation' != 'Invalid operation'
- Invald operation
+ Invalid operation
? +

======================================================================
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.002s

FAILED (failures=6)

Дискусия
История
Това решение има само една версия.