Домашни > Pitches love the D > Решения > Решението на Росица Илиева

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

9 точки общо

34 успешни теста
3 неуспешни теста
Код

  1class Tone:
  2    """A class that represents a musical tone."""
  3    TONES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
  4
  5    def __init__(self, tone):
  6        if tone not in Tone.TONES or not tone:
  7            raise ValueError("Invalid input for tone")
  8        self.tone = tone
  9
 10    def __str__(self):
 11        return self.tone
 12
 13    def __eq__(self, other):
 14        if isinstance(other, Tone):
 15            return self.tone == other.tone
 16        return False
 17
 18    def __add__(self, other):
 19        if isinstance(other, Interval):
 20            return self.add_interval(other)
 21        if isinstance(other, Tone):
 22            return Chord(self, other)
 23        raise TypeError("Invalid operation")
 24
 25    def __sub__(self, other):
 26        if isinstance(other, Interval):
 27            return self.sub_interval(other)
 28        if isinstance(self, Tone) and isinstance(other, Tone):
 29            return Interval(abs(self.TONES.index(self.tone) - other.TONES.index(other.tone)))
 30        raise TypeError("Invalid operation")
 31
 32    def add_interval(self, other):
 33        """A method that adds an interval to a tone and returns new tone."""
 34        if isinstance(other, Tone):
 35            raise TypeError("Invalid operation")
 36        elif isinstance(self, Tone) and isinstance(other, Interval):
 37            cur_tone_index = self.TONES.index(self.tone)
 38            new_index = (cur_tone_index + other.number_of_semitones) % len(self.TONES)
 39            return Tone(self.TONES[new_index])
 40        raise TypeError("Invalid operation")
 41
 42    def sub_interval(self, other):
 43        """A method that subtracts an interval to a tone and returns new tone."""
 44        if isinstance(self, Tone) and isinstance(other, Interval):
 45            cur_tone_index = self.TONES.index(self.tone)
 46            new_index = abs((cur_tone_index - other.number_of_semitones) % len(self.TONES))
 47            return Tone(self.TONES[new_index])
 48        if isinstance(other, Tone):
 49            raise TypeError("Invalid operation")
 50        raise TypeError("Invalid operation")
 51
 52
 53class Interval:
 54    """A class that represents a musical interval."""
 55    INTERVALS = ("unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th",
 56                 "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th")
 57    INTERVALS_LENGTH = len(INTERVALS)
 58
 59    def __init__(self, number_of_semitones):
 60        if not isinstance(number_of_semitones, int):
 61            raise TypeError("Invalid input for number of semitones")
 62        self.number_of_semitones = number_of_semitones % Interval.INTERVALS_LENGTH
 63
 64    def __str__(self):
 65        return self.INTERVALS[self.number_of_semitones % Interval.INTERVALS_LENGTH]
 66
 67    def __add__(self, other):
 68        if isinstance(self, Interval) and isinstance(other, Interval):
 69            return Interval(self.number_of_semitones + other.number_of_semitones)
 70        raise TypeError("Invalid operation")
 71
 72    def __sub__(self, other):
 73        raise TypeError("Invalid operation")
 74
 75    def __neg__(self):
 76        return Interval(-self.number_of_semitones)
 77
 78
 79class Chord:
 80    """A class that represents a musical chord."""
 81
 82    def __init__(self, *args):
 83        if len(args) == 0:
 84            raise TypeError("Empty chord")
 85        self.root = args[0].tone
 86        self.all_tones = []
 87        for cur_tone in args:
 88            if cur_tone not in self.all_tones:
 89                self.all_tones.append(cur_tone)
 90
 91        if len(self.all_tones) == 1:
 92            raise TypeError("Cannot have a chord made of only 1 unique tone")
 93        
 94        root_index = Tone.TONES.index(self.root)
 95        sorted_all_tones = []
 96        sorted_all_tones.append(Tone.TONES[root_index])
 97
 98        for i in range(1, len(Tone.TONES)):
 99            current_index = (root_index + i) % len(Tone.TONES)
100            current_tone = Tone.TONES[current_index]
101            if Tone(current_tone) in self.all_tones:
102                sorted_all_tones.append(current_tone)
103        self.all_tones = sorted_all_tones
104
105    def __str__(self):
106        return "-".join(str(cur_tone) for cur_tone in self.all_tones)
107
108    def is_minor(self):
109        """A method that checks if there is a tone in the chord that together
110           with the root tone form minor 3rd interval. Returns a boolean."""
111        root_index = Tone.TONES.index(self.root)
112        for tone in self.all_tones:
113            tone_index = Tone.TONES.index(tone)
114            if tone == self.root:
115                continue
116            elif tone_index - root_index == 3:
117                return True
118            elif (root_index - tone_index) % 12 == 9:
119                return True
120        return False
121
122    def is_major(self):
123        """A method that checks if there is a tone in the chord that together
124           with the root tone form major 3rd interval. Returns a boolean."""
125        root_index = Tone.TONES.index(self.root)
126        for tone in self.all_tones:
127            tone_index = Tone.TONES.index(tone)
128            if tone == self.root:
129                continue
130            elif tone_index - root_index == 4:
131                return True
132            elif (root_index - tone_index) % 12 == 9:
133                return True
134        return False
135
136    def is_power_chord(self):
137        """A method that checks if a chord does not contain a tone that, together 
138           with the root, forms a minor 3rd or a major 3rd. Returns a boolean."""
139        if not self.is_major() and not self.is_minor():
140            return True
141        return False
142
143    def __add__(self, other):
144        if isinstance(other, Tone):
145            return Chord(*map(Tone, self.all_tones + [other.tone]))
146        if isinstance(other, Chord):
147            result = []
148            for tone in self.all_tones:
149                result.append(Tone(tone))
150            for tone in other.all_tones:
151                result.append(Tone(tone))
152            return Chord(*result)
153        raise TypeError("Invalid operation")
154
155    def __sub__(self, other):
156        if isinstance(other, Tone):
157            result = []
158            additional_tone = Tone(other.tone)
159            result.append(Tone(other.tone))
160            for tone in self.all_tones:
161                if Tone(tone) == additional_tone:
162                    result.remove(additional_tone)
163                else:
164                    result.append(Tone(tone))
165            if additional_tone in result:
166                raise TypeError(f"Cannot remove tone {Tone(other.tone)} from chord {str(self)}")
167            return Chord(*result)
168        raise TypeError("Invalid operation")
169
170    def transposed(self, interval):
171        """A method that shifts each of its tones by the same interval."""
172        transposed_tones = [Tone(tone) + interval for tone in self.all_tones]
173        return Chord(*transposed_tones)

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

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

======================================================================
FAIL: test_tone_subtraction_inverse (test.TestOperations.test_tone_subtraction_inverse)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 178, in test_tone_subtraction_inverse
self.assertEqual(str(perfect_4th), "perfect 4th")
AssertionError: 'perfect 5th' != 'perfect 4th'
- perfect 5th
? ^
+ perfect 4th
? ^

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

FAILED (failures=3)

Дискусия
Росица Илиева
04.11.2024 16:33

Много благодаря!
Георги Кунчев
04.11.2024 16:24

Ето пример: ``` reference_list = ['най-малко', 'по-малко', 'нещо', 'по-голямо', 'най-голямо'] to_be_sorted = ['най-голямо', 'нещо', 'по-малко'] print(sorted(to_be_sorted, key=lambda x: reference_list.index(x))) # ['по-малко', 'нещо', 'най-голямо'] ``` `key` атрибутът на `sorted` очаква функция, която връща някаква стойност. Тази стойност се използва за сортирането вместо самите стойности в `to_be_sorted`. Създавайки функцията `lambda x: reference_list.index(x)`, просто връщаме индекса на даден елемент в списъка `reference_list`. Ако сортираме `to_be_sorted`, използвайки не стойностите в него, а резултата от функцията, извикана със конкретния елемент, всъщност сортираме елементите сравнявайки индексите им в списъка `reference_list`. В горния пример индексите са съответно: 4 - най-голямо (4 е резултатът от `reference_list.index('най-голямо')`; 2 - нещо (2 е резултатът от `reference_list.index('нещо')`; 1 - по-малко (1 е резултатът от `reference_list.index('по-малко')`. Тъй като сортирането не става по стойността на текста, а по индекса (4, 2, 1), резултатът е ['по-малко', 'нещо', 'най-голямо']
Росица Илиева
04.11.2024 16:04

Може ли да ме насочите повече как трябва да сортирам с sorted(some_list, key=lambda x: ordered_list.index(x)), тъй като ламбда функциите доста ме объркват, и както и да се опитвам да го направя по този начин, не се получава?
История

f1class Tone:f1class Tone:
2    """A class that represents a musical tone."""2    """A class that represents a musical tone."""
n3    tones = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")n3    TONES = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
4 
4    def __init__(self, tone):5    def __init__(self, tone):
n5        if tone not in Tone.tones or not tone:n6        if tone not in Tone.TONES or not tone:
6            raise ValueError("Invalid input for tone")7            raise ValueError("Invalid input for tone")
7        self.tone = tone8        self.tone = tone
89
9    def __str__(self):10    def __str__(self):
n10        return f"{self.tone}"n11        return self.tone
1112
12    def __eq__(self, other):13    def __eq__(self, other):
13        if isinstance(other, Tone):14        if isinstance(other, Tone):
14            return self.tone == other.tone15            return self.tone == other.tone
15        return False16        return False
1617
17    def __add__(self, other):18    def __add__(self, other):
18        if isinstance(other, Interval):19        if isinstance(other, Interval):
19            return self.add_interval(other)20            return self.add_interval(other)
20        if isinstance(other, Tone):21        if isinstance(other, Tone):
21            return Chord(self, other)22            return Chord(self, other)
nn23        raise TypeError("Invalid operation")
2224
23    def __sub__(self, other):25    def __sub__(self, other):
24        if isinstance(other, Interval):26        if isinstance(other, Interval):
25            return self.sub_interval(other)27            return self.sub_interval(other)
26        if isinstance(self, Tone) and isinstance(other, Tone):28        if isinstance(self, Tone) and isinstance(other, Tone):
n27            return Interval(abs(self.tones.index(self.tone) - other.tones.index(other.tone)))n29            return Interval(abs(self.TONES.index(self.tone) - other.TONES.index(other.tone)))
30        raise TypeError("Invalid operation")
2831
29    def add_interval(self, other):32    def add_interval(self, other):
nn33        """A method that adds an interval to a tone and returns new tone."""
30        if isinstance(other, Tone):34        if isinstance(other, Tone):
31            raise TypeError("Invalid operation")35            raise TypeError("Invalid operation")
32        elif isinstance(self, Tone) and isinstance(other, Interval):36        elif isinstance(self, Tone) and isinstance(other, Interval):
n33            cur_tone_index = self.tones.index(self.tone)n37            cur_tone_index = self.TONES.index(self.tone)
34            new_index = (cur_tone_index + other.number_of_semitones) % len(self.tones)38            new_index = (cur_tone_index + other.number_of_semitones) % len(self.TONES)
35            return Tone(self.tones[new_index])39            return Tone(self.TONES[new_index])
40        raise TypeError("Invalid operation")
3641
37    def sub_interval(self, other):42    def sub_interval(self, other):
nn43        """A method that subtracts an interval to a tone and returns new tone."""
38        if isinstance(self, Tone) and isinstance(other, Interval):44        if isinstance(self, Tone) and isinstance(other, Interval):
n39            cur_tone_index = self.tones.index(self.tone)n45            cur_tone_index = self.TONES.index(self.tone)
40            new_index = abs((cur_tone_index - other.number_of_semitones) % len(self.tones))46            new_index = abs((cur_tone_index - other.number_of_semitones) % len(self.TONES))
41            return Tone(self.tones[new_index])47            return Tone(self.TONES[new_index])
42        if isinstance(other, Tone):48        if isinstance(other, Tone):
43            raise TypeError("Invalid operation")49            raise TypeError("Invalid operation")
nn50        raise TypeError("Invalid operation")
51 
4452
45class Interval:53class Interval:
46    """A class that represents a musical interval."""54    """A class that represents a musical interval."""
n47    intervals = {0 : "unison", 1 : "minor 2nd", 2 : "major 2nd", 3 : "minor 3rd", 4 : "major 3rd", 5 : "perfect 4th",n55    INTERVALS = ("unison", "minor 2nd", "major 2nd", "minor 3rd", "major 3rd", "perfect 4th",
48                 6 : "diminished 5th", 7 : "perfect 5th", 8 : "minor 6th", 9 : "major 6th", 10 : "minor 7th", 11 : "major 7th"}56                 "diminished 5th", "perfect 5th", "minor 6th", "major 6th", "minor 7th", "major 7th")
57    INTERVALS_LENGTH = len(INTERVALS)
4958
50    def __init__(self, number_of_semitones):59    def __init__(self, number_of_semitones):
51        if not isinstance(number_of_semitones, int):60        if not isinstance(number_of_semitones, int):
52            raise TypeError("Invalid input for number of semitones")61            raise TypeError("Invalid input for number of semitones")
n53        self.number_of_semitones = number_of_semitones % 12n62        self.number_of_semitones = number_of_semitones % Interval.INTERVALS_LENGTH
5463
55    def __str__(self):64    def __str__(self):
n56        return f"{self.intervals[self.number_of_semitones % 12]}"n65        return self.INTERVALS[self.number_of_semitones % Interval.INTERVALS_LENGTH]
57    66 
58    def __add__(self, other):67    def __add__(self, other):
59        if isinstance(self, Interval) and isinstance(other, Interval):68        if isinstance(self, Interval) and isinstance(other, Interval):
60            return Interval(self.number_of_semitones + other.number_of_semitones)69            return Interval(self.number_of_semitones + other.number_of_semitones)
n61        n70        raise TypeError("Invalid operation")
71 
72    def __sub__(self, other):
73        raise TypeError("Invalid operation")
74 
62    def __neg__(self):75    def __neg__(self):
63        return Interval(-self.number_of_semitones)76        return Interval(-self.number_of_semitones)
n64    n77 
78 
65class Chord:79class Chord:
n66    """A class that represents a musical chord."""   n80    """A class that represents a musical chord."""
81 
67    def __init__(self, *args):82    def __init__(self, *args):
68        if len(args) == 0:83        if len(args) == 0:
69            raise TypeError("Empty chord")84            raise TypeError("Empty chord")
n70        self.root = str(args[0])n85        self.root = args[0].tone
71        self.all_thones = []86        self.all_tones = []
72        for cur_tone in args:87        for cur_tone in args:
n73            if cur_tone not in self.all_thones:n88            if cur_tone not in self.all_tones:
74                self.all_thones.append(cur_tone)89                self.all_tones.append(cur_tone)
7590
n76        if len(self.all_thones) == 1:n91        if len(self.all_tones) == 1:
77            raise TypeError("Cannot have a chord made of only 1 unique tone")92            raise TypeError("Cannot have a chord made of only 1 unique tone")
78        93        
n79        root_index = Tone.tones.index(self.root)n94        root_index = Tone.TONES.index(self.root)
80        sorted_all_thones = []95        sorted_all_tones = []
81        sorted_all_thones.append(Tone.tones[root_index])96        sorted_all_tones.append(Tone.TONES[root_index])
8297
n83        for i in range(1, len(Tone.tones)):n98        for i in range(1, len(Tone.TONES)):
84            current_index = (root_index + i) % len(Tone.tones)99            current_index = (root_index + i) % len(Tone.TONES)
85            current_tone = Tone.tones[current_index]100            current_tone = Tone.TONES[current_index]
86            if Tone(current_tone) in self.all_thones:101            if Tone(current_tone) in self.all_tones:
87                sorted_all_thones.append(current_tone)102                sorted_all_tones.append(current_tone)
88        self.all_thones = sorted_all_thones103        self.all_tones = sorted_all_tones
89             104 
90    def __str__(self):105    def __str__(self):
n91        return "-".join(str(cur_tone) for cur_tone in self.all_thones)n106        return "-".join(str(cur_tone) for cur_tone in self.all_tones)
92    107 
93    def is_minor(self):108    def is_minor(self):
nn109        """A method that checks if there is a tone in the chord that together
110           with the root tone form minor 3rd interval. Returns a boolean."""
94        root_index = Tone.tones.index(self.root)111        root_index = Tone.TONES.index(self.root)
95        for tone in self.all_thones:112        for tone in self.all_tones:
96            tone_index = Tone.tones.index(tone)113            tone_index = Tone.TONES.index(tone)
97            if tone == self.root:114            if tone == self.root:
98                continue115                continue
99            elif tone_index - root_index == 3:116            elif tone_index - root_index == 3:
100                return True117                return True
n101            elif tone_index in (0, 1, 2) and root_index == tone_index + 9:n118            elif (root_index - tone_index) % 12 == 9:
102                return True
103            elif tone_index in (9, 10, 11) and root_index == tone_index - 9:
104                return True119                return True
105        return False120        return False
n106    n121 
107    def is_major(self):122    def is_major(self):
nn123        """A method that checks if there is a tone in the chord that together
124           with the root tone form major 3rd interval. Returns a boolean."""
108        root_index = Tone.tones.index(self.root)125        root_index = Tone.TONES.index(self.root)
109        for tone in self.all_thones:126        for tone in self.all_tones:
110            tone_index = Tone.tones.index(tone)127            tone_index = Tone.TONES.index(tone)
111            if tone == self.root:128            if tone == self.root:
112                continue129                continue
113            elif tone_index - root_index == 4:130            elif tone_index - root_index == 4:
114                return True131                return True
n115            elif tone_index in (0, 1, 2, 3) and root_index == tone_index + 8:n132            elif (root_index - tone_index) % 12 == 9:
116                return True
117            elif tone_index in (8, 9, 10, 11) and root_index == tone_index - 8:
118                return True133                return True
119        return False134        return False
120135
121    def is_power_chord(self):136    def is_power_chord(self):
nn137        """A method that checks if a chord does not contain a tone that, together 
138           with the root, forms a minor 3rd or a major 3rd. Returns a boolean."""
122        if self.is_major() is False and self.is_minor() is False:139        if not self.is_major() and not self.is_minor():
123            return True140            return True
124        return False141        return False
n125       n142 
126    def __add__(self, other):143    def __add__(self, other):
127        if isinstance(other, Tone):144        if isinstance(other, Tone):
n128            result = []n145            return Chord(*map(Tone, self.all_tones + [other.tone]))
129            for tone in self.all_thones:
130                result.append(Tone(tone))
131            result.append(Tone(other.tone))
132            return Chord(*result)
133        if isinstance(other, Chord):146        if isinstance(other, Chord):
134            result = []147            result = []
n135            for tone in self.all_thones:n148            for tone in self.all_tones:
136                result.append(Tone(tone))149                result.append(Tone(tone))
n137            for tone in other.all_thones:n150            for tone in other.all_tones:
138                result.append(Tone(tone))151                result.append(Tone(tone))
139            return Chord(*result)152            return Chord(*result)
n140               n153        raise TypeError("Invalid operation")
154 
141    def __sub__(self, other):155    def __sub__(self, other):
142        if isinstance(other, Tone):156        if isinstance(other, Tone):
143            result = []157            result = []
144            additional_tone = Tone(other.tone)158            additional_tone = Tone(other.tone)
145            result.append(Tone(other.tone))159            result.append(Tone(other.tone))
n146            for tone in self.all_thones:n160            for tone in self.all_tones:
147                if Tone(tone) == additional_tone:161                if Tone(tone) == additional_tone:
148                    result.remove(additional_tone)162                    result.remove(additional_tone)
149                else:163                else:
150                    result.append(Tone(tone))164                    result.append(Tone(tone))
151            if additional_tone in result:165            if additional_tone in result:
n152                raise TypeError(f"Cannot remove tone {Tone(other.tone)} from chord {Chord(*(Tone(tone) for tone in self.all_thones))}")n166                raise TypeError(f"Cannot remove tone {Tone(other.tone)} from chord {str(self)}")
153            return Chord(*result)167            return Chord(*result)
nn168        raise TypeError("Invalid operation")
154169
155    def transposed(self, interval):170    def transposed(self, interval):
tt171        """A method that shifts each of its tones by the same interval."""
156        transposed_tones = [Tone(tone) + interval for tone in self.all_thones]172        transposed_tones = [Tone(tone) + interval for tone in self.all_tones]
157        return Chord(*transposed_tones)173        return Chord(*transposed_tones)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op