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

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

8 точки общо

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

  1NUMBERS_OF_TONES = 12
  2UNIQUE_TONES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
  3
  4class Tone:
  5    def __init__(self, name):
  6        self.name = name
  7        self.position = UNIQUE_TONES.index(name)
  8
  9    def __str__(self):
 10        return self.name
 11    
 12    def __eq__(self, other):
 13        if isinstance(other, Tone):
 14            return self.name == other.name
 15        return False
 16    
 17    def __hash__(self):
 18        return hash(self.name)
 19    
 20    def __add__(self, other):
 21        if not isinstance(self, Tone):
 22            raise TypeError("Invalid operation")
 23    
 24        if isinstance(other, Tone):
 25            return Chord(self, other)
 26        elif isinstance(other, Interval):
 27            new_position = (self.position + other.semitones) % NUMBERS_OF_TONES
 28            return Tone(UNIQUE_TONES[new_position])
 29        else:
 30            raise TypeError("Invalid operation")
 31        
 32    def __sub__(self, other):
 33        if not isinstance(self, Tone):
 34            raise TypeError("Invalid operation")
 35    
 36        if isinstance(other, Tone):
 37            semitone_difference = ((self.position - other.position) + NUMBERS_OF_TONES) % NUMBERS_OF_TONES
 38            return Interval(semitone_difference)
 39        elif isinstance(other, Interval):
 40            new_position = ((self.position - other.semitones) + NUMBERS_OF_TONES) % NUMBERS_OF_TONES
 41            return Tone(UNIQUE_TONES[new_position])
 42        else:
 43            raise TypeError("Invalid operation")
 44
 45
 46class Interval:
 47    SEMITONES = ("unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th",
 48                 "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th")
 49    
 50    def __init__(self, semitones):
 51        self.semitones = semitones % NUMBERS_OF_TONES
 52
 53    def __str__(self):
 54        return self.SEMITONES[self.semitones]
 55    
 56    def __add__(self, other_interval):
 57        if not isinstance(other_interval, Interval):
 58            raise TypeError("Invalid operation")
 59        
 60        new_position = (self.semitones + other_interval.semitones) % NUMBERS_OF_TONES
 61        return self.SEMITONES[new_position]
 62        
 63    def __neg__(self):
 64        return Interval(-self.semitones)
 65
 66
 67class Chord:
 68   
 69    def __init__(self, keytone, *other_tones):
 70        self.keytone = keytone
 71        self.tones = {keytone, *other_tones}
 72        self.other_tones_set = {*other_tones}
 73        if len(self.tones) < 2:
 74            raise TypeError("Cannot have a chord made of only 1 unique tone")
 75        
 76    def __str__(self):
 77        start_index = self.keytone.position
 78        rotated_scale = (UNIQUE_TONES[start_index:] + UNIQUE_TONES[:start_index])
 79        ordered_tones = [tone for note_name in rotated_scale for tone in self.tones if tone.name == note_name]
 80        return "-".join(map(str, ordered_tones))
 81    
 82    def is_minor(self):
 83        minor_3rd_interval = 3
 84        return any((tone.position - self.keytone.position) % NUMBERS_OF_TONES == minor_3rd_interval for tone in self.tones)
 85
 86    def is_major(self):
 87        major_3rd_interval = 4  
 88        return any((tone.position - self.keytone.position) % NUMBERS_OF_TONES == major_3rd_interval for tone in self.tones)
 89
 90    def is_power_chord(self):
 91        return not (self.is_minor() or self.is_major())
 92    
 93    def __add__(self, other):
 94        if isinstance(other, Tone):
 95            new_chord = Chord(*self.tones, other)
 96            return new_chord
 97        elif isinstance(other, Chord):
 98            new_tones = self.other_tones_set | other.tones
 99            sorted_tones = sorted(new_tones, key=lambda tone: tone.position)
100            return Chord(self.keytone, *sorted_tones)
101
102    def __sub__(self, other):
103        if other.name not in  [tone.name for tone in self.tones]:
104            raise TypeError(f"Cannot remove tone {other} from chord {self}")
105
106        remaining_tones = [tone for tone in self.tones if tone.name != other.name]
107        return Chord(*remaining_tones)
108
109    def transposed(self, interval):
110        if not isinstance(interval, Interval):
111            raise TypeError("Interval expected for transposition")
112        
113        transported_tones = set()
114        for tone in self.tones:
115            transported_index = (UNIQUE_TONES.index(tone.name) + interval.semitones) % 12
116            transported_tones.add(Tone(UNIQUE_TONES[transported_index]))
117
118        transported_keytone_index = (UNIQUE_TONES.index(self.keytone.name) + interval.semitones) % 12
119        transported_keytone = Tone(UNIQUE_TONES[transported_keytone_index])
120
121        return Chord(transported_keytone, *transported_tones)

.....................FFFFF.F..F......
======================================================================
FAIL: test_add_tone_to_chord (test.TestOperations.test_add_tone_to_chord)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 254, in test_add_tone_to_chord
self.assertEqual(str(result_chord), "F-A-C-D")
AssertionError: 'A-C-D-F' != 'F-A-C-D'
- A-C-D-F
? --
+ F-A-C-D
? ++

======================================================================
FAIL: test_add_tone_to_chord_existing_tone (test.TestOperations.test_add_tone_to_chord_existing_tone)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 270, in test_add_tone_to_chord_existing_tone
self.assertEqual(str(result_chord), "F-G#-C")
AssertionError: 'C-F-G#' != 'F-G#-C'
- C-F-G#
+ F-G#-C

======================================================================
FAIL: test_add_tone_to_chord_order (test.TestOperations.test_add_tone_to_chord_order)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 261, in test_add_tone_to_chord_order
self.assertEqual(str(result_chord), "F-G-A-C")
AssertionError: 'A-C-F-G' != 'F-G-A-C'
- A-C-F-G
+ F-G-A-C

======================================================================
FAIL: test_interval_addition (test.TestOperations.test_interval_addition)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 240, in test_interval_addition
self.assertIsInstance(major_3rd, Interval)
AssertionError: 'major 3rd' is not an instance of <class 'solution.Interval'>

======================================================================
FAIL: test_interval_addition_overflow (test.TestOperations.test_interval_addition_overflow)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 246, in test_interval_addition_overflow
self.assertIsInstance(unison, Interval)
AssertionError: 'unison' is not an instance of <class 'solution.Interval'>

======================================================================
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: "unsupported operand type(s) for -: 'Interval' and 'Tone'" != 'Invalid operation'
- unsupported operand type(s) for -: 'Interval' and 'Tone'
+ Invalid operation

======================================================================
FAIL: test_subtract_tone_from_chord (test.TestOperations.test_subtract_tone_from_chord)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 277, in test_subtract_tone_from_chord
self.assertEqual(str(result_chord), "F-G#")
AssertionError: 'G#-F' != 'F-G#'
- G#-F
+ F-G#

----------------------------------------------------------------------
Ran 37 tests in 0.002s

FAILED (failures=7)

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