Домашни > Pitches love the D > Решения > Решението на Ипек Ибрахим

Резултати
8 точки от тестове
1 точки от учител

9 точки общо

29 успешни теста
8 неуспешни теста
Код

  1DEFINED_TONES = (
  2    "C", "C#", "D", "D#", "E", "F",
  3    "F#", "G", "G#", "A", "A#", "B"
  4    )
  5DEFINED_INTERVALS = (
  6    "unison", "minor 2nd", "major 2nd",
  7    "minor 3rd", "major 3rd", "perfect 4th",
  8    "diminished 5th", "perfect 5th", "minor 6th",
  9    "major 6th", "minor 7th", "major 7th"
 10    )
 11TOTAL_TONES_COUNT = 12
 12
 13
 14class Tone:
 15
 16    def __init__(self, note):
 17        self.note = note
 18    
 19    def __str__(self):
 20        return self.note
 21       
 22    def __add__(self, other):
 23        if isinstance(other, Tone):
 24            return Chord(self, other)
 25        elif isinstance(other, Interval):
 26            note_idx = (DEFINED_TONES.index(self.note) 
 27                        + other.number_of_semitones)
 28            return Tone(DEFINED_TONES[note_idx % TOTAL_TONES_COUNT])
 29        
 30    def __sub__(self, other):
 31        if isinstance(other, Tone):
 32            return Interval(DEFINED_TONES.index(self.note) 
 33                            - DEFINED_TONES.index(other.note))
 34        elif isinstance(other, Interval):
 35            note_idx = (DEFINED_TONES.index(self.note) 
 36                        - other.number_of_semitones)
 37            return Tone(DEFINED_TONES[note_idx % TOTAL_TONES_COUNT])
 38
 39    def __eq__(self, value):
 40        return self.note == value.note
 41        
 42
 43class Interval:
 44
 45    def __init__(self, number_of_semitones):
 46        self.number_of_semitones = number_of_semitones % TOTAL_TONES_COUNT
 47        self.semitone = DEFINED_INTERVALS[self.number_of_semitones]
 48    
 49    def __str__(self):
 50        return self.semitone
 51    
 52    def __add__(self, other):
 53        if isinstance(other, Interval):
 54            return Interval(self.number_of_semitones 
 55                            + other.number_of_semitones)
 56        elif isinstance(other, Tone):
 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.number_of_semitones)
 65
 66    
 67class Chord:
 68
 69    def __init__(self, root, *tones):
 70        self.root = root
 71        self.secondary_tones = []
 72        for tone in tones:
 73            if tone not in self.secondary_tones:
 74                self.secondary_tones.append(tone)        
 75        if root in self.secondary_tones:
 76            self.secondary_tones.remove(root)
 77        if not self.secondary_tones:
 78            raise TypeError("Cannot have a chord made of only 1 unique tone")
 79        self.secondary_tones.sort(key=lambda x: DEFINED_TONES.index(x.note))
 80
 81    def __str__(self):
 82        tones_concat = "-".join(tone.note for tone in self.secondary_tones)
 83        return f"{str(self.root)}-{tones_concat}"
 84    
 85    def __add__(self, other):
 86        if isinstance(other, Tone):
 87            return Chord(self.root,
 88                         *self.secondary_tones,
 89                         other)
 90        elif isinstance(other, Chord):
 91            return Chord(self.root,
 92                         *self.secondary_tones,
 93                         other.root,
 94                         *other.secondary_tones)
 95    
 96    def __sub__(self, other):
 97        if not isinstance(other, Tone):
 98            return
 99        if (other not in self.secondary_tones and 
100            not (other == self.root)):
101            raise TypeError(
102                f"Cannot remove tone {str(other)} from chord {str(self)}"
103                )
104        if other == self.root:
105            return Chord(self.secondary_tones[0],
106                         *self.secondary_tones[1:])
107        else:
108            modified_secondary_tones = self.secondary_tones[:]
109            modified_secondary_tones.remove(other)
110            return Chord(self.root,
111                         *modified_secondary_tones)
112
113    def transposed(self, interval):
114        modified_secondary_tones = [
115            (tone + interval) for tone in self.secondary_tones
116            ]
117        return Chord(self.root + interval, *modified_secondary_tones)
118
119    def is_minor(self):
120        root_idx = DEFINED_TONES.index(self.root.note)
121        minor_3rd_diff = DEFINED_INTERVALS.index("minor 3rd")
122        for tone in self.secondary_tones:
123            tone_idx = DEFINED_TONES.index(tone.note)
124            if abs(root_idx - tone_idx) == minor_3rd_diff:
125                return True
126        return False
127
128    def is_major(self):
129        root_idx = DEFINED_TONES.index(self.root.note)
130        major_3rd_diff = DEFINED_INTERVALS.index("major 3rd")
131        for tone in self.secondary_tones:
132            tone_idx = DEFINED_TONES.index(tone.note)
133            if abs(root_idx - tone_idx) == major_3rd_diff:
134                return True
135        return False
136
137    def is_power_chord(self):
138        return not (self.is_major() or self.is_minor())

.F..FFF..F...........FFF.............
======================================================================
FAIL: test_chord_ordering (test.TestBasicChordFunctionality.test_chord_ordering)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 65, in test_chord_ordering
self.assertEqual(str(f_sixth_ninth_chord), "F-A-C-E")
AssertionError: 'F-C-E-A' != 'F-A-C-E'
- F-C-E-A
? --
+ F-A-C-E
? ++

======================================================================
FAIL: test_is_major (test.TestBasicChordFunctionality.test_is_major)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 107, in test_is_major
self.assertTrue(a_major_chord.is_major())
AssertionError: False is not true

======================================================================
FAIL: test_is_minor (test.TestBasicChordFunctionality.test_is_minor)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 90, in test_is_minor
self.assertTrue(a_minor_chord.is_minor())
AssertionError: False is not true

======================================================================
FAIL: test_is_power_chord (test.TestBasicChordFunctionality.test_is_power_chord)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 116, in test_is_power_chord
self.assertFalse(a_minor_chord.is_power_chord())
AssertionError: True is not false

======================================================================
FAIL: test_transposed_negative_overflow (test.TestBasicChordFunctionality.test_transposed_negative_overflow)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 152, in test_transposed_negative_overflow
self.assertEqual(str(result_chord), "G#-B-D#")
AssertionError: 'G#-D#-B' != 'G#-B-D#'
- G#-D#-B
? --
+ G#-B-D#
? ++

======================================================================
FAIL: test_add_tone_to_chord (test.TestOperations.test_add_tone_to_chord)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 254, in test_add_tone_to_chord
self.assertEqual(str(result_chord), "F-A-C-D")
AssertionError: 'F-C-D-A' != 'F-A-C-D'
- F-C-D-A
? --
+ F-A-C-D
? ++

======================================================================
FAIL: test_add_tone_to_chord_existing_tone (test.TestOperations.test_add_tone_to_chord_existing_tone)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 270, in test_add_tone_to_chord_existing_tone
self.assertEqual(str(result_chord), "F-G#-C")
AssertionError: 'F-C-G#' != 'F-G#-C'
- F-C-G#
+ F-G#-C

======================================================================
FAIL: test_add_tone_to_chord_order (test.TestOperations.test_add_tone_to_chord_order)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 261, in test_add_tone_to_chord_order
self.assertEqual(str(result_chord), "F-G-A-C")
AssertionError: 'F-C-G-A' != 'F-G-A-C'
- F-C-G-A
? --
+ F-G-A-C
? ++

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

FAILED (failures=8)

Дискусия
Георги Кунчев
04.11.2024 13:40

Усещам, че се стремиш стриктно да спазваш правилото за 79 символа на ред. Това е чудесно, но имай предвид, че в днешно време повечето хора се стремят да използват 100 или 120 като лимит, защото 79 е легаси и е прекалено малко. Оценявам факта, че всички пренасяния спазват стриктно PEP8 правилата (или поне не видях отклонения). Ако решиш да си до 79 символа - супер, но ако ти е прекалено изкуствено да пренасяш само заради някакви си 4-5 символа отгоре, специално в нашия курс няма да се оплакваме. Като цяло имаш много чист стил и кодът се чете сам. Браво!
История

f1DEFINED_TONES = (f1DEFINED_TONES = (
2    "C", "C#", "D", "D#", "E", "F",2    "C", "C#", "D", "D#", "E", "F",
3    "F#", "G", "G#", "A", "A#", "B"3    "F#", "G", "G#", "A", "A#", "B"
4    )4    )
5DEFINED_INTERVALS = (5DEFINED_INTERVALS = (
6    "unison", "minor 2nd", "major 2nd",6    "unison", "minor 2nd", "major 2nd",
7    "minor 3rd", "major 3rd", "perfect 4th",7    "minor 3rd", "major 3rd", "perfect 4th",
8    "diminished 5th", "perfect 5th", "minor 6th",8    "diminished 5th", "perfect 5th", "minor 6th",
9    "major 6th", "minor 7th", "major 7th"9    "major 6th", "minor 7th", "major 7th"
10    )10    )
11TOTAL_TONES_COUNT = 1211TOTAL_TONES_COUNT = 12
1212
1313
14class Tone:14class Tone:
1515
16    def __init__(self, note):16    def __init__(self, note):
17        self.note = note17        self.note = note
18    18    
19    def __str__(self):19    def __str__(self):
20        return self.note20        return self.note
21       21       
22    def __add__(self, other):22    def __add__(self, other):
23        if isinstance(other, Tone):23        if isinstance(other, Tone):
24            return Chord(self, other)24            return Chord(self, other)
25        elif isinstance(other, Interval):25        elif isinstance(other, Interval):
26            note_idx = (DEFINED_TONES.index(self.note) 26            note_idx = (DEFINED_TONES.index(self.note) 
27                        + other.number_of_semitones)27                        + other.number_of_semitones)
28            return Tone(DEFINED_TONES[note_idx % TOTAL_TONES_COUNT])28            return Tone(DEFINED_TONES[note_idx % TOTAL_TONES_COUNT])
29        29        
30    def __sub__(self, other):30    def __sub__(self, other):
31        if isinstance(other, Tone):31        if isinstance(other, Tone):
32            return Interval(DEFINED_TONES.index(self.note) 32            return Interval(DEFINED_TONES.index(self.note) 
33                            - DEFINED_TONES.index(other.note))33                            - DEFINED_TONES.index(other.note))
34        elif isinstance(other, Interval):34        elif isinstance(other, Interval):
35            note_idx = (DEFINED_TONES.index(self.note) 35            note_idx = (DEFINED_TONES.index(self.note) 
36                        - other.number_of_semitones)36                        - other.number_of_semitones)
37            return Tone(DEFINED_TONES[note_idx % TOTAL_TONES_COUNT])37            return Tone(DEFINED_TONES[note_idx % TOTAL_TONES_COUNT])
3838
39    def __eq__(self, value):39    def __eq__(self, value):
40        return self.note == value.note40        return self.note == value.note
41        41        
4242
43class Interval:43class Interval:
4444
45    def __init__(self, number_of_semitones):45    def __init__(self, number_of_semitones):
46        self.number_of_semitones = number_of_semitones % TOTAL_TONES_COUNT46        self.number_of_semitones = number_of_semitones % TOTAL_TONES_COUNT
47        self.semitone = DEFINED_INTERVALS[self.number_of_semitones]47        self.semitone = DEFINED_INTERVALS[self.number_of_semitones]
48    48    
49    def __str__(self):49    def __str__(self):
50        return self.semitone50        return self.semitone
51    51    
52    def __add__(self, other):52    def __add__(self, other):
53        if isinstance(other, Interval):53        if isinstance(other, Interval):
54            return Interval(self.number_of_semitones 54            return Interval(self.number_of_semitones 
55                            + other.number_of_semitones)55                            + other.number_of_semitones)
56        elif isinstance(other, Tone):56        elif isinstance(other, Tone):
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.number_of_semitones)64        return Interval(-self.number_of_semitones)
6565
66    66    
67class Chord:67class Chord:
6868
n69    min_tones_count = 2n
70 
71    def __init__(self, root, *tones):69    def __init__(self, root, *tones):
72        self.root = root70        self.root = root
73        self.secondary_tones = []71        self.secondary_tones = []
74        for tone in tones:72        for tone in tones:
75            if tone not in self.secondary_tones:73            if tone not in self.secondary_tones:
76                self.secondary_tones.append(tone)        74                self.secondary_tones.append(tone)        
77        if root in self.secondary_tones:75        if root in self.secondary_tones:
78            self.secondary_tones.remove(root)76            self.secondary_tones.remove(root)
79        if not self.secondary_tones:77        if not self.secondary_tones:
80            raise TypeError("Cannot have a chord made of only 1 unique tone")78            raise TypeError("Cannot have a chord made of only 1 unique tone")
81        self.secondary_tones.sort(key=lambda x: DEFINED_TONES.index(x.note))79        self.secondary_tones.sort(key=lambda x: DEFINED_TONES.index(x.note))
8280
83    def __str__(self):81    def __str__(self):
84        tones_concat = "-".join(tone.note for tone in self.secondary_tones)82        tones_concat = "-".join(tone.note for tone in self.secondary_tones)
85        return f"{str(self.root)}-{tones_concat}"83        return f"{str(self.root)}-{tones_concat}"
86    84    
87    def __add__(self, other):85    def __add__(self, other):
88        if isinstance(other, Tone):86        if isinstance(other, Tone):
89            return Chord(self.root,87            return Chord(self.root,
n90                        *self.secondary_tones,n88                         *self.secondary_tones,
91                        other)89                         other)
92        elif isinstance(other, Chord):90        elif isinstance(other, Chord):
93            return Chord(self.root,91            return Chord(self.root,
n94                        *self.secondary_tones,n92                         *self.secondary_tones,
95                        other.root,93                         other.root,
96                        *other.secondary_tones)94                         *other.secondary_tones)
97    95    
98    def __sub__(self, other):96    def __sub__(self, other):
99        if not isinstance(other, Tone):97        if not isinstance(other, Tone):
100            return98            return
101        if (other not in self.secondary_tones and 99        if (other not in self.secondary_tones and 
102            not (other == self.root)):100            not (other == self.root)):
103            raise TypeError(101            raise TypeError(
104                f"Cannot remove tone {str(other)} from chord {str(self)}"102                f"Cannot remove tone {str(other)} from chord {str(self)}"
105                )103                )
n106        if (len(self.secondary_tones) < Chord.min_tones_count):n
107            raise TypeError("Cannot have a chord made of only 1 unique tone")
108        if other == self.root:104        if other == self.root:
109            return Chord(self.secondary_tones[0],105            return Chord(self.secondary_tones[0],
n110                        *self.secondary_tones[1:])n106                         *self.secondary_tones[1:])
111        else:107        else:
112            modified_secondary_tones = self.secondary_tones[:]108            modified_secondary_tones = self.secondary_tones[:]
113            modified_secondary_tones.remove(other)109            modified_secondary_tones.remove(other)
114            return Chord(self.root,110            return Chord(self.root,
t115                        *modified_secondary_tones)t111                         *modified_secondary_tones)
116112
117    def transposed(self, interval):113    def transposed(self, interval):
118        modified_secondary_tones = [114        modified_secondary_tones = [
119            (tone + interval) for tone in self.secondary_tones115            (tone + interval) for tone in self.secondary_tones
120            ]116            ]
121        return Chord(self.root + interval, *modified_secondary_tones)117        return Chord(self.root + interval, *modified_secondary_tones)
122118
123    def is_minor(self):119    def is_minor(self):
124        root_idx = DEFINED_TONES.index(self.root.note)120        root_idx = DEFINED_TONES.index(self.root.note)
125        minor_3rd_diff = DEFINED_INTERVALS.index("minor 3rd")121        minor_3rd_diff = DEFINED_INTERVALS.index("minor 3rd")
126        for tone in self.secondary_tones:122        for tone in self.secondary_tones:
127            tone_idx = DEFINED_TONES.index(tone.note)123            tone_idx = DEFINED_TONES.index(tone.note)
128            if abs(root_idx - tone_idx) == minor_3rd_diff:124            if abs(root_idx - tone_idx) == minor_3rd_diff:
129                return True125                return True
130        return False126        return False
131127
132    def is_major(self):128    def is_major(self):
133        root_idx = DEFINED_TONES.index(self.root.note)129        root_idx = DEFINED_TONES.index(self.root.note)
134        major_3rd_diff = DEFINED_INTERVALS.index("major 3rd")130        major_3rd_diff = DEFINED_INTERVALS.index("major 3rd")
135        for tone in self.secondary_tones:131        for tone in self.secondary_tones:
136            tone_idx = DEFINED_TONES.index(tone.note)132            tone_idx = DEFINED_TONES.index(tone.note)
137            if abs(root_idx - tone_idx) == major_3rd_diff:133            if abs(root_idx - tone_idx) == major_3rd_diff:
138                return True134                return True
139        return False135        return False
140136
141    def is_power_chord(self):137    def is_power_chord(self):
142        return not (self.is_major() or self.is_minor())138        return not (self.is_major() or self.is_minor())
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op