Домашни > Pitches love the D > Решения > Решението на Енисел Кунч

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

7 точки общо

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

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

F..F..F.EE.E....F.....F....F.....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_not_enough_tones (test.TestBasicChordFunctionality.test_chord_not_enough_tones)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 83, in test_chord_not_enough_tones
with self.assertRaises(TypeError) as err:
AssertionError: TypeError not raised

======================================================================
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: 'A-A-A-A-A-A-A-C-C-C-C-C-C-C-C-C-C-C-C-C-C-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E' != 'A-C-E'
- A-A-A-A-A-A-A-C-C-C-C-C-C-C-C-C-C-C-C-C-C-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E
+ A-C-E

======================================================================
FAIL: test_is_power_chord (test.TestBasicChordFunctionality.test_is_power_chord)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 124, in test_is_power_chord
self.assertTrue(a_kind_of_power_chord.is_power_chord())
AssertionError: False is not true

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

======================================================================
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: 'F-F-G#-G#-C-C' != 'F-G#-C'
- F-F-G#-G#-C-C
+ F-G#-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

======================================================================
FAIL: test_tone_addition_same_tone (test.TestOperations.test_tone_addition_same_tone)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 166, in test_tone_addition_same_tone
with self.assertRaises(TypeError) as err:
AssertionError: TypeError not raised

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

FAILED (failures=7, errors=3)

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

f1class Tone:f1class Tone:
2    tones = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]2    tones = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
33
4    def __init__(self, name):4    def __init__(self, name):
5        self.name = name5        self.name = name
66
7    def __str__(self):7    def __str__(self):
8        return self.name8        return self.name
99
10    def __add__(self, other):10    def __add__(self, other):
11        if isinstance(other, Tone):11        if isinstance(other, Tone):
12            return Chord(self, other)12            return Chord(self, other)
13        elif isinstance(other, Interval):13        elif isinstance(other, Interval):
14            curr_index = (Tone.tones.index(self.name) + other.semitones) % 1214            curr_index = (Tone.tones.index(self.name) + other.semitones) % 12
15            return Tone(Tone.tones[curr_index])15            return Tone(Tone.tones[curr_index])
16        16        
17    def __sub__(self, other):17    def __sub__(self, other):
18        if isinstance(other, Tone):18        if isinstance(other, Tone):
19            distance = (Tone.tones.index(self.name) - Tone.tones.index(other.name)) % 1219            distance = (Tone.tones.index(self.name) - Tone.tones.index(other.name)) % 12
20            return Interval(distance)20            return Interval(distance)
21        21        
22        elif isinstance(other, Interval):22        elif isinstance(other, Interval):
23            curr_index = (Tone.tones.index(self.name) - other.semitones) % 1223            curr_index = (Tone.tones.index(self.name) - other.semitones) % 12
24            return Tone(Tone.tones[curr_index])24            return Tone(Tone.tones[curr_index])
2525
2626
27class Interval:27class Interval:
28    INTERVAL_NAMES = {28    INTERVAL_NAMES = {
29        0: "unison", 1: "minor 2nd", 2: "major 2nd", 3: "minor 3rd",29        0: "unison", 1: "minor 2nd", 2: "major 2nd", 3: "minor 3rd",
30        4: "major 3rd", 5: "perfect 4th", 6: "diminished 5th",30        4: "major 3rd", 5: "perfect 4th", 6: "diminished 5th",
31        7: "perfect 5th", 8: "minor 6th", 9: "major 6th",31        7: "perfect 5th", 8: "minor 6th", 9: "major 6th",
32        10: "minor 7th", 11: "major 7th"32        10: "minor 7th", 11: "major 7th"
33    }33    }
3434
35    def __init__(self, semitones):35    def __init__(self, semitones):
36        self.semitones = semitones % 1236        self.semitones = semitones % 12
3737
38    def __str__(self):38    def __str__(self):
39        return self.INTERVAL_NAMES[self.semitones]39        return self.INTERVAL_NAMES[self.semitones]
4040
41    def __add__(self, other):41    def __add__(self, other):
42        if isinstance(other, Interval):42        if isinstance(other, Interval):
43            new_semitones = (self.semitones + other.semitones) % 1243            new_semitones = (self.semitones + other.semitones) % 12
44            return Interval(new_semitones)44            return Interval(new_semitones)
45        else:45        else:
46            raise TypeError("Invalid operation")46            raise TypeError("Invalid operation")
n47    n47 
48 
48class Chord:49class Chord:
49    def __init__(self, root_tone, *tones):50    def __init__(self, root_tone, *tones):
50        unique_tones = {root_tone, *tones}51        unique_tones = {root_tone, *tones}
5152
52        if len(unique_tones) < 2:53        if len(unique_tones) < 2:
53            raise TypeError("Cannot have a chord made of only 1 unique tone")54            raise TypeError("Cannot have a chord made of only 1 unique tone")
54        55        
55        self.root_tone = root_tone56        self.root_tone = root_tone
56        self.tones = unique_tones57        self.tones = unique_tones
5758
58        start_index = Tone.tones.index(root_tone.name)59        start_index = Tone.tones.index(root_tone.name)
59        sorted_tones = sorted(unique_tones, key=lambda t: (Tone.tones * 2).index(t.name, start_index))60        sorted_tones = sorted(unique_tones, key=lambda t: (Tone.tones * 2).index(t.name, start_index))
60        61        
61        self.tones = [Tone(t.name) for t in sorted_tones]62        self.tones = [Tone(t.name) for t in sorted_tones]
6263
63    def __str__(self):64    def __str__(self):
64        return "-".join(str(tone) for tone in self.tones)65        return "-".join(str(tone) for tone in self.tones)
65    66    
66    #Find distance between two tones67    #Find distance between two tones
67    def semitone_distance(self, tone1, tone2):68    def semitone_distance(self, tone1, tone2):
68        return (Tone.tones.index(tone2.name) - Tone.tones.index(tone1.name)) % 1269        return (Tone.tones.index(tone2.name) - Tone.tones.index(tone1.name)) % 12
69    70    
70    def is_minor(self):71    def is_minor(self):
71        for tone in self.tones:72        for tone in self.tones:
72            if tone != self.root_tone:73            if tone != self.root_tone:
73                distance = self.semitone_distance(self.root_tone, tone)74                distance = self.semitone_distance(self.root_tone, tone)
74                if Interval (distance).__str__() == "minor 3rd":75                if Interval (distance).__str__() == "minor 3rd":
75                    return True76                    return True
76        return False77        return False
77    78    
78    def is_major(self):79    def is_major(self):
79        for tone in self.tones:80        for tone in self.tones:
80            if tone != self.root_tone:81            if tone != self.root_tone:
81                distance = self.semitone_distance(self.root_tone, tone)82                distance = self.semitone_distance(self.root_tone, tone)
82                if Interval(distance).__str__() == "major 3rd":83                if Interval(distance).__str__() == "major 3rd":
83                    return True84                    return True
84        return False85        return False
85    86    
86    def is_power_chord(self):87    def is_power_chord(self):
87        if not self.is_major and not self.is_minor:88        if not self.is_major and not self.is_minor:
88            return True89            return True
89        return False 90        return False 
9091
91    def __sub__(self, other):92    def __sub__(self, other):
92        if isinstance(other, Tone):93        if isinstance(other, Tone):
n93            # if other not in self.tones:n94            if other.name not in [tone.name for tone in self.tones]:
94            #     raise TypeError(f"Cannot remove tone {other} from chord {self}")95                raise TypeError(f"Cannot remove tone {other} from chord {self}")
95           
96            # Проверка дали тонът съществува в акорда
97                if other.name not in [tone.name for tone in self.tones]:
98                    raise TypeError(f"Cannot remove tone {other} from chord {self}")
99            96            
n100        n
101        new_tones = [tone for tone in self.tones if tone.name != other.name]97        new_tones = [tone for tone in self.tones if tone.name != other.name]
10298
103        if len(new_tones) == 1:99        if len(new_tones) == 1:
104            raise TypeError("Cannot have a chord made of only 1 unique tone")100            raise TypeError("Cannot have a chord made of only 1 unique tone")
105        101        
106        new_root_tone = new_tones[0]102        new_root_tone = new_tones[0]
107103
108        return Chord(new_root_tone, *new_tones)104        return Chord(new_root_tone, *new_tones)
109    105    
110    def __add__(self, other):106    def __add__(self, other):
111        if isinstance(other, Chord):107        if isinstance(other, Chord):
112            combined_tones = list(self.tones)  108            combined_tones = list(self.tones)  
113            for tone in other.tones:109            for tone in other.tones:
114                if tone not in combined_tones:110                if tone not in combined_tones:
115                    combined_tones.append(tone)  111                    combined_tones.append(tone)  
116            new_root_tone = combined_tones[0]112            new_root_tone = combined_tones[0]
117            unique_tones = []113            unique_tones = []
118            for tone in combined_tones:114            for tone in combined_tones:
119                if tone not in unique_tones:115                if tone not in unique_tones:
120                    unique_tones.append(tone)116                    unique_tones.append(tone)
121            return Chord(new_root_tone, *unique_tones)117            return Chord(new_root_tone, *unique_tones)
122        elif isinstance(other, Tone):118        elif isinstance(other, Tone):
123            combined_tones = list(self.tones)119            combined_tones = list(self.tones)
124            if other not in combined_tones:120            if other not in combined_tones:
125                combined_tones.append(other)121                combined_tones.append(other)
126            new_root_tone = combined_tones[0]122            new_root_tone = combined_tones[0]
127            return Chord(new_root_tone, *combined_tones)123            return Chord(new_root_tone, *combined_tones)
128    124    
129    def transposed(self, interval):125    def transposed(self, interval):
130        if not isinstance(interval, Interval):126        if not isinstance(interval, Interval):
131            raise TypeError("Interval is expected")127            raise TypeError("Interval is expected")
132128
133        transposed_tones = [129        transposed_tones = [
134            Tone(Tone.tones[(Tone.tones.index(tone.name) + interval.semitones) % 12])130            Tone(Tone.tones[(Tone.tones.index(tone.name) + interval.semitones) % 12])
135            for tone in self.tones131            for tone in self.tones
136        ]132        ]
137        return Chord(transposed_tones[0], *transposed_tones[1:])133        return Chord(transposed_tones[0], *transposed_tones[1:])
t138 t
139        
140# c_minor_chord = Chord(Tone("C"), Tone("D#"), Tone("G"))
141# print(str(c_minor_chord))  # "C-D#-G"
142 
143# d_minor_chord = c_minor_chord.transposed(Interval(2))
144# print(str(d_minor_chord))  # "D-F-A"
145 
146# a_sharp_minor_chord = d_minor_chord.transposed(Interval(-4))
147# print(str(a_sharp_minor_chord))  # "A#-C#-F"
148 
149# c_major_chord = Chord(Tone("C"), Tone("E"), Tone("G"))
150# result_chord = c_major_chord - Tone("E")
151# print(result_chord)
152 
153# c_power_chord = Chord(Tone("C"), Tone("G"))
154# result_chord = c_power_chord - Tone("G")
155 
156# c_major_chord = Chord(Tone("C"), Tone("E"), Tone("G"))
157# result_chord = c_major_chord - Tone("E")
158# print(result_chord)
159c_major_chord = Chord(Tone("C"), Tone("E"), Tone("G"))
160result_chord = c_major_chord - Tone("E")
161print(result_chord)
162 
163    
164 
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op