1TONES = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]
2
3
4class Tone:
5 def __init__(self, entry):
6 self.tone = entry
7 self.idx = TONES.index(entry)
8
9 def __str__(self):
10 return self.tone
11
12 def __eq__(self, value):
13 return self.tone == value.tone
14
15 def __hash__(self):
16 return hash(self.tone)
17
18 def __add__(self, other):
19 if type(other) is Chord:
20 return Chord(self, other)
21 elif type(other) is Interval:
22 tone = (self.idx + other.type) % 12
23 return Tone(TONES[tone])
24 elif type(other) is Tone:
25 return Chord(self, other)
26
27 def __sub__(self, other):
28 if type(other) is Tone:
29 return Interval(self.idx - other.idx)
30 if type(other) is Interval:
31 tone = (self.idx - other.type) % 12
32 return Tone(TONES[tone])
33
34
35INTERVAL_RANGE = [
36 "unison",
37 "minor 2nd",
38 "major 2nd",
39 "minor 3rd",
40 "major 3rd",
41 "perfect 4th",
42 "diminished 5th",
43 "perfect 5th",
44 "minor 6th",
45 "major 6th",
46 "minor 7th",
47 "major 7th",
48]
49
50
51class Interval:
52 def __init__(self, number):
53 self.type = number % 12
54
55 def __str__(self):
56 return INTERVAL_RANGE[self.type]
57
58 def __add__(self, other):
59 if type(other) is Interval:
60 return Interval((self.type + other.type) % 12)
61 elif type(other) is Tone:
62 raise TypeError("Invalid operation")
63
64 def __neg__(self):
65 return Interval(12 - self.type)
66
67 def __sub__(self, other):
68 raise TypeError("Invalid operation")
69
70
71class Chord:
72 def __init__(self, root, *args):
73 self.chord_set = set()
74 self.chord_set.add(root)
75 self.root = root
76
77 self.chord_set.update(args)
78
79 if len(self.chord_set) == 1:
80 raise TypeError("Cannot have a chord made of only 1 unique tone")
81
82 def __str__(self):
83 temp_list = []
84 for k in range(self.root.idx, self.root.idx + 12):
85 if Tone(TONES[k % 12]) in self.chord_set:
86 temp_list.append(str(Tone(TONES[k % 12])))
87 return "-".join(temp_list)
88
89 def is_minor(self):
90 for elt in self.chord_set:
91 if not elt == self.root:
92 if (elt - self.root).type == 3:
93 return True
94 return False
95
96 def is_major(self):
97 for elt in self.chord_set:
98 if not elt == self.root:
99 if (elt - self.root).type == 4:
100 return True
101 return False
102
103 def is_power_chord(self):
104 return not (self.is_major() or self.is_minor())
105
106 def __add__(self, other):
107 if type(other) is Tone:
108 self.chord_set.add(other)
109 return Chord(self.root, *self.chord_set)
110 if type(other) is Chord:
111 return Chord(self.root, *(self.chord_set | other.chord_set))
112
113 def __sub__(self, other):
114 if type(other) is Tone:
115 if other not in self.chord_set:
116 raise TypeError(
117 f"Cannot remove tone {str(other)} from chord {str(self)}"
118 )
119 elif len(self.chord_set) <= 2:
120 raise TypeError("Cannot have a chord made of only 1 unique tone")
121 else:
122 self.chord_set.remove(other)
123 return Chord(self.root, *self.chord_set)
124
125 def transposed(self, other):
126 return Chord(self.root + other, *list(map(lambda x: x + other, self.chord_set)))
.....................................
----------------------------------------------------------------------
Ran 37 tests in 0.001s
OK
Виктор Бечев
06.11.2024 15:23Много правилно.
|
Даниел Манчевски
06.11.2024 15:13Reply то: "Имаш опцията за self.chord_set.extend(args), което ще добави всички елементи в колекцията и няма да има нужда от "ръчен" for."
Когато имаме set се използва .update()
|
Виктор Бечев
06.11.2024 15:08Въпреки, че ти липсват някои от идиоматичните за Python неща - впечатляващо добре обмислено решение.
|
f | 1 | TONES = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"] | f | 1 | TONES = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"] |
2 | 2 | ||||
3 | 3 | ||||
4 | class Tone: | 4 | class Tone: | ||
n | 5 | def __init__(self, *args): | n | 5 | def __init__(self, entry): |
6 | self.tone = args[0] | 6 | self.tone = entry | ||
7 | for i, tone in enumerate(TONES): | 7 | self.idx = TONES.index(entry) | ||
8 | if self.tone == tone: | ||||
9 | self.idx = i | ||||
10 | 8 | ||||
11 | def __str__(self): | 9 | def __str__(self): | ||
12 | return self.tone | 10 | return self.tone | ||
13 | 11 | ||||
14 | def __eq__(self, value): | 12 | def __eq__(self, value): | ||
15 | return self.tone == value.tone | 13 | return self.tone == value.tone | ||
16 | 14 | ||||
17 | def __hash__(self): | 15 | def __hash__(self): | ||
18 | return hash(self.tone) | 16 | return hash(self.tone) | ||
19 | 17 | ||||
20 | def __add__(self, other): | 18 | def __add__(self, other): | ||
21 | if type(other) is Chord: | 19 | if type(other) is Chord: | ||
22 | return Chord(self, other) | 20 | return Chord(self, other) | ||
23 | elif type(other) is Interval: | 21 | elif type(other) is Interval: | ||
24 | tone = (self.idx + other.type) % 12 | 22 | tone = (self.idx + other.type) % 12 | ||
25 | return Tone(TONES[tone]) | 23 | return Tone(TONES[tone]) | ||
26 | elif type(other) is Tone: | 24 | elif type(other) is Tone: | ||
27 | return Chord(self, other) | 25 | return Chord(self, other) | ||
28 | 26 | ||||
29 | def __sub__(self, other): | 27 | def __sub__(self, other): | ||
30 | if type(other) is Tone: | 28 | if type(other) is Tone: | ||
31 | return Interval(self.idx - other.idx) | 29 | return Interval(self.idx - other.idx) | ||
32 | if type(other) is Interval: | 30 | if type(other) is Interval: | ||
33 | tone = (self.idx - other.type) % 12 | 31 | tone = (self.idx - other.type) % 12 | ||
34 | return Tone(TONES[tone]) | 32 | return Tone(TONES[tone]) | ||
n | 35 | n | |||
36 | def __str__(self): | ||||
37 | return TONES[self.idx] | ||||
38 | 33 | ||||
39 | 34 | ||||
40 | INTERVAL_RANGE = [ | 35 | INTERVAL_RANGE = [ | ||
41 | "unison", | 36 | "unison", | ||
42 | "minor 2nd", | 37 | "minor 2nd", | ||
43 | "major 2nd", | 38 | "major 2nd", | ||
44 | "minor 3rd", | 39 | "minor 3rd", | ||
45 | "major 3rd", | 40 | "major 3rd", | ||
46 | "perfect 4th", | 41 | "perfect 4th", | ||
47 | "diminished 5th", | 42 | "diminished 5th", | ||
48 | "perfect 5th", | 43 | "perfect 5th", | ||
49 | "minor 6th", | 44 | "minor 6th", | ||
50 | "major 6th", | 45 | "major 6th", | ||
51 | "minor 7th", | 46 | "minor 7th", | ||
52 | "major 7th", | 47 | "major 7th", | ||
53 | ] | 48 | ] | ||
54 | 49 | ||||
55 | 50 | ||||
56 | class Interval: | 51 | class Interval: | ||
57 | def __init__(self, number): | 52 | def __init__(self, number): | ||
58 | self.type = number % 12 | 53 | self.type = number % 12 | ||
59 | 54 | ||||
60 | def __str__(self): | 55 | def __str__(self): | ||
61 | return INTERVAL_RANGE[self.type] | 56 | return INTERVAL_RANGE[self.type] | ||
62 | 57 | ||||
63 | def __add__(self, other): | 58 | def __add__(self, other): | ||
64 | if type(other) is Interval: | 59 | if type(other) is Interval: | ||
65 | return Interval((self.type + other.type) % 12) | 60 | return Interval((self.type + other.type) % 12) | ||
66 | elif type(other) is Tone: | 61 | elif type(other) is Tone: | ||
67 | raise TypeError("Invalid operation") | 62 | raise TypeError("Invalid operation") | ||
68 | 63 | ||||
69 | def __neg__(self): | 64 | def __neg__(self): | ||
70 | return Interval(12 - self.type) | 65 | return Interval(12 - self.type) | ||
71 | 66 | ||||
72 | def __sub__(self, other): | 67 | def __sub__(self, other): | ||
73 | raise TypeError("Invalid operation") | 68 | raise TypeError("Invalid operation") | ||
74 | 69 | ||||
75 | 70 | ||||
76 | class Chord: | 71 | class Chord: | ||
77 | def __init__(self, root, *args): | 72 | def __init__(self, root, *args): | ||
78 | self.chord_set = set() | 73 | self.chord_set = set() | ||
79 | self.chord_set.add(root) | 74 | self.chord_set.add(root) | ||
80 | self.root = root | 75 | self.root = root | ||
81 | 76 | ||||
n | 82 | for arg in args: | n | ||
83 | self.chord_set.add(arg) | 77 | self.chord_set.update(args) | ||
84 | 78 | ||||
85 | if len(self.chord_set) == 1: | 79 | if len(self.chord_set) == 1: | ||
86 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 80 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
87 | 81 | ||||
88 | def __str__(self): | 82 | def __str__(self): | ||
n | 89 | res = "" | n | 83 | temp_list = [] |
90 | var = False | ||||
91 | for k in range(self.root.idx, self.root.idx + 12): | 84 | for k in range(self.root.idx, self.root.idx + 12): | ||
92 | if Tone(TONES[k % 12]) in self.chord_set: | 85 | if Tone(TONES[k % 12]) in self.chord_set: | ||
n | 93 | if var: | n | 86 | temp_list.append(str(Tone(TONES[k % 12]))) |
94 | res += "-" | 87 | return "-".join(temp_list) | ||
95 | res += Tone(TONES[k % 12]).__str__() | ||||
96 | var = True | ||||
97 | |||||
98 | return res | ||||
99 | 88 | ||||
100 | def is_minor(self): | 89 | def is_minor(self): | ||
n | 101 | for elt in list(self.chord_set): | n | 90 | for elt in self.chord_set: |
102 | if not elt == self.root: | 91 | if not elt == self.root: | ||
103 | if (elt - self.root).type == 3: | 92 | if (elt - self.root).type == 3: | ||
104 | return True | 93 | return True | ||
105 | return False | 94 | return False | ||
106 | 95 | ||||
107 | def is_major(self): | 96 | def is_major(self): | ||
n | 108 | for elt in list(self.chord_set): | n | 97 | for elt in self.chord_set: |
109 | if not elt == self.root: | 98 | if not elt == self.root: | ||
110 | if (elt - self.root).type == 4: | 99 | if (elt - self.root).type == 4: | ||
111 | return True | 100 | return True | ||
112 | return False | 101 | return False | ||
113 | 102 | ||||
114 | def is_power_chord(self): | 103 | def is_power_chord(self): | ||
115 | return not (self.is_major() or self.is_minor()) | 104 | return not (self.is_major() or self.is_minor()) | ||
116 | 105 | ||||
117 | def __add__(self, other): | 106 | def __add__(self, other): | ||
118 | if type(other) is Tone: | 107 | if type(other) is Tone: | ||
119 | self.chord_set.add(other) | 108 | self.chord_set.add(other) | ||
120 | return Chord(self.root, *self.chord_set) | 109 | return Chord(self.root, *self.chord_set) | ||
121 | if type(other) is Chord: | 110 | if type(other) is Chord: | ||
122 | return Chord(self.root, *(self.chord_set | other.chord_set)) | 111 | return Chord(self.root, *(self.chord_set | other.chord_set)) | ||
123 | 112 | ||||
124 | def __sub__(self, other): | 113 | def __sub__(self, other): | ||
125 | if type(other) is Tone: | 114 | if type(other) is Tone: | ||
t | 126 | if not self.chord_set.__contains__(other): | t | 115 | if other not in self.chord_set: |
127 | raise TypeError( | 116 | raise TypeError( | ||
128 | f"Cannot remove tone {str(other)} from chord {str(self)}" | 117 | f"Cannot remove tone {str(other)} from chord {str(self)}" | ||
129 | ) | 118 | ) | ||
130 | elif len(self.chord_set) <= 2: | 119 | elif len(self.chord_set) <= 2: | ||
131 | raise TypeError("Cannot have a chord made of only 1 unique tone") | 120 | raise TypeError("Cannot have a chord made of only 1 unique tone") | ||
132 | else: | 121 | else: | ||
133 | self.chord_set.remove(other) | 122 | self.chord_set.remove(other) | ||
134 | return Chord(self.root, *self.chord_set) | 123 | return Chord(self.root, *self.chord_set) | ||
135 | 124 | ||||
136 | def transposed(self, other): | 125 | def transposed(self, other): | ||
137 | return Chord(self.root + other, *list(map(lambda x: x + other, self.chord_set))) | 126 | return Chord(self.root + other, *list(map(lambda x: x + other, self.chord_set))) |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|