1class Tone:
2 NOTES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
3
4 def __init__(self, note):
5 self.note = note
6
7 def __str__(self):
8 return self.note
9
10 def __add__(self, other):
11 if isinstance(other, Interval):
12 index = (self.NOTES.index(self.note) + other.semitones) % 12
13 return Tone(self.NOTES[index])
14 elif isinstance(other, Tone):
15 return Chord(self, other)
16
17 def __sub__(self, other):
18 if isinstance(other, Tone):
19 start = self.NOTES.index(other.note)
20 end = self.NOTES.index(self.note)
21 semitones = (end - start) % 12
22 return Interval(semitones)
23 elif isinstance(other, Interval):
24 index = (self.NOTES.index(self.note) - other.semitones) % 12
25 return Tone(self.NOTES[index])
26 raise TypeError("Invalid operation")
27
28 def __eq__(self, other):
29 return isinstance(other, Tone) and self.note == other.note
30
31 def __hash__(self):
32 return hash(self.note)
33
34class Interval:
35 NAMES = {
36 0: "perfect unison",
37 1: "minor 2nd",
38 2: "major 2nd",
39 3: "minor 3rd",
40 4: "major 3rd",
41 5: "perfect 4th",
42 6: "tritone",
43 7: "perfect 5th",
44 8: "minor 6th",
45 9: "major 6th",
46 10: "minor 7th",
47 11: "major 7th"
48 }
49
50 def __init__(self, semitones):
51 self.semitones = semitones % 12
52
53 def __str__(self):
54 return self.NAMES[self.semitones]
55
56 def __add__(self, other):
57 return Interval(self.semitones + other.semitones)
58
59 def __neg__(self):
60 return Interval(-self.semitones)
61
62class Chord:
63 def __init__(self, root, *notes):
64 unique_notes = {root}
65 for note in notes:
66 unique_notes.add(note)
67
68 if len(unique_notes) < 2:
69 raise TypeError("Cannot have a chord made of only 1 unique tone")
70
71 self.root = root
72 self.notes = unique_notes
73
74 def __str__(self):
75 sorted_notes = sorted(self.notes,
76 key=lambda x: (Tone.NOTES.index(x.note) - Tone.NOTES.index(self.root.note)) % 12)
77 return "-".join(str(note) for note in sorted_notes)
78
79 def is_minor(self):
80 for note in self.notes:
81 if (note - self.root).semitones == 3:
82 return True
83 return False
84
85 def is_major(self):
86 for note in self.notes:
87 if (note - self.root).semitones == 4:
88 return True
89 return False
90
91 def is_power_chord(self):
92 return not (self.is_minor() or self.is_major())
93
94 def __add__(self, other):
95 if isinstance(other, Tone):
96 return Chord(self.root, *(self.notes | {other}))
97 elif isinstance(other, Chord):
98 return Chord(self.root, *(self.notes | other.notes))
99
100 def __sub__(self, other):
101 if other not in self.notes:
102 raise TypeError(f"Cannot remove tone {other} from chord {self}")
103
104 remaining = self.notes - {other}
105 if len(remaining) < 2:
106 raise TypeError("Cannot have a chord made of only 1 unique tone")
107
108 return Chord(self.root, *(note for note in remaining if note != self.root))
109
110 def transposed(self, interval):
111 if isinstance(interval, int):
112 interval = Interval(interval)
113 return Chord(self.root + interval,
114 *(note + interval for note in self.notes if note != self.root))
115
116# Кой е любимия плод на бетовен?
117# БА-НА-НА-НААААААА
.............F....E......F.F........F
======================================================================
ERROR: test_add_interval_to_tone_left_side_error (test.TestOperations.test_add_interval_to_tone_left_side_error)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 210, in test_add_interval_to_tone_left_side_error
Interval(2) + g
~~~~~~~~~~~~^~~
File "/tmp/solution.py", line 57, in __add__
return Interval(self.semitones + other.semitones)
^^^^^^^^^^^^^^^
AttributeError: 'Tone' object has no attribute 'semitones'
======================================================================
FAIL: test_interval_str (test.TestBasicIntervalFunctionality.test_interval_str)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 42, in test_interval_str
self.assertEqual(str(Interval(index)), interval)
AssertionError: 'perfect unison' != 'unison'
- perfect unison
+ unison
======================================================================
FAIL: test_interval_addition_overflow (test.TestOperations.test_interval_addition_overflow)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 247, in test_interval_addition_overflow
self.assertEqual(str(unison), "unison")
AssertionError: 'perfect unison' != 'unison'
- perfect unison
+ unison
======================================================================
FAIL: test_subtract_interval_from_tone_left_side_error (test.TestOperations.test_subtract_interval_from_tone_left_side_error)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 235, in test_subtract_interval_from_tone_left_side_error
self.assertEqual(str(err.exception), INVALID_OPERATION)
AssertionError: "unsupported operand type(s) for -: 'Interval' and 'Tone'" != 'Invalid operation'
- unsupported operand type(s) for -: 'Interval' and 'Tone'
+ Invalid operation
======================================================================
FAIL: test_tone_subtraction_same_tone (test.TestOperations.test_tone_subtraction_same_tone)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 183, in test_tone_subtraction_same_tone
self.assertEqual(str(unison), "unison")
AssertionError: 'perfect unison' != 'unison'
- perfect unison
+ unison
----------------------------------------------------------------------
Ran 37 tests in 0.002s
FAILED (failures=4, errors=1)
Виктор Бечев
05.11.2024 10:26Ако е нещо, на което държим - ще сме настоятелни. Тези - занапред. :)
|
Никола Георгиев
05.11.2024 09:07Мерси за обратната връзка :))
Бърз въпрос - много ли се налага да оправя тези нещица, или просто да си ги имам предвид занапред?
|
Никола Георгиев
03.11.2024 13:27What kind of music are Balloons afraid of?
Pop music.
|
03.11.2024 21:24
03.11.2024 21:25
03.11.2024 21:28
03.11.2024 21:27
03.11.2024 21:22