Домашни > Pitches love the D > Решения > Решението на Мариана Терзиева

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

10 точки общо

36 успешни теста
1 неуспешни теста
Код (С корекции по is_minor и is_major)
Скрий всички коментари

  1TONES_COUNT = 12
  2TONES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
  3
  4class Tone:
  5    """Musical tone"""
  6    def __init__(self, tone):
  7        self.tone = tone
  8        if tone == 'C':
  9            self.position = 0
 10        elif tone == 'C#':
 11            self.position = 1
 12        elif tone == 'D':
 13            self.position = 2
 14        elif tone == 'D#':
 15            self.position = 3
 16        elif tone == 'E':
 17            self.position = 4
 18        elif tone == 'F':
 19            self.position = 5
 20        elif tone == 'F#':
 21            self.position = 6
 22        elif tone == 'G':
 23            self.position = 7
 24        elif tone == 'G#':
 25            self.position = 8
 26        elif tone == 'A':
 27            self.position = 9
 28        elif tone == 'A#':
 29            self.position = 10
 30        elif tone == 'B':
 31            self.position = 11
 32
 33    def __str__(self):
 34        return str(self.tone)
 35
 36    def __eq__(self, other):
 37        return self.tone == other.tone
 38
 39    def __int__(self):
 40        return self.position
 41
 42    def __add__(self, other):
 43        if isinstance(other, Tone):
 44            return Chord(self, other)
 45        if isinstance(other, Interval):
 46            return Tone(TONES[(self.position + other.semitones) % TONES_COUNT])
 47        return Tone(self.tone)
 48
 49    def __sub__(self, other):
 50        if isinstance(other, Tone):
 51            if self.position < other.position:
 52                return Interval(self.position + TONES_COUNT - other.position)
 53            return Interval(self.position - other.position)
 54        if isinstance(other, Interval):
 55            if self.position < other.semitones:
 56                return Tone(TONES[TONES_COUNT + self.position - other.semitones])
 57            return Tone(TONES[self.position - other.semitones])
 58        return Tone(self.tone)
 59
 60
 61class Interval:
 62    """Musical interval, measured in semitones."""
 63    def __init__(self, semitones):
 64        self.semitones = semitones % 12
 65        self.is_negative = False # Chord.transposed function uses it
 66
 67        if self.semitones == 0:
 68            self.name = 'unison'
 69        elif self.semitones == 1:
 70            self.name = 'minor 2nd'
 71        elif self.semitones == 2:
 72            self.name = 'major 2nd'
 73        elif self.semitones == 3:
 74            self.name = 'minor 3rd'
 75        elif self.semitones == 4:
 76            self.name = 'major 3rd'
 77        elif self.semitones == 5:
 78            self.name = 'perfect 4th'
 79        elif self.semitones == 6:
 80            self.name = 'diminished 5th'
 81        elif self.semitones == 7:
 82            self.name = 'perfect 5th'
 83        elif self.semitones == 8:
 84            self.name = 'minor 6th'
 85        elif self.semitones == 9:
 86            self.name = 'major 6th'
 87        elif self.semitones == 10:
 88            self.name = 'minor 7th'
 89        elif self.semitones == 11:
 90            self.name = 'major 7th'
 91
 92    def __str__(self):
 93        return self.name
 94
 95    def __int__(self):
 96        return self.semitones
 97
 98    def __add__(self, other):
 99        if isinstance(other, Tone):
100            raise TypeError('Invalid operation')
101        return Interval(self.semitones + other.semitones)
102
103    def __sub__(self, other):
104        if isinstance(other, Tone):
105            raise TypeError('Invalid operation')
106
107    def __neg__(self):
108        self.is_negative = True
109        return self
110
111
112class Chord:
113    """Musical chord made up of 2 or more unique tones."""
114    def __init__(self, root_tone, *other_tones):
115        self.root_tone = root_tone
116        tones = {self.root_tone.tone : self.root_tone.position}
117        self.tones = [self.root_tone]
118
119        # remove duplicates
120        for tone in other_tones:
121            if tone.tone not in tones:
122                tones[tone.tone] = tone.position
123                self.tones.append(tone)
124
125        if self.tones.__len__() == 1:
126            raise TypeError('Cannot have a chord made of only 1 unique tone')
127
128        # order relative to root
129        tones = [self.root_tone]
130        position_list = list(map(int, self.tones))
131        for i in range(self.root_tone.position + 1, self.root_tone.position + TONES_COUNT):
132            if i % TONES_COUNT in position_list:
133                tones.append(self.tones[position_list.index(i % TONES_COUNT)])
134        self.tones = tones
135
136    def __str__(self):
137        return '-'.join(map(str, self.tones))
138
139    def is_minor(self):
140        """Return whether there are 3 semitones between the root 
141        and any other tone in the chord."""
142        for tone in self.tones:
143            if (tone is not self.root_tone
144                and self.root_tone + Interval(3) == tone):
145                return True
146        return False
147
148    def is_major(self):
149        """Return whether there are 4 semitones between the root 
150        and any other tone in the chord."""
151        for tone in self.tones:
152            if (tone is not self.root_tone
153                and self.root_tone + Interval(4) == tone):
154                return True
155        return False
156
157    def is_power_chord(self):
158        """Return whether chord is neither minor nor major."""
159        return not self.is_major() and not self.is_minor()
160
161    def __add__(self, other):
162        if isinstance(other, Tone):
163            tones = self.tones[:]
164            tones.append(other)
165            return Chord(*tones)
166        if isinstance(other, Chord):
167            tones = self.tones[:]
168            tones.extend(other.tones)
169            return Chord(*tones)
170        return Chord(*self.tones)
171
172    def __sub__(self, other):
173        if other in self.tones:
174            tones = self.tones[:]
175            tones.remove(other)
176            return Chord(*tones)
177        raise TypeError(f'Cannot remove tone {other} from chord {self}')
178
179    def transposed(self, interval):
180        """Subtract or add an interval to all of chord's tones."""
181        tones = [tone - interval if interval.is_negative
182                 else tone + interval for tone in self.tones]
183        return Chord(*tones)

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

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

FAILED (failures=1)

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

f1TONES_COUNT = 12f1TONES_COUNT = 12
2TONES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']2TONES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
33
4class Tone:4class Tone:
5    """Musical tone"""5    """Musical tone"""
6    def __init__(self, tone):6    def __init__(self, tone):
7        self.tone = tone7        self.tone = tone
8        if tone == 'C':8        if tone == 'C':
9            self.position = 09            self.position = 0
10        elif tone == 'C#':10        elif tone == 'C#':
11            self.position = 111            self.position = 1
12        elif tone == 'D':12        elif tone == 'D':
13            self.position = 213            self.position = 2
14        elif tone == 'D#':14        elif tone == 'D#':
15            self.position = 315            self.position = 3
16        elif tone == 'E':16        elif tone == 'E':
17            self.position = 417            self.position = 4
18        elif tone == 'F':18        elif tone == 'F':
19            self.position = 519            self.position = 5
20        elif tone == 'F#':20        elif tone == 'F#':
21            self.position = 621            self.position = 6
22        elif tone == 'G':22        elif tone == 'G':
23            self.position = 723            self.position = 7
24        elif tone == 'G#':24        elif tone == 'G#':
25            self.position = 825            self.position = 8
26        elif tone == 'A':26        elif tone == 'A':
27            self.position = 927            self.position = 9
28        elif tone == 'A#':28        elif tone == 'A#':
29            self.position = 1029            self.position = 10
30        elif tone == 'B':30        elif tone == 'B':
31            self.position = 1131            self.position = 11
3232
33    def __str__(self):33    def __str__(self):
34        return str(self.tone)34        return str(self.tone)
3535
36    def __eq__(self, other):36    def __eq__(self, other):
37        return self.tone == other.tone37        return self.tone == other.tone
3838
39    def __int__(self):39    def __int__(self):
40        return self.position40        return self.position
4141
42    def __add__(self, other):42    def __add__(self, other):
43        if isinstance(other, Tone):43        if isinstance(other, Tone):
44            return Chord(self, other)44            return Chord(self, other)
45        if isinstance(other, Interval):45        if isinstance(other, Interval):
46            return Tone(TONES[(self.position + other.semitones) % TONES_COUNT])46            return Tone(TONES[(self.position + other.semitones) % TONES_COUNT])
47        return Tone(self.tone)47        return Tone(self.tone)
4848
49    def __sub__(self, other):49    def __sub__(self, other):
50        if isinstance(other, Tone):50        if isinstance(other, Tone):
51            if self.position < other.position:51            if self.position < other.position:
52                return Interval(self.position + TONES_COUNT - other.position)52                return Interval(self.position + TONES_COUNT - other.position)
53            return Interval(self.position - other.position)53            return Interval(self.position - other.position)
54        if isinstance(other, Interval):54        if isinstance(other, Interval):
55            if self.position < other.semitones:55            if self.position < other.semitones:
56                return Tone(TONES[TONES_COUNT + self.position - other.semitones])56                return Tone(TONES[TONES_COUNT + self.position - other.semitones])
57            return Tone(TONES[self.position - other.semitones])57            return Tone(TONES[self.position - other.semitones])
58        return Tone(self.tone)58        return Tone(self.tone)
5959
6060
61class Interval:61class Interval:
62    """Musical interval, measured in semitones."""62    """Musical interval, measured in semitones."""
63    def __init__(self, semitones):63    def __init__(self, semitones):
64        self.semitones = semitones % 1264        self.semitones = semitones % 12
65        self.is_negative = False # Chord.transposed function uses it65        self.is_negative = False # Chord.transposed function uses it
6666
67        if self.semitones == 0:67        if self.semitones == 0:
68            self.name = 'unison'68            self.name = 'unison'
69        elif self.semitones == 1:69        elif self.semitones == 1:
70            self.name = 'minor 2nd'70            self.name = 'minor 2nd'
71        elif self.semitones == 2:71        elif self.semitones == 2:
72            self.name = 'major 2nd'72            self.name = 'major 2nd'
73        elif self.semitones == 3:73        elif self.semitones == 3:
74            self.name = 'minor 3rd'74            self.name = 'minor 3rd'
75        elif self.semitones == 4:75        elif self.semitones == 4:
76            self.name = 'major 3rd'76            self.name = 'major 3rd'
77        elif self.semitones == 5:77        elif self.semitones == 5:
78            self.name = 'perfect 4th'78            self.name = 'perfect 4th'
79        elif self.semitones == 6:79        elif self.semitones == 6:
80            self.name = 'diminished 5th'80            self.name = 'diminished 5th'
81        elif self.semitones == 7:81        elif self.semitones == 7:
82            self.name = 'perfect 5th'82            self.name = 'perfect 5th'
83        elif self.semitones == 8:83        elif self.semitones == 8:
84            self.name = 'minor 6th'84            self.name = 'minor 6th'
85        elif self.semitones == 9:85        elif self.semitones == 9:
86            self.name = 'major 6th'86            self.name = 'major 6th'
87        elif self.semitones == 10:87        elif self.semitones == 10:
88            self.name = 'minor 7th'88            self.name = 'minor 7th'
89        elif self.semitones == 11:89        elif self.semitones == 11:
90            self.name = 'major 7th'90            self.name = 'major 7th'
9191
92    def __str__(self):92    def __str__(self):
93        return self.name93        return self.name
9494
95    def __int__(self):95    def __int__(self):
96        return self.semitones96        return self.semitones
9797
98    def __add__(self, other):98    def __add__(self, other):
99        if isinstance(other, Tone):99        if isinstance(other, Tone):
100            raise TypeError('Invalid operation')100            raise TypeError('Invalid operation')
101        return Interval(self.semitones + other.semitones)101        return Interval(self.semitones + other.semitones)
102102
103    def __sub__(self, other):103    def __sub__(self, other):
104        if isinstance(other, Tone):104        if isinstance(other, Tone):
105            raise TypeError('Invalid operation')105            raise TypeError('Invalid operation')
106106
107    def __neg__(self):107    def __neg__(self):
108        self.is_negative = True108        self.is_negative = True
109        return self109        return self
110110
111111
112class Chord:112class Chord:
113    """Musical chord made up of 2 or more unique tones."""113    """Musical chord made up of 2 or more unique tones."""
114    def __init__(self, root_tone, *other_tones):114    def __init__(self, root_tone, *other_tones):
115        self.root_tone = root_tone115        self.root_tone = root_tone
116        tones = {self.root_tone.tone : self.root_tone.position}116        tones = {self.root_tone.tone : self.root_tone.position}
117        self.tones = [self.root_tone]117        self.tones = [self.root_tone]
118118
119        # remove duplicates119        # remove duplicates
120        for tone in other_tones:120        for tone in other_tones:
121            if tone.tone not in tones:121            if tone.tone not in tones:
122                tones[tone.tone] = tone.position122                tones[tone.tone] = tone.position
123                self.tones.append(tone)123                self.tones.append(tone)
124124
125        if self.tones.__len__() == 1:125        if self.tones.__len__() == 1:
126            raise TypeError('Cannot have a chord made of only 1 unique tone')126            raise TypeError('Cannot have a chord made of only 1 unique tone')
127127
128        # order relative to root128        # order relative to root
129        tones = [self.root_tone]129        tones = [self.root_tone]
130        position_list = list(map(int, self.tones))130        position_list = list(map(int, self.tones))
131        for i in range(self.root_tone.position + 1, self.root_tone.position + TONES_COUNT):131        for i in range(self.root_tone.position + 1, self.root_tone.position + TONES_COUNT):
132            if i % TONES_COUNT in position_list:132            if i % TONES_COUNT in position_list:
133                tones.append(self.tones[position_list.index(i % TONES_COUNT)])133                tones.append(self.tones[position_list.index(i % TONES_COUNT)])
134        self.tones = tones134        self.tones = tones
135135
136    def __str__(self):136    def __str__(self):
137        return '-'.join(map(str, self.tones))137        return '-'.join(map(str, self.tones))
138138
139    def is_minor(self):139    def is_minor(self):
140        """Return whether there are 3 semitones between the root 140        """Return whether there are 3 semitones between the root 
141        and any other tone in the chord."""141        and any other tone in the chord."""
142        for tone in self.tones:142        for tone in self.tones:
143            if (tone is not self.root_tone143            if (tone is not self.root_tone
n144                and abs(self.root_tone.position - tone.position) == 3):n144                and self.root_tone + Interval(3) == tone):
145                return True145                return True
146        return False146        return False
147147
148    def is_major(self):148    def is_major(self):
149        """Return whether there are 4 semitones between the root 149        """Return whether there are 4 semitones between the root 
150        and any other tone in the chord."""150        and any other tone in the chord."""
151        for tone in self.tones:151        for tone in self.tones:
152            if (tone is not self.root_tone152            if (tone is not self.root_tone
t153                and abs(self.root_tone.position - tone.position) == 4):t153                and self.root_tone + Interval(4) == tone):
154                return True154                return True
155        return False155        return False
156156
157    def is_power_chord(self):157    def is_power_chord(self):
158        """Return whether chord is neither minor nor major."""158        """Return whether chord is neither minor nor major."""
159        return not self.is_major() and not self.is_minor()159        return not self.is_major() and not self.is_minor()
160160
161    def __add__(self, other):161    def __add__(self, other):
162        if isinstance(other, Tone):162        if isinstance(other, Tone):
163            tones = self.tones[:]163            tones = self.tones[:]
164            tones.append(other)164            tones.append(other)
165            return Chord(*tones)165            return Chord(*tones)
166        if isinstance(other, Chord):166        if isinstance(other, Chord):
167            tones = self.tones[:]167            tones = self.tones[:]
168            tones.extend(other.tones)168            tones.extend(other.tones)
169            return Chord(*tones)169            return Chord(*tones)
170        return Chord(*self.tones)170        return Chord(*self.tones)
171171
172    def __sub__(self, other):172    def __sub__(self, other):
173        if other in self.tones:173        if other in self.tones:
174            tones = self.tones[:]174            tones = self.tones[:]
175            tones.remove(other)175            tones.remove(other)
176            return Chord(*tones)176            return Chord(*tones)
177        raise TypeError(f'Cannot remove tone {other} from chord {self}')177        raise TypeError(f'Cannot remove tone {other} from chord {self}')
178178
179    def transposed(self, interval):179    def transposed(self, interval):
180        """Subtract or add an interval to all of chord's tones."""180        """Subtract or add an interval to all of chord's tones."""
181        tones = [tone - interval if interval.is_negative181        tones = [tone - interval if interval.is_negative
182                 else tone + interval for tone in self.tones]182                 else tone + interval for tone in self.tones]
183        return Chord(*tones)183        return Chord(*tones)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op