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

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

10 точки общо

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

  1class Tone:
  2    NOTES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
  3    NOTE_COUNT = 12
  4
  5    def __init__(self, name):
  6        if name not in Tone.NOTES:
  7            raise TypeError("Invalid tone")
  8        self.name = name
  9        self.index = Tone.NOTES.index(name)
 10
 11    def __str__(self):
 12        return self.name
 13
 14    def __add__(self, other):
 15        if isinstance(other, Interval):
 16            new_index = (self.index + other.steps) % self.NOTE_COUNT
 17            return Tone(Tone.NOTES[new_index])
 18        elif isinstance(other, Tone):
 19            return Chord(self, other)
 20        raise TypeError("Invalid operation")
 21
 22    def __sub__(self, other):
 23        if isinstance(other, Interval):
 24            new_index = (self.index - other.steps) % self.NOTE_COUNT
 25            return Tone(Tone.NOTES[new_index])
 26        elif isinstance(other, Tone):
 27            steps = (self.index - other.index) % self.NOTE_COUNT
 28            return Interval(steps)
 29        raise TypeError("Invalid operation")
 30    
 31    def __hash__(self):
 32        return hash(self.name)
 33
 34    def __eq__(self, other):
 35        if isinstance(other, Tone):
 36            return self.name == other.name
 37        return False
 38    
 39        
 40class Interval:
 41    INTERVAL_NAMES = {0: "unison", 1: "minor 2nd",
 42                        2: "major 2nd", 3: "minor 3rd",
 43                        4: "major 3rd", 5: "perfect 4th",
 44                        6: "diminished 5th", 7: "perfect 5th",
 45                        8: "minor 6th", 9: "major 6th",
 46                        10: "minor 7th", 11: "major 7th"}
 47
 48    def __init__(self, steps):
 49        self.steps = steps % Tone.NOTE_COUNT
 50
 51    def __str__(self):
 52        return Interval.INTERVAL_NAMES[self.steps]
 53
 54    def __add__(self, other):
 55        if isinstance(other, Interval):
 56            return Interval(self.steps + other.steps)
 57        raise TypeError("Invalid operation")
 58    
 59    def __sub__(self, other):
 60        if isinstance(other, Tone):
 61            raise TypeError("Invalid operation")
 62    
 63    def __neg__(self):
 64        return Interval(-self.steps)
 65        
 66class Chord:
 67    def __init__(self, root, *tones):
 68        unique_tones = {root} | set(tones)
 69        if len(unique_tones) < 2:
 70            raise TypeError("Cannot have a chord made of only 1 unique tone")
 71        self.root = root
 72        self.tones = sorted(unique_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)
 73        self.tone_names = set(map(lambda tone: tone.name, self.tones))
 74
 75    def __str__(self):
 76        return "-".join(str(tone) for tone in self.tones)
 77
 78    def __add__(self, other):
 79        if isinstance(other, Tone):
 80            return Chord(self.root, *self.tones, other)
 81        elif isinstance(other, Chord):
 82            new_tones = {self.root} | set(self.tones + other.tones)
 83            return Chord(self.root, *(new_tones))
 84        elif isinstance(other, Interval):
 85            return self.transposed(other)
 86        raise TypeError("Invalid operation")
 87
 88    def __sub__(self, other):
 89        if isinstance(other, Tone):
 90            if other.name not in self.tone_names:
 91                raise TypeError(f"Cannot remove tone {other.name} from chord {self}")
 92            remaining_tones = set(filter(lambda tone: tone.name != other.name, self.tones))
 93            if len(remaining_tones) < 2:
 94                raise TypeError("Cannot have a chord made of only 1 unique tone")
 95            if self.root not in remaining_tones:
 96                new_root = min(remaining_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)
 97                return Chord(new_root, *remaining_tones)
 98            else:
 99                return Chord(self.root, *remaining_tones)
100        raise TypeError("Invalid operation")
101       
102    def is_minor(self):
103        minor_3rd = Interval(3)
104        return any((tone - self.root).steps == minor_3rd.steps for tone in self.tones)
105
106    def is_major(self):
107        major_3rd = Interval(4)
108        return any((tone - self.root).steps == major_3rd.steps for tone in self.tones)
109
110    def is_power_chord(self):
111        return not (self.is_minor() or self.is_major())
112
113    def transposed(self, interval):
114        transposed_tones = list(map(lambda tone: tone + interval, self.tones))
115        return Chord(*transposed_tones)

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

OK

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

f1class Tone:f1class Tone:
2    NOTES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")2    NOTES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
3    NOTE_COUNT = 123    NOTE_COUNT = 12
44
5    def __init__(self, name):5    def __init__(self, name):
6        if name not in Tone.NOTES:6        if name not in Tone.NOTES:
7            raise TypeError("Invalid tone")7            raise TypeError("Invalid tone")
8        self.name = name8        self.name = name
9        self.index = Tone.NOTES.index(name)9        self.index = Tone.NOTES.index(name)
1010
11    def __str__(self):11    def __str__(self):
12        return self.name12        return self.name
1313
14    def __add__(self, other):14    def __add__(self, other):
15        if isinstance(other, Interval):15        if isinstance(other, Interval):
16            new_index = (self.index + other.steps) % self.NOTE_COUNT16            new_index = (self.index + other.steps) % self.NOTE_COUNT
17            return Tone(Tone.NOTES[new_index])17            return Tone(Tone.NOTES[new_index])
18        elif isinstance(other, Tone):18        elif isinstance(other, Tone):
19            return Chord(self, other)19            return Chord(self, other)
20        raise TypeError("Invalid operation")20        raise TypeError("Invalid operation")
2121
22    def __sub__(self, other):22    def __sub__(self, other):
23        if isinstance(other, Interval):23        if isinstance(other, Interval):
24            new_index = (self.index - other.steps) % self.NOTE_COUNT24            new_index = (self.index - other.steps) % self.NOTE_COUNT
25            return Tone(Tone.NOTES[new_index])25            return Tone(Tone.NOTES[new_index])
26        elif isinstance(other, Tone):26        elif isinstance(other, Tone):
27            steps = (self.index - other.index) % self.NOTE_COUNT27            steps = (self.index - other.index) % self.NOTE_COUNT
28            return Interval(steps)28            return Interval(steps)
29        raise TypeError("Invalid operation")29        raise TypeError("Invalid operation")
30    30    
31    def __hash__(self):31    def __hash__(self):
32        return hash(self.name)32        return hash(self.name)
3333
34    def __eq__(self, other):34    def __eq__(self, other):
35        if isinstance(other, Tone):35        if isinstance(other, Tone):
36            return self.name == other.name36            return self.name == other.name
37        return False37        return False
38    38    
39        39        
40class Interval:40class Interval:
41    INTERVAL_NAMES = {0: "unison", 1: "minor 2nd",41    INTERVAL_NAMES = {0: "unison", 1: "minor 2nd",
42                        2: "major 2nd", 3: "minor 3rd",42                        2: "major 2nd", 3: "minor 3rd",
43                        4: "major 3rd", 5: "perfect 4th",43                        4: "major 3rd", 5: "perfect 4th",
44                        6: "diminished 5th", 7: "perfect 5th",44                        6: "diminished 5th", 7: "perfect 5th",
45                        8: "minor 6th", 9: "major 6th",45                        8: "minor 6th", 9: "major 6th",
46                        10: "minor 7th", 11: "major 7th"}46                        10: "minor 7th", 11: "major 7th"}
4747
48    def __init__(self, steps):48    def __init__(self, steps):
49        self.steps = steps % Tone.NOTE_COUNT49        self.steps = steps % Tone.NOTE_COUNT
5050
51    def __str__(self):51    def __str__(self):
52        return Interval.INTERVAL_NAMES[self.steps]52        return Interval.INTERVAL_NAMES[self.steps]
5353
54    def __add__(self, other):54    def __add__(self, other):
55        if isinstance(other, Interval):55        if isinstance(other, Interval):
56            return Interval(self.steps + other.steps)56            return Interval(self.steps + other.steps)
57        raise TypeError("Invalid operation")57        raise TypeError("Invalid operation")
58    58    
59    def __sub__(self, other):59    def __sub__(self, other):
60        if isinstance(other, Tone):60        if isinstance(other, Tone):
61            raise TypeError("Invalid operation")61            raise TypeError("Invalid operation")
62    62    
63    def __neg__(self):63    def __neg__(self):
64        return Interval(-self.steps)64        return Interval(-self.steps)
65        65        
66class Chord:66class Chord:
67    def __init__(self, root, *tones):67    def __init__(self, root, *tones):
68        unique_tones = {root} | set(tones)68        unique_tones = {root} | set(tones)
69        if len(unique_tones) < 2:69        if len(unique_tones) < 2:
70            raise TypeError("Cannot have a chord made of only 1 unique tone")70            raise TypeError("Cannot have a chord made of only 1 unique tone")
71        self.root = root71        self.root = root
72        self.tones = sorted(unique_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)72        self.tones = sorted(unique_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)
73        self.tone_names = set(map(lambda tone: tone.name, self.tones))73        self.tone_names = set(map(lambda tone: tone.name, self.tones))
7474
75    def __str__(self):75    def __str__(self):
76        return "-".join(str(tone) for tone in self.tones)76        return "-".join(str(tone) for tone in self.tones)
7777
78    def __add__(self, other):78    def __add__(self, other):
79        if isinstance(other, Tone):79        if isinstance(other, Tone):
80            return Chord(self.root, *self.tones, other)80            return Chord(self.root, *self.tones, other)
81        elif isinstance(other, Chord):81        elif isinstance(other, Chord):
t82            new_tones = {self.root} | set(self.tones) | set(other.tones)t82            new_tones = {self.root} | set(self.tones + other.tones)
83            return Chord(self.root, *(new_tones))83            return Chord(self.root, *(new_tones))
84        elif isinstance(other, Interval):84        elif isinstance(other, Interval):
85            return self.transposed(other)85            return self.transposed(other)
86        raise TypeError("Invalid operation")86        raise TypeError("Invalid operation")
8787
88    def __sub__(self, other):88    def __sub__(self, other):
89        if isinstance(other, Tone):89        if isinstance(other, Tone):
90            if other.name not in self.tone_names:90            if other.name not in self.tone_names:
91                raise TypeError(f"Cannot remove tone {other.name} from chord {self}")91                raise TypeError(f"Cannot remove tone {other.name} from chord {self}")
92            remaining_tones = set(filter(lambda tone: tone.name != other.name, self.tones))92            remaining_tones = set(filter(lambda tone: tone.name != other.name, self.tones))
93            if len(remaining_tones) < 2:93            if len(remaining_tones) < 2:
94                raise TypeError("Cannot have a chord made of only 1 unique tone")94                raise TypeError("Cannot have a chord made of only 1 unique tone")
95            if self.root not in remaining_tones:95            if self.root not in remaining_tones:
96                new_root = min(remaining_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)96                new_root = min(remaining_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)
97                return Chord(new_root, *remaining_tones)97                return Chord(new_root, *remaining_tones)
98            else:98            else:
99                return Chord(self.root, *remaining_tones)99                return Chord(self.root, *remaining_tones)
100        raise TypeError("Invalid operation")100        raise TypeError("Invalid operation")
101       101       
102    def is_minor(self):102    def is_minor(self):
103        minor_3rd = Interval(3)103        minor_3rd = Interval(3)
104        return any((tone - self.root).steps == minor_3rd.steps for tone in self.tones)104        return any((tone - self.root).steps == minor_3rd.steps for tone in self.tones)
105105
106    def is_major(self):106    def is_major(self):
107        major_3rd = Interval(4)107        major_3rd = Interval(4)
108        return any((tone - self.root).steps == major_3rd.steps for tone in self.tones)108        return any((tone - self.root).steps == major_3rd.steps for tone in self.tones)
109109
110    def is_power_chord(self):110    def is_power_chord(self):
111        return not (self.is_minor() or self.is_major())111        return not (self.is_minor() or self.is_major())
112112
113    def transposed(self, interval):113    def transposed(self, interval):
114        transposed_tones = list(map(lambda tone: tone + interval, self.tones))114        transposed_tones = list(map(lambda tone: tone + interval, self.tones))
115        return Chord(*transposed_tones)115        return Chord(*transposed_tones)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1class Tone:f1class Tone:
2    NOTES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")2    NOTES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
3    NOTE_COUNT = 123    NOTE_COUNT = 12
44
5    def __init__(self, name):5    def __init__(self, name):
6        if name not in Tone.NOTES:6        if name not in Tone.NOTES:
7            raise TypeError("Invalid tone")7            raise TypeError("Invalid tone")
8        self.name = name8        self.name = name
9        self.index = Tone.NOTES.index(name)9        self.index = Tone.NOTES.index(name)
1010
11    def __str__(self):11    def __str__(self):
12        return self.name12        return self.name
1313
14    def __add__(self, other):14    def __add__(self, other):
15        if isinstance(other, Interval):15        if isinstance(other, Interval):
16            new_index = (self.index + other.steps) % self.NOTE_COUNT16            new_index = (self.index + other.steps) % self.NOTE_COUNT
17            return Tone(Tone.NOTES[new_index])17            return Tone(Tone.NOTES[new_index])
18        elif isinstance(other, Tone):18        elif isinstance(other, Tone):
19            return Chord(self, other)19            return Chord(self, other)
20        raise TypeError("Invalid operation")20        raise TypeError("Invalid operation")
2121
22    def __sub__(self, other):22    def __sub__(self, other):
23        if isinstance(other, Interval):23        if isinstance(other, Interval):
24            new_index = (self.index - other.steps) % self.NOTE_COUNT24            new_index = (self.index - other.steps) % self.NOTE_COUNT
25            return Tone(Tone.NOTES[new_index])25            return Tone(Tone.NOTES[new_index])
26        elif isinstance(other, Tone):26        elif isinstance(other, Tone):
27            steps = (self.index - other.index) % self.NOTE_COUNT27            steps = (self.index - other.index) % self.NOTE_COUNT
28            return Interval(steps)28            return Interval(steps)
29        raise TypeError("Invalid operation")29        raise TypeError("Invalid operation")
30    30    
31    def __hash__(self):31    def __hash__(self):
32        return hash(self.name)32        return hash(self.name)
3333
34    def __eq__(self, other):34    def __eq__(self, other):
35        if isinstance(other, Tone):35        if isinstance(other, Tone):
36            return self.name == other.name36            return self.name == other.name
37        return False37        return False
38    38    
39        39        
40class Interval:40class Interval:
41    INTERVAL_NAMES = {0: "unison", 1: "minor 2nd",41    INTERVAL_NAMES = {0: "unison", 1: "minor 2nd",
42                        2: "major 2nd", 3: "minor 3rd",42                        2: "major 2nd", 3: "minor 3rd",
43                        4: "major 3rd", 5: "perfect 4th",43                        4: "major 3rd", 5: "perfect 4th",
44                        6: "diminished 5th", 7: "perfect 5th",44                        6: "diminished 5th", 7: "perfect 5th",
45                        8: "minor 6th", 9: "major 6th",45                        8: "minor 6th", 9: "major 6th",
46                        10: "minor 7th", 11: "major 7th"}46                        10: "minor 7th", 11: "major 7th"}
4747
48    def __init__(self, steps):48    def __init__(self, steps):
49        self.steps = steps % Tone.NOTE_COUNT49        self.steps = steps % Tone.NOTE_COUNT
5050
51    def __str__(self):51    def __str__(self):
52        return Interval.INTERVAL_NAMES[self.steps]52        return Interval.INTERVAL_NAMES[self.steps]
5353
54    def __add__(self, other):54    def __add__(self, other):
55        if isinstance(other, Interval):55        if isinstance(other, Interval):
56            return Interval(self.steps + other.steps)56            return Interval(self.steps + other.steps)
57        raise TypeError("Invalid operation")57        raise TypeError("Invalid operation")
58    58    
tt59    def __sub__(self, other):
60        if isinstance(other, Tone):
61            raise TypeError("Invalid operation")
62    
59    def __neg__(self):63    def __neg__(self):
60        return Interval(-self.steps)64        return Interval(-self.steps)
61        65        
62class Chord:66class Chord:
63    def __init__(self, root, *tones):67    def __init__(self, root, *tones):
64        unique_tones = {root} | set(tones)68        unique_tones = {root} | set(tones)
65        if len(unique_tones) < 2:69        if len(unique_tones) < 2:
66            raise TypeError("Cannot have a chord made of only 1 unique tone")70            raise TypeError("Cannot have a chord made of only 1 unique tone")
67        self.root = root71        self.root = root
68        self.tones = sorted(unique_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)72        self.tones = sorted(unique_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)
69        self.tone_names = set(map(lambda tone: tone.name, self.tones))73        self.tone_names = set(map(lambda tone: tone.name, self.tones))
7074
71    def __str__(self):75    def __str__(self):
72        return "-".join(str(tone) for tone in self.tones)76        return "-".join(str(tone) for tone in self.tones)
7377
74    def __add__(self, other):78    def __add__(self, other):
75        if isinstance(other, Tone):79        if isinstance(other, Tone):
76            return Chord(self.root, *self.tones, other)80            return Chord(self.root, *self.tones, other)
77        elif isinstance(other, Chord):81        elif isinstance(other, Chord):
78            new_tones = {self.root} | set(self.tones) | set(other.tones)82            new_tones = {self.root} | set(self.tones) | set(other.tones)
79            return Chord(self.root, *(new_tones))83            return Chord(self.root, *(new_tones))
80        elif isinstance(other, Interval):84        elif isinstance(other, Interval):
81            return self.transposed(other)85            return self.transposed(other)
82        raise TypeError("Invalid operation")86        raise TypeError("Invalid operation")
8387
84    def __sub__(self, other):88    def __sub__(self, other):
85        if isinstance(other, Tone):89        if isinstance(other, Tone):
86            if other.name not in self.tone_names:90            if other.name not in self.tone_names:
87                raise TypeError(f"Cannot remove tone {other.name} from chord {self}")91                raise TypeError(f"Cannot remove tone {other.name} from chord {self}")
88            remaining_tones = set(filter(lambda tone: tone.name != other.name, self.tones))92            remaining_tones = set(filter(lambda tone: tone.name != other.name, self.tones))
89            if len(remaining_tones) < 2:93            if len(remaining_tones) < 2:
90                raise TypeError("Cannot have a chord made of only 1 unique tone")94                raise TypeError("Cannot have a chord made of only 1 unique tone")
91            if self.root not in remaining_tones:95            if self.root not in remaining_tones:
92                new_root = min(remaining_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)96                new_root = min(remaining_tones, key=lambda tone: (tone.index - self.root.index) % Tone.NOTE_COUNT)
93                return Chord(new_root, *remaining_tones)97                return Chord(new_root, *remaining_tones)
94            else:98            else:
95                return Chord(self.root, *remaining_tones)99                return Chord(self.root, *remaining_tones)
96        raise TypeError("Invalid operation")100        raise TypeError("Invalid operation")
97       101       
98    def is_minor(self):102    def is_minor(self):
99        minor_3rd = Interval(3)103        minor_3rd = Interval(3)
100        return any((tone - self.root).steps == minor_3rd.steps for tone in self.tones)104        return any((tone - self.root).steps == minor_3rd.steps for tone in self.tones)
101105
102    def is_major(self):106    def is_major(self):
103        major_3rd = Interval(4)107        major_3rd = Interval(4)
104        return any((tone - self.root).steps == major_3rd.steps for tone in self.tones)108        return any((tone - self.root).steps == major_3rd.steps for tone in self.tones)
105109
106    def is_power_chord(self):110    def is_power_chord(self):
107        return not (self.is_minor() or self.is_major())111        return not (self.is_minor() or self.is_major())
108112
109    def transposed(self, interval):113    def transposed(self, interval):
110        transposed_tones = list(map(lambda tone: tone + interval, self.tones))114        transposed_tones = list(map(lambda tone: tone + interval, self.tones))
111        return Chord(*transposed_tones)115        return Chord(*transposed_tones)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op