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

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

10 точки общо

37 успешни теста
0 неуспешни теста
Код

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

.....................................
----------------------------------------------------------------------
Ran 37 tests in 0.001s

OK

Дискусия
Виктор Бечев
04.11.2024 14:15

Изцяло стилистично е - имаш 2 интервала след `if`-а, липсва ти интервал преди `==`, имаш един интервал преди `:`. За `is_minor / is_major` функциите - за minor / major 3rd интервал интерпретираме само ако е в посока "нагоре". П.П. От теоретична гледна точка - иначе бихме имали инверсии на акордите. П.П.П. Друг път като не си сигурна - ако след 2-3 прочита пак не е ясно - питай ни овреме, защото иначе разчиташ на късмета да си го имплементирала правилно, тъй като рядко поправяме хората по отношение на имплементацията (обратната ни връзка цели подобряване на стила и запознаване с идиомите и похватите в Python, както и някои абстрактни концепции, а не да откриваме бъгове в кода и да ви ги споменаваме). П.П.П.П. Ако има нещо друго неясно по условието - сега е моментът.
Вяра Тодорова
04.11.2024 13:50

Относно 91 ред визираш, че съм пропуснала един интервал или че интервалите за проверката не са точни? Тъй като се чудех за is_major и is_minor дали трябва да връща True ако разликата е съответно 4 и 3 без значение в коя посока е тонът спрямо корена или само ако е по часовниковата стрелка?
История

f1ALL_VALID_TONES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")f1ALL_VALID_TONES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
2ALL_VALID_INTERVALS = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"]2ALL_VALID_INTERVALS = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"]
3NUMBER_OF_INTERVALS = 123NUMBER_OF_INTERVALS = 12
4NUMBER_FOR_MINOR_3RD = 34NUMBER_FOR_MINOR_3RD = 3
5NUMBER_FOR_MAJOR_3RD = 45NUMBER_FOR_MAJOR_3RD = 4
66
7class Tone:7class Tone:
8    def __init__(self, tone):8    def __init__(self, tone):
9        if tone in ALL_VALID_TONES:9        if tone in ALL_VALID_TONES:
10            self.name = tone10            self.name = tone
11            self.index = ALL_VALID_TONES.index(tone)11            self.index = ALL_VALID_TONES.index(tone)
12        else:12        else:
13            raise Exception("Invalid input.")13            raise Exception("Invalid input.")
1414
15    def __str__(self):15    def __str__(self):
16        return self.name16        return self.name
1717
18    def __add__(self, other):18    def __add__(self, other):
19        if isinstance(other, Tone):19        if isinstance(other, Tone):
20            return Chord(self, other)20            return Chord(self, other)
21        elif isinstance(other, Interval):21        elif isinstance(other, Interval):
22            index_of_new_tone = (self.index + other.interval_number) % 1222            index_of_new_tone = (self.index + other.interval_number) % 12
23            return Tone(ALL_VALID_TONES[index_of_new_tone])23            return Tone(ALL_VALID_TONES[index_of_new_tone])
2424
25    def __sub__(self, other):25    def __sub__(self, other):
26        if isinstance(other, Tone):26        if isinstance(other, Tone):
27            index_of_first_tone = self.index27            index_of_first_tone = self.index
28            index_of_second_tone = other.index28            index_of_second_tone = other.index
29            return Interval(index_of_first_tone - index_of_second_tone)29            return Interval(index_of_first_tone - index_of_second_tone)
30        elif isinstance(other, Interval):30        elif isinstance(other, Interval):
31            index_of_new_tone = self.index - other.interval_number31            index_of_new_tone = self.index - other.interval_number
32            return Tone(ALL_VALID_TONES[index_of_new_tone])32            return Tone(ALL_VALID_TONES[index_of_new_tone])
3333
3434
35class Interval:35class Interval:
36    def __init__(self, number):36    def __init__(self, number):
37        number %= NUMBER_OF_INTERVALS37        number %= NUMBER_OF_INTERVALS
38        self.interval_number = number38        self.interval_number = number
39        self.interval_name = ALL_VALID_INTERVALS[number]39        self.interval_name = ALL_VALID_INTERVALS[number]
4040
41    def __str__(self):41    def __str__(self):
42        return self.interval_name42        return self.interval_name
4343
44    def __add__(self, other):44    def __add__(self, other):
45        if isinstance(other, Tone):45        if isinstance(other, Tone):
46            raise TypeError("Invalid operation")46            raise TypeError("Invalid operation")
47        elif isinstance(other, Interval):47        elif isinstance(other, Interval):
48            return Interval(self.interval_number + other.interval_number)48            return Interval(self.interval_number + other.interval_number)
4949
50    def __sub__(self, other):50    def __sub__(self, other):
51        if isinstance(other, Tone):51        if isinstance(other, Tone):
52            raise TypeError("Invalid operation")52            raise TypeError("Invalid operation")
5353
54    def __neg__(self):54    def __neg__(self):
55        return Interval(-self.interval_number)55        return Interval(-self.interval_number)
5656
5757
58class Chord:58class Chord:
59    def __init__(self, root, *args):59    def __init__(self, root, *args):
60        self.unique_tone_names = {root.name}60        self.unique_tone_names = {root.name}
61        self.tones = [root]61        self.tones = [root]
62        self.root = root62        self.root = root
63        for tone in args:63        for tone in args:
64            if tone.name not in self.unique_tone_names:64            if tone.name not in self.unique_tone_names:
65                self.tones.append(tone)65                self.tones.append(tone)
66                self.unique_tone_names.add(tone.name)66                self.unique_tone_names.add(tone.name)
67        if len(self.tones) == 1:67        if len(self.tones) == 1:
68            raise TypeError("Cannot have a chord made of only 1 unique tone")68            raise TypeError("Cannot have a chord made of only 1 unique tone")
69        root_num = ALL_VALID_TONES.index(str(root))69        root_num = ALL_VALID_TONES.index(str(root))
70        self.sorted_tones = sorted(self.tones, key= lambda tone: (ALL_VALID_TONES.index(str(tone)) - root_num) % 12)70        self.sorted_tones = sorted(self.tones, key= lambda tone: (ALL_VALID_TONES.index(str(tone)) - root_num) % 12)
7171
72    def __str__(self):72    def __str__(self):
73        return "-".join(str(tone) for tone in self.sorted_tones)73        return "-".join(str(tone) for tone in self.sorted_tones)
7474
75    def is_minor(self):75    def is_minor(self):
76        for tone in self.sorted_tones:76        for tone in self.sorted_tones:
77            difference = ALL_VALID_TONES.index((str(tone))) - ALL_VALID_TONES.index((str(self.root)))77            difference = ALL_VALID_TONES.index((str(tone))) - ALL_VALID_TONES.index((str(self.root)))
78            if difference < 0:78            if difference < 0:
79                difference += NUMBER_OF_INTERVALS79                difference += NUMBER_OF_INTERVALS
80            if difference == NUMBER_FOR_MINOR_3RD:80            if difference == NUMBER_FOR_MINOR_3RD:
n81                return "True"n81                return True
82        return "False"82        return False
8383
84    def is_major(self):84    def is_major(self):
85        for tone in self.sorted_tones:85        for tone in self.sorted_tones:
86            difference = ALL_VALID_TONES.index((str(tone))) - ALL_VALID_TONES.index((str(self.root)))86            difference = ALL_VALID_TONES.index((str(tone))) - ALL_VALID_TONES.index((str(self.root)))
87            if difference < 0:87            if difference < 0:
88                difference += NUMBER_OF_INTERVALS88                difference += NUMBER_OF_INTERVALS
89            if difference == NUMBER_FOR_MAJOR_3RD:89            if difference == NUMBER_FOR_MAJOR_3RD:
n90                return "True"n90                return True
91        return "False"91        return False
9292
93    def is_power_chord(self):93    def is_power_chord(self):
n94        if self.is_minor() == "True" or self.is_major() == "True":n94        if self.is_minor() == True or self.is_major() == True:
95            return "False"95            return False
96        return "True"96        return True
9797
98    def __add__(self, other):98    def __add__(self, other):
99        if isinstance(other, Tone):99        if isinstance(other, Tone):
100            return Chord(*self.tones, other)100            return Chord(*self.tones, other)
101        if isinstance(other, Chord):101        if isinstance(other, Chord):
102            tones_for_new_chord = self.sorted_tones102            tones_for_new_chord = self.sorted_tones
103            for tone in other.sorted_tones:103            for tone in other.sorted_tones:
104                if not tone in tones_for_new_chord:104                if not tone in tones_for_new_chord:
105                    tones_for_new_chord.append(tone)105                    tones_for_new_chord.append(tone)
106            return Chord(*tones_for_new_chord)106            return Chord(*tones_for_new_chord)
107107
108    def __sub__(self, other):108    def __sub__(self, other):
109        if isinstance(other, Tone):109        if isinstance(other, Tone):
110            if other.name not in self.unique_tone_names:110            if other.name not in self.unique_tone_names:
111                raise TypeError(f"Cannot remove tone {other.name} from chord {str(self)}")111                raise TypeError(f"Cannot remove tone {other.name} from chord {str(self)}")
112            elif len(self.sorted_tones) - 1 == 1:112            elif len(self.sorted_tones) - 1 == 1:
113                raise TypeError("Cannot have a chord made of only 1 unique tone")113                raise TypeError("Cannot have a chord made of only 1 unique tone")
114            else:114            else:
115                tones_for_new_chord = list()115                tones_for_new_chord = list()
116                for tone in self.sorted_tones:116                for tone in self.sorted_tones:
117                    if not tone.name == other.name:117                    if not tone.name == other.name:
118                        tones_for_new_chord.append(tone)118                        tones_for_new_chord.append(tone)
119                return Chord(*tones_for_new_chord)119                return Chord(*tones_for_new_chord)
120120
121    def transposed(self, interval):121    def transposed(self, interval):
122        tones_in_new_chord = list()122        tones_in_new_chord = list()
123        if interval.interval_number >= 0:123        if interval.interval_number >= 0:
124            for tone in self.sorted_tones:124            for tone in self.sorted_tones:
125                tones_in_new_chord.append(tone + interval)125                tones_in_new_chord.append(tone + interval)
126            return Chord(*tones_in_new_chord)126            return Chord(*tones_in_new_chord)
127        else:127        else:
128            for tone in self.sorted_tones:128            for tone in self.sorted_tones:
129                tones_in_new_chord.append(tone - interval)129                tones_in_new_chord.append(tone - interval)
130            return Chord(*tones_in_new_chord)130            return Chord(*tones_in_new_chord)
tt131 
132 
133 
134 
135 
136 
137 
138 
139 
140 
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1ALL_VALID_TONES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")f1ALL_VALID_TONES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
2ALL_VALID_INTERVALS = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"]2ALL_VALID_INTERVALS = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"]
3NUMBER_OF_INTERVALS = 123NUMBER_OF_INTERVALS = 12
4NUMBER_FOR_MINOR_3RD = 34NUMBER_FOR_MINOR_3RD = 3
5NUMBER_FOR_MAJOR_3RD = 45NUMBER_FOR_MAJOR_3RD = 4
66
7class Tone:7class Tone:
8    def __init__(self, tone):8    def __init__(self, tone):
9        if tone in ALL_VALID_TONES:9        if tone in ALL_VALID_TONES:
10            self.name = tone10            self.name = tone
11            self.index = ALL_VALID_TONES.index(tone)11            self.index = ALL_VALID_TONES.index(tone)
12        else:12        else:
13            raise Exception("Invalid input.")13            raise Exception("Invalid input.")
1414
15    def __str__(self):15    def __str__(self):
16        return self.name16        return self.name
1717
18    def __add__(self, other):18    def __add__(self, other):
19        if isinstance(other, Tone):19        if isinstance(other, Tone):
20            return Chord(self, other)20            return Chord(self, other)
21        elif isinstance(other, Interval):21        elif isinstance(other, Interval):
22            index_of_new_tone = (self.index + other.interval_number) % 1222            index_of_new_tone = (self.index + other.interval_number) % 12
23            return Tone(ALL_VALID_TONES[index_of_new_tone])23            return Tone(ALL_VALID_TONES[index_of_new_tone])
2424
25    def __sub__(self, other):25    def __sub__(self, other):
26        if isinstance(other, Tone):26        if isinstance(other, Tone):
27            index_of_first_tone = self.index27            index_of_first_tone = self.index
28            index_of_second_tone = other.index28            index_of_second_tone = other.index
29            return Interval(index_of_first_tone - index_of_second_tone)29            return Interval(index_of_first_tone - index_of_second_tone)
30        elif isinstance(other, Interval):30        elif isinstance(other, Interval):
31            index_of_new_tone = self.index - other.interval_number31            index_of_new_tone = self.index - other.interval_number
32            return Tone(ALL_VALID_TONES[index_of_new_tone])32            return Tone(ALL_VALID_TONES[index_of_new_tone])
3333
3434
35class Interval:35class Interval:
36    def __init__(self, number):36    def __init__(self, number):
37        number %= NUMBER_OF_INTERVALS37        number %= NUMBER_OF_INTERVALS
38        self.interval_number = number38        self.interval_number = number
39        self.interval_name = ALL_VALID_INTERVALS[number]39        self.interval_name = ALL_VALID_INTERVALS[number]
4040
41    def __str__(self):41    def __str__(self):
42        return self.interval_name42        return self.interval_name
4343
44    def __add__(self, other):44    def __add__(self, other):
45        if isinstance(other, Tone):45        if isinstance(other, Tone):
46            raise TypeError("Invalid operation")46            raise TypeError("Invalid operation")
47        elif isinstance(other, Interval):47        elif isinstance(other, Interval):
48            return Interval(self.interval_number + other.interval_number)48            return Interval(self.interval_number + other.interval_number)
4949
50    def __sub__(self, other):50    def __sub__(self, other):
51        if isinstance(other, Tone):51        if isinstance(other, Tone):
52            raise TypeError("Invalid operation")52            raise TypeError("Invalid operation")
5353
54    def __neg__(self):54    def __neg__(self):
55        return Interval(-self.interval_number)55        return Interval(-self.interval_number)
5656
5757
58class Chord:58class Chord:
59    def __init__(self, root, *args):59    def __init__(self, root, *args):
60        self.unique_tone_names = {root.name}60        self.unique_tone_names = {root.name}
61        self.tones = [root]61        self.tones = [root]
62        self.root = root62        self.root = root
63        for tone in args:63        for tone in args:
64            if tone.name not in self.unique_tone_names:64            if tone.name not in self.unique_tone_names:
65                self.tones.append(tone)65                self.tones.append(tone)
66                self.unique_tone_names.add(tone.name)66                self.unique_tone_names.add(tone.name)
67        if len(self.tones) == 1:67        if len(self.tones) == 1:
68            raise TypeError("Cannot have a chord made of only 1 unique tone")68            raise TypeError("Cannot have a chord made of only 1 unique tone")
69        root_num = ALL_VALID_TONES.index(str(root))69        root_num = ALL_VALID_TONES.index(str(root))
70        self.sorted_tones = sorted(self.tones, key= lambda tone: (ALL_VALID_TONES.index(str(tone)) - root_num) % 12)70        self.sorted_tones = sorted(self.tones, key= lambda tone: (ALL_VALID_TONES.index(str(tone)) - root_num) % 12)
7171
72    def __str__(self):72    def __str__(self):
73        return "-".join(str(tone) for tone in self.sorted_tones)73        return "-".join(str(tone) for tone in self.sorted_tones)
7474
75    def is_minor(self):75    def is_minor(self):
76        for tone in self.sorted_tones:76        for tone in self.sorted_tones:
n77            difference = abs(ALL_VALID_TONES.index((str(self.root))) - ALL_VALID_TONES.index((str(tone))))n77            difference = ALL_VALID_TONES.index((str(tone))) - ALL_VALID_TONES.index((str(self.root)))
78            if difference < 0:
79                difference += NUMBER_OF_INTERVALS
78            if difference == NUMBER_FOR_MINOR_3RD:80            if difference == NUMBER_FOR_MINOR_3RD:
79                return "True"81                return "True"
80        return "False"82        return "False"
8183
82    def is_major(self):84    def is_major(self):
83        for tone in self.sorted_tones:85        for tone in self.sorted_tones:
t84            difference = abs(ALL_VALID_TONES.index((str(self.root))) - ALL_VALID_TONES.index((str(tone))))t86            difference = ALL_VALID_TONES.index((str(tone))) - ALL_VALID_TONES.index((str(self.root)))
87            if difference < 0:
88                difference += NUMBER_OF_INTERVALS
85            if difference == NUMBER_FOR_MAJOR_3RD:89            if difference == NUMBER_FOR_MAJOR_3RD:
86                return "True"90                return "True"
87        return "False"91        return "False"
8892
89    def is_power_chord(self):93    def is_power_chord(self):
90        if self.is_minor() == "True" or self.is_major() == "True":94        if self.is_minor() == "True" or self.is_major() == "True":
91            return "False"95            return "False"
92        return "True"96        return "True"
9397
94    def __add__(self, other):98    def __add__(self, other):
95        if isinstance(other, Tone):99        if isinstance(other, Tone):
96            return Chord(*self.tones, other)100            return Chord(*self.tones, other)
97        if isinstance(other, Chord):101        if isinstance(other, Chord):
98            tones_for_new_chord = self.sorted_tones102            tones_for_new_chord = self.sorted_tones
99            for tone in other.sorted_tones:103            for tone in other.sorted_tones:
100                if not tone in tones_for_new_chord:104                if not tone in tones_for_new_chord:
101                    tones_for_new_chord.append(tone)105                    tones_for_new_chord.append(tone)
102            return Chord(*tones_for_new_chord)106            return Chord(*tones_for_new_chord)
103107
104    def __sub__(self, other):108    def __sub__(self, other):
105        if isinstance(other, Tone):109        if isinstance(other, Tone):
106            if other.name not in self.unique_tone_names:110            if other.name not in self.unique_tone_names:
107                raise TypeError(f"Cannot remove tone {other.name} from chord {str(self)}")111                raise TypeError(f"Cannot remove tone {other.name} from chord {str(self)}")
108            elif len(self.sorted_tones) - 1 == 1:112            elif len(self.sorted_tones) - 1 == 1:
109                raise TypeError("Cannot have a chord made of only 1 unique tone")113                raise TypeError("Cannot have a chord made of only 1 unique tone")
110            else:114            else:
111                tones_for_new_chord = list()115                tones_for_new_chord = list()
112                for tone in self.sorted_tones:116                for tone in self.sorted_tones:
113                    if not tone.name == other.name:117                    if not tone.name == other.name:
114                        tones_for_new_chord.append(tone)118                        tones_for_new_chord.append(tone)
115                return Chord(*tones_for_new_chord)119                return Chord(*tones_for_new_chord)
116120
117    def transposed(self, interval):121    def transposed(self, interval):
118        tones_in_new_chord = list()122        tones_in_new_chord = list()
119        if interval.interval_number >= 0:123        if interval.interval_number >= 0:
120            for tone in self.sorted_tones:124            for tone in self.sorted_tones:
121                tones_in_new_chord.append(tone + interval)125                tones_in_new_chord.append(tone + interval)
122            return Chord(*tones_in_new_chord)126            return Chord(*tones_in_new_chord)
123        else:127        else:
124            for tone in self.sorted_tones:128            for tone in self.sorted_tones:
125                tones_in_new_chord.append(tone - interval)129                tones_in_new_chord.append(tone - interval)
126            return Chord(*tones_in_new_chord)130            return Chord(*tones_in_new_chord)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

n1all_valid_tones = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")n1ALL_VALID_TONES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
2all_valid_intervals = {0: "unison", 1: "minor 2nd", 2: "major 2nd", 3: "minor 3rd", 4: "major 3rd", 5: "perfect 4th",2ALL_VALID_INTERVALS = ["unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th", "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th"]
3                       6: "diminished 5th", 7: "perfect 5th", 8: "minor 6th", 9: "major 6th", 10: "minor 7th", 11: "major 7th"}3NUMBER_OF_INTERVALS = 12
4number_of_intervals = 124NUMBER_FOR_MINOR_3RD = 3
5number_for_minor_3rd = 35NUMBER_FOR_MAJOR_3RD = 4
6number_for_major_3rd = 4
76
8class Tone:7class Tone:
9    def __init__(self, tone):8    def __init__(self, tone):
n10        if tone in all_valid_tones:n9        if tone in ALL_VALID_TONES:
11            self.name = tone10            self.name = tone
n12            self.index = all_valid_tones.index(tone)n11            self.index = ALL_VALID_TONES.index(tone)
13        else:12        else:
14            raise Exception("Invalid input.")13            raise Exception("Invalid input.")
1514
16    def __str__(self):15    def __str__(self):
n17        return self.namen
18 
19    def __getitem__(self, item):
20        return self.name16        return self.name
2117
22    def __add__(self, other):18    def __add__(self, other):
23        if isinstance(other, Tone):19        if isinstance(other, Tone):
24            return Chord(self, other)20            return Chord(self, other)
25        elif isinstance(other, Interval):21        elif isinstance(other, Interval):
26            index_of_new_tone = (self.index + other.interval_number) % 1222            index_of_new_tone = (self.index + other.interval_number) % 12
n27            return Tone(all_valid_tones[index_of_new_tone])n23            return Tone(ALL_VALID_TONES[index_of_new_tone])
2824
29    def __sub__(self, other):25    def __sub__(self, other):
30        if isinstance(other, Tone):26        if isinstance(other, Tone):
31            index_of_first_tone = self.index27            index_of_first_tone = self.index
32            index_of_second_tone = other.index28            index_of_second_tone = other.index
33            return Interval(index_of_first_tone - index_of_second_tone)29            return Interval(index_of_first_tone - index_of_second_tone)
34        elif isinstance(other, Interval):30        elif isinstance(other, Interval):
35            index_of_new_tone = self.index - other.interval_number31            index_of_new_tone = self.index - other.interval_number
n36            return Tone(all_valid_tones[index_of_new_tone])n32            return Tone(ALL_VALID_TONES[index_of_new_tone])
3733
3834
39class Interval:35class Interval:
40    def __init__(self, number):36    def __init__(self, number):
n41        number %= number_of_intervalsn37        number %= NUMBER_OF_INTERVALS
42        self.interval_number = number38        self.interval_number = number
n43        self.interval_name = all_valid_intervals[number]n39        self.interval_name = ALL_VALID_INTERVALS[number]
4440
45    def __str__(self):41    def __str__(self):
46        return self.interval_name42        return self.interval_name
4743
48    def __add__(self, other):44    def __add__(self, other):
49        if isinstance(other, Tone):45        if isinstance(other, Tone):
50            raise TypeError("Invalid operation")46            raise TypeError("Invalid operation")
51        elif isinstance(other, Interval):47        elif isinstance(other, Interval):
52            return Interval(self.interval_number + other.interval_number)48            return Interval(self.interval_number + other.interval_number)
5349
54    def __sub__(self, other):50    def __sub__(self, other):
55        if isinstance(other, Tone):51        if isinstance(other, Tone):
56            raise TypeError("Invalid operation")52            raise TypeError("Invalid operation")
5753
58    def __neg__(self):54    def __neg__(self):
59        return Interval(-self.interval_number)55        return Interval(-self.interval_number)
6056
6157
62class Chord:58class Chord:
63    def __init__(self, root, *args):59    def __init__(self, root, *args):
n64        self.unique_tone_names = set()n
65        self.tones = list()
66        self.unique_tone_names.add(root.name)60        self.unique_tone_names = {root.name}
67        self.tones.append(root)61        self.tones = [root]
68        self.root = root62        self.root = root
69        for tone in args:63        for tone in args:
70            if tone.name not in self.unique_tone_names:64            if tone.name not in self.unique_tone_names:
71                self.tones.append(tone)65                self.tones.append(tone)
72                self.unique_tone_names.add(tone.name)66                self.unique_tone_names.add(tone.name)
73        if len(self.tones) == 1:67        if len(self.tones) == 1:
74            raise TypeError("Cannot have a chord made of only 1 unique tone")68            raise TypeError("Cannot have a chord made of only 1 unique tone")
n75        root_num = all_valid_tones.index(str(root))n69        root_num = ALL_VALID_TONES.index(str(root))
76        self.sorted_tones = sorted(self.tones, key= lambda tone: (all_valid_tones.index(str(tone)) - root_num) % 12)70        self.sorted_tones = sorted(self.tones, key= lambda tone: (ALL_VALID_TONES.index(str(tone)) - root_num) % 12)
7771
78    def __str__(self):72    def __str__(self):
79        return "-".join(str(tone) for tone in self.sorted_tones)73        return "-".join(str(tone) for tone in self.sorted_tones)
8074
81    def is_minor(self):75    def is_minor(self):
82        for tone in self.sorted_tones:76        for tone in self.sorted_tones:
n83            difference = abs(all_valid_tones.index((str(self.root))) - all_valid_tones.index((str(tone))))n77            difference = abs(ALL_VALID_TONES.index((str(self.root))) - ALL_VALID_TONES.index((str(tone))))
84            if  difference == number_for_minor_3rd or 12 - difference == number_for_minor_3rd:78            if difference == NUMBER_FOR_MINOR_3RD:
85                return "True"79                return "True"
86        return "False"80        return "False"
8781
88    def is_major(self):82    def is_major(self):
89        for tone in self.sorted_tones:83        for tone in self.sorted_tones:
t90            difference = abs(all_valid_tones.index((str(self.root))) - all_valid_tones.index((str(tone))))t84            difference = abs(ALL_VALID_TONES.index((str(self.root))) - ALL_VALID_TONES.index((str(tone))))
91            if  difference== number_for_major_3rd or 12 - difference == number_for_major_3rd :85            if difference == NUMBER_FOR_MAJOR_3RD:
92                return "True"86                return "True"
93        return "False"87        return "False"
9488
95    def is_power_chord(self):89    def is_power_chord(self):
96        if self.is_minor() == "True" or self.is_major() == "True":90        if self.is_minor() == "True" or self.is_major() == "True":
97            return "False"91            return "False"
98        return "True"92        return "True"
9993
100    def __add__(self, other):94    def __add__(self, other):
101        if isinstance(other, Tone):95        if isinstance(other, Tone):
102            return Chord(*self.tones, other)96            return Chord(*self.tones, other)
103        if isinstance(other, Chord):97        if isinstance(other, Chord):
104            tones_for_new_chord = self.sorted_tones98            tones_for_new_chord = self.sorted_tones
105            for tone in other.sorted_tones:99            for tone in other.sorted_tones:
106                if not tone in tones_for_new_chord:100                if not tone in tones_for_new_chord:
107                    tones_for_new_chord.append(tone)101                    tones_for_new_chord.append(tone)
108            return Chord(*tones_for_new_chord)102            return Chord(*tones_for_new_chord)
109103
110    def __sub__(self, other):104    def __sub__(self, other):
111        if isinstance(other, Tone):105        if isinstance(other, Tone):
112            if other.name not in self.unique_tone_names:106            if other.name not in self.unique_tone_names:
113                raise TypeError(f"Cannot remove tone {other.name} from chord {str(self)}")107                raise TypeError(f"Cannot remove tone {other.name} from chord {str(self)}")
114            elif len(self.sorted_tones) - 1 == 1:108            elif len(self.sorted_tones) - 1 == 1:
115                raise TypeError("Cannot have a chord made of only 1 unique tone")109                raise TypeError("Cannot have a chord made of only 1 unique tone")
116            else:110            else:
117                tones_for_new_chord = list()111                tones_for_new_chord = list()
118                for tone in self.sorted_tones:112                for tone in self.sorted_tones:
119                    if not tone.name == other.name:113                    if not tone.name == other.name:
120                        tones_for_new_chord.append(tone)114                        tones_for_new_chord.append(tone)
121                return Chord(*tones_for_new_chord)115                return Chord(*tones_for_new_chord)
122116
123    def transposed(self, interval):117    def transposed(self, interval):
124        tones_in_new_chord = list()118        tones_in_new_chord = list()
125        if interval.interval_number >= 0:119        if interval.interval_number >= 0:
126            for tone in self.sorted_tones:120            for tone in self.sorted_tones:
127                tones_in_new_chord.append(tone + interval)121                tones_in_new_chord.append(tone + interval)
128            return Chord(*tones_in_new_chord)122            return Chord(*tones_in_new_chord)
129        else:123        else:
130            for tone in self.sorted_tones:124            for tone in self.sorted_tones:
131                tones_in_new_chord.append(tone - interval)125                tones_in_new_chord.append(tone - interval)
132            return Chord(*tones_in_new_chord)126            return Chord(*tones_in_new_chord)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op