Домашни > Pitches love the D > Решения > Решението на Цветелина Гоцова

Резултати
7 точки от тестове
-7 точки от учител

0 точки общо

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

  1class Tone:
  2    CHROMATIC_SCALE = [ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ]
  3    
  4    def __init__(self, name):
  5        self.name = name
  6
  7    def __str__(self):
  8        return self.name
  9    
 10    def __eq__(self, other):
 11        if isinstance(other, Tone):
 12            return self.name == other.name
 13        return False
 14
 15    def __add__(self, other):
 16        if isinstance(other, Tone):
 17            return Chord(self, other)
 18        if isinstance(other, Interval):
 19            new_index = (self._get_chromatic_index() + other.number_of_semitones) % 12
 20            return Tone(Tone.CHROMATIC_SCALE[new_index])
 21        else:
 22            raise TypeError("Invalid operation")
 23        
 24    def __sub__(self, other):
 25        if isinstance(other, Tone):
 26            semitone_diff = (self._get_chromatic_index() - other._get_chromatic_index()) % 12
 27            return Interval(semitone_diff)
 28        if isinstance(other, Interval):
 29            new_index = (self._get_chromatic_index() - other.number_of_semitones) % 12
 30            return Tone(Tone.CHROMATIC_SCALE[new_index])
 31        else:
 32            raise TypeError("Invalid operation")
 33
 34    def _get_chromatic_index(self):
 35        return Tone.CHROMATIC_SCALE.index(self.name)
 36
 37class Interval:
 38    INTERVAL_NAMES = {0: "unison", 1: "minor 2nd", 2: "major 2nd", 3: "minor 3rd", 4: "major 3rd", 5: "perfect 4th", 6: "diminished 5th", 7: "perfect 5th", 8: "minor 6th", 9: "major 6th", 10: "minor 7th", 11: "major 7th"}
 39
 40    def __init__(self, number_of_semitones):
 41        self.number_of_semitones = number_of_semitones % 12
 42
 43    def __str__(self):
 44        return self.INTERVAL_NAMES.get(self.number_of_semitones, "unknown interval")
 45
 46    def __add__(self, other):
 47        if isinstance(other, Interval):
 48            new_semitones = (self.number_of_semitones + other.number_of_semitones) % 12
 49            return Interval(new_semitones)
 50        else:
 51            raise TypeError("Invalid operation")
 52
 53class Chord:
 54    def __init__(self, root_tone, *tones):
 55        if not isinstance(root_tone, Tone):
 56            raise TypeError("The root tone must be an instance of class Tone")
 57        self.root_tone = root_tone
 58        unique_tones  = []
 59        unique_tone_names = set()
 60        for tone in (root_tone, *tones):
 61            if isinstance(tone, Tone) and tone.name not in unique_tone_names:
 62                unique_tones.append(tone)
 63                unique_tone_names.add(tone.name)
 64        if len(unique_tones) < 2:
 65            raise TypeError("Cannot have a chord made of only 1 unique tone")
 66        self.tones = unique_tones
 67    
 68    def is_minor(self):
 69        root_index = self.root_tone._get_chromatic_index()
 70        for tone in self.tones:
 71            if tone != self.root_tone:
 72                interval_semitones = (tone._get_chromatic_index() - root_index) % 12
 73                if interval_semitones == 3:
 74                    return True
 75        return False
 76    
 77    def is_major(self):
 78        root_index = self.root_tone._get_chromatic_index()
 79        for tone in self.tones:
 80            if tone != self.root_tone:
 81                interval_semitones = (tone._get_chromatic_index() - root_index) % 12
 82                if interval_semitones == 4:
 83                    return True
 84        return False
 85    
 86    def is_power_chord(self):
 87        root_index = self.root_tone._get_chromatic_index()
 88        for tone in self.tones:
 89            if tone != self.root_tone:
 90                interval_semitones = (tone._get_chromatic_index() - root_index) % 12
 91                if interval_semitones != 3 and interval_semitones != 4:
 92                    return True
 93        return False
 94    
 95    def __add__(self, other):
 96        if isinstance(other, Tone):
 97            if other not in self.tones:
 98                new_chord = Chord(self.root_tone, *self.tones, other)
 99                return new_chord
100            else:
101                return self
102        if isinstance(other, Chord):
103            combined_tones = list(self.tones) + list(other.tones)
104            return Chord(self.root_tone, *combined_tones)
105        else:
106            raise TypeError("Invalid operation")
107    
108    def __sub__(self, other):
109        if isinstance(other, Tone):
110            if other not in self.tones:
111                raise TypeError(f"Cannot remove tone {other} from chord {self}")
112            new_tones = [tone for tone in self.tones if tone != other]
113            if len(new_tones) < 2:
114                raise TypeError("Cannot have a chord made of only 1 unique tone")
115            return Chord(self.root_tone, *new_tones)
116        else:
117            raise TypeError("Invalid operation")
118
119    def __str__(self):
120        sorted_tones = sorted(self.tones, key=lambda tone: tone._get_chromatic_index())
121        return '-'.join(str(tone) for tone in sorted_tones)
122    
123    def transposed(self, interval):
124        if isinstance(interval, Interval):
125            transposed_tones = []
126            for tone in self.tones:
127                transposed_tone = tone + interval
128                transposed_tones.append(transposed_tone)
129            return Chord(transposed_tones[0], *transposed_tones)
130        else:
131            raise TypeError("Invalid operation")

.FFF..F.EEFE.........FFF...F.........
======================================================================
ERROR: test_transposed_negative (test.TestBasicChordFunctionality.test_transposed_negative)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 136, in test_transposed_negative
result_chord = e_minor_chord.transposed(-Interval(2))
^^^^^^^^^^^^
TypeError: bad operand type for unary -: 'Interval'

======================================================================
ERROR: test_transposed_negative_overflow (test.TestBasicChordFunctionality.test_transposed_negative_overflow)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 150, in test_transposed_negative_overflow
result_chord = e_minor_chord.transposed(-Interval(8))
^^^^^^^^^^^^
TypeError: bad operand type for unary -: 'Interval'

======================================================================
ERROR: test_interval_negative (test.TestBasicIntervalFunctionality.test_interval_negative)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 50, in test_interval_negative
minor_2nd = -major_7th
^^^^^^^^^^
TypeError: bad operand type for unary -: 'Interval'

======================================================================
FAIL: test_chord_ordering (test.TestBasicChordFunctionality.test_chord_ordering)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 65, in test_chord_ordering
self.assertEqual(str(f_sixth_ninth_chord), "F-A-C-E")
AssertionError: 'C-E-F-A' != 'F-A-C-E'
- C-E-F-A
+ F-A-C-E

======================================================================
FAIL: test_chord_str (test.TestBasicChordFunctionality.test_chord_str)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 60, in test_chord_str
self.assertEqual(str(a_major_chord), "A-C#-E")
AssertionError: 'C#-E-A' != 'A-C#-E'
- C#-E-A
+ A-C#-E

======================================================================
FAIL: test_chord_tone_repetition (test.TestBasicChordFunctionality.test_chord_tone_repetition)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 74, in test_chord_tone_repetition
self.assertEqual(str(a_minor_chord), "A-C-E")
AssertionError: 'C-E-A' != 'A-C-E'
- C-E-A
+ A-C-E

======================================================================
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_transposed_overflow (test.TestBasicChordFunctionality.test_transposed_overflow)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 145, in test_transposed_overflow
self.assertEqual(str(result_chord), "A#-D-F")
AssertionError: 'D-F-A#' != 'A#-D-F'
- D-F-A#
+ A#-D-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: 'C-D-F-A' != 'F-A-C-D'
- C-D-F-A
+ 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: 'C-F-G-A' != 'F-G-A-C'
- C-F-G-A
? --
+ F-G-A-C
? ++

======================================================================
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

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

FAILED (failures=9, errors=3)

Дискусия
Георги Кунчев
06.11.2024 20:23

Решението е предадено след крайния срок. Качено е от мен, ръчно, за да дадем обратна връзка, но не получава точки.
История
Това решение има само една версия.