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

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

10 точки общо

36 успешни теста
1 неуспешни теста
Код

  1"""
  2    This module provides classes and functions for representing musical
  3    tones, intervals, and chords. It allows for operations such as
  4    adding tones to chords, removing tones from chords, and
  5    transposing chords using intervals.
  6"""
  7
  8
  9MINIMUM_UNIQUE_TONES = 1
 10TOTAL_TONES = 12
 11MINOR_THIRD_INTERVAL = 3
 12MAJOR_THIRD_INTERVAL = 4
 13
 14
 15class Tone:
 16    """Represent a musical tone and methods to perform operations with intervals and other tones."""
 17    def __init__(self, name):
 18        self.name = name
 19
 20    def __str__(self):
 21        return self.name
 22
 23    @property
 24    def tone_index(self):
 25        return Chord.LIST_OF_TONES.index(self.name)
 26
 27    def __add__(self, other):
 28        if isinstance(other, Interval):
 29            new_tone_index = (self.tone_index + other.number_of_semitones) % TOTAL_TONES
 30            return Tone(Chord.LIST_OF_TONES[new_tone_index])
 31        return Chord(self, other)
 32
 33    def __radd__(self, other):
 34        raise TypeError("Invalid operation")
 35
 36    def __sub__(self, other):
 37        if isinstance(other, Interval):
 38            new_tone_index = (self.tone_index - other.number_of_semitones) % TOTAL_TONES
 39            return Tone(Chord.LIST_OF_TONES[new_tone_index])
 40        distance = (self.tone_index - other.tone_index) % TOTAL_TONES
 41        return Interval(distance)
 42
 43    def __rsub__(self, other):
 44        raise TypeError("Invalid operation")
 45
 46
 47class Interval:
 48    """Represent a musical interval in semitones."""
 49    INTERVALS_NAME = [
 50        "unison",
 51        "minor 2nd",
 52        "major 2nd",
 53        "minor 3rd",
 54        "major 3rd",
 55        "perfect 4th",
 56        "diminished 5th",
 57        "perfect 5th",
 58        "minor 6th",
 59        "major 6th",
 60        "minor 7th",
 61        "major 7th"
 62    ]
 63
 64    def __init__(self, number_of_semitones):
 65        self.number_of_semitones = number_of_semitones % TOTAL_TONES
 66
 67    def __neg__(self):
 68        return Interval(-self.number_of_semitones)
 69
 70    def __str__(self):
 71        return f"{self.INTERVALS_NAME[self.number_of_semitones]}"
 72
 73    def __add__(self, other):
 74        new_semitones = (self.number_of_semitones + other.number_of_semitones) % TOTAL_TONES
 75        return Interval(new_semitones)
 76
 77
 78class Chord:
 79    """Represent a musical chord of multiple tones."""
 80    LIST_OF_TONES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
 81
 82    def __init__(self, root, *arg):
 83        self.tones = [root]
 84        for tone in arg:
 85            if tone.name not in [t.name for t in self.tones]:
 86                self.tones.append(tone)
 87
 88        if len(self.tones) == MINIMUM_UNIQUE_TONES:
 89            raise TypeError("Cannot have a chord made of only 1 unique tone")
 90        self.root_index = self.LIST_OF_TONES.index(root.name)
 91        self.sort_tones = sorted(self.tones, key=self._get_distance_from_root)
 92
 93    def _get_distance_from_root(self, tone):
 94        return (self.LIST_OF_TONES.index(tone.name) - self.root_index) % TOTAL_TONES
 95
 96    def __str__(self):
 97        return "-".join(str(tone) for tone in self.sort_tones)
 98
 99    def is_minor(self):
100        """Check if the formed chord is 'minor 3rd'."""
101        for tone in self.tones:
102            if self._get_distance_from_root(tone) == MINOR_THIRD_INTERVAL:
103                return True
104        return False
105
106    def is_major(self):
107        """Check if the formed chord is 'major 3rd'."""
108        for tone in self.tones:
109            if self._get_distance_from_root(tone) == MAJOR_THIRD_INTERVAL:
110                return True
111        return False
112
113    def is_power_chord(self):
114        """Check if the chord is a power chord (not major or minor)."""
115        return not (self.is_minor() or self.is_major())
116
117    def __add__(self, other):
118        if isinstance(other, Tone):
119            return Chord(*self.tones, other)
120        return Chord(*self.tones, *other.tones)
121
122    def __sub__(self, other):
123        if isinstance(other, Tone):
124            if other.name not in [tone.name for tone in self.tones]:
125                raise TypeError(f"Cannot remove tone {str(other)} from chord {str(self)}")
126            new_tones = [tone for tone in self.tones if tone.name != other.name]
127            return Chord(*new_tones)
128
129    def transposed(self, interval):
130        """Transpose the chord by a given interval."""
131        transposed_tones = []
132        for tone in self.tones:
133            new_index = (self.LIST_OF_TONES.index(tone.name) + interval.number_of_semitones) % TOTAL_TONES
134            transposed_tones.append(Tone(self.LIST_OF_TONES[new_index]))
135        return Chord(transposed_tones[0], *transposed_tones[1:])

..................E..................
======================================================================
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 74, in __add__
new_semitones = (self.number_of_semitones + other.number_of_semitones) % TOTAL_TONES
^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Tone' object has no attribute 'number_of_semitones'

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

FAILED (errors=1)

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

f1"""f1"""
2    This module provides classes and functions for representing musical2    This module provides classes and functions for representing musical
3    tones, intervals, and chords. It allows for operations such as3    tones, intervals, and chords. It allows for operations such as
4    adding tones to chords, removing tones from chords, and4    adding tones to chords, removing tones from chords, and
5    transposing chords using intervals.5    transposing chords using intervals.
6"""6"""
77
88
9MINIMUM_UNIQUE_TONES = 19MINIMUM_UNIQUE_TONES = 1
10TOTAL_TONES = 1210TOTAL_TONES = 12
11MINOR_THIRD_INTERVAL = 311MINOR_THIRD_INTERVAL = 3
12MAJOR_THIRD_INTERVAL = 412MAJOR_THIRD_INTERVAL = 4
1313
1414
15class Tone:15class Tone:
16    """Represent a musical tone and methods to perform operations with intervals and other tones."""16    """Represent a musical tone and methods to perform operations with intervals and other tones."""
17    def __init__(self, name):17    def __init__(self, name):
18        self.name = name18        self.name = name
1919
20    def __str__(self):20    def __str__(self):
21        return self.name21        return self.name
2222
nn23    @property
23    def get_tone_index(self):24    def tone_index(self):
24        return Chord.list_of_tones.index(self.name)25        return Chord.LIST_OF_TONES.index(self.name)
2526
26    def __add__(self, other):27    def __add__(self, other):
27        if isinstance(other, Interval):28        if isinstance(other, Interval):
n28            tone_index = (self.get_tone_index() + other.number_of_semitones) % TOTAL_TONESn29            new_tone_index = (self.tone_index + other.number_of_semitones) % TOTAL_TONES
29            return Tone(Chord.list_of_tones[tone_index])30            return Tone(Chord.LIST_OF_TONES[new_tone_index])
30        return Chord(self, other)31        return Chord(self, other)
3132
32    def __radd__(self, other):33    def __radd__(self, other):
33        raise TypeError("Invalid operation")34        raise TypeError("Invalid operation")
3435
35    def __sub__(self, other):36    def __sub__(self, other):
36        if isinstance(other, Interval):37        if isinstance(other, Interval):
n37            tone_index = (self.get_tone_index() - other.number_of_semitones) % TOTAL_TONESn38            new_tone_index = (self.tone_index - other.number_of_semitones) % TOTAL_TONES
38            return Tone(Chord.list_of_tones[tone_index])39            return Tone(Chord.LIST_OF_TONES[new_tone_index])
39        distance = (self.get_tone_index() - other.get_tone_index()) % TOTAL_TONES40        distance = (self.tone_index - other.tone_index) % TOTAL_TONES
40        return Interval(distance)41        return Interval(distance)
4142
42    def __rsub__(self, other):43    def __rsub__(self, other):
43        raise TypeError("Invalid operation")44        raise TypeError("Invalid operation")
4445
4546
46class Interval:47class Interval:
47    """Represent a musical interval in semitones."""48    """Represent a musical interval in semitones."""
n48    INTERVALS_NAME = (n49    INTERVALS_NAME = [
49        "unison",50        "unison",
50        "minor 2nd",51        "minor 2nd",
51        "major 2nd",52        "major 2nd",
52        "minor 3rd",53        "minor 3rd",
53        "major 3rd",54        "major 3rd",
54        "perfect 4th",55        "perfect 4th",
55        "diminished 5th",56        "diminished 5th",
56        "perfect 5th",57        "perfect 5th",
57        "minor 6th",58        "minor 6th",
58        "major 6th",59        "major 6th",
59        "minor 7th",60        "minor 7th",
60        "major 7th"61        "major 7th"
n61    )n62    ]
6263
63    def __init__(self, number_of_semitones):64    def __init__(self, number_of_semitones):
64        self.number_of_semitones = number_of_semitones % TOTAL_TONES65        self.number_of_semitones = number_of_semitones % TOTAL_TONES
6566
66    def __neg__(self):67    def __neg__(self):
67        return Interval(-self.number_of_semitones)68        return Interval(-self.number_of_semitones)
6869
69    def __str__(self):70    def __str__(self):
70        return f"{self.INTERVALS_NAME[self.number_of_semitones]}"71        return f"{self.INTERVALS_NAME[self.number_of_semitones]}"
7172
72    def __add__(self, other):73    def __add__(self, other):
73        new_semitones = (self.number_of_semitones + other.number_of_semitones) % TOTAL_TONES74        new_semitones = (self.number_of_semitones + other.number_of_semitones) % TOTAL_TONES
74        return Interval(new_semitones)75        return Interval(new_semitones)
7576
7677
77class Chord:78class Chord:
78    """Represent a musical chord of multiple tones."""79    """Represent a musical chord of multiple tones."""
n79    list_of_tones = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]n80    LIST_OF_TONES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
8081
81    def __init__(self, root, *arg):82    def __init__(self, root, *arg):
82        self.tones = [root]83        self.tones = [root]
83        for tone in arg:84        for tone in arg:
84            if tone.name not in [t.name for t in self.tones]:85            if tone.name not in [t.name for t in self.tones]:
85                self.tones.append(tone)86                self.tones.append(tone)
8687
87        if len(self.tones) == MINIMUM_UNIQUE_TONES:88        if len(self.tones) == MINIMUM_UNIQUE_TONES:
88            raise TypeError("Cannot have a chord made of only 1 unique tone")89            raise TypeError("Cannot have a chord made of only 1 unique tone")
n89        self.root_index = self.list_of_tones.index(root.name)n90        self.root_index = self.LIST_OF_TONES.index(root.name)
90        self.sort_tones = sorted(self.tones, key=self._get_distance_from_root)91        self.sort_tones = sorted(self.tones, key=self._get_distance_from_root)
9192
92    def _get_distance_from_root(self, tone):93    def _get_distance_from_root(self, tone):
n93        return (self.list_of_tones.index(tone.name) - self.root_index) % TOTAL_TONESn94        return (self.LIST_OF_TONES.index(tone.name) - self.root_index) % TOTAL_TONES
9495
95    def __str__(self):96    def __str__(self):
96        return "-".join(str(tone) for tone in self.sort_tones)97        return "-".join(str(tone) for tone in self.sort_tones)
9798
98    def is_minor(self):99    def is_minor(self):
99        """Check if the formed chord is 'minor 3rd'."""100        """Check if the formed chord is 'minor 3rd'."""
100        for tone in self.tones:101        for tone in self.tones:
101            if self._get_distance_from_root(tone) == MINOR_THIRD_INTERVAL:102            if self._get_distance_from_root(tone) == MINOR_THIRD_INTERVAL:
102                return True103                return True
103        return False104        return False
104105
105    def is_major(self):106    def is_major(self):
106        """Check if the formed chord is 'major 3rd'."""107        """Check if the formed chord is 'major 3rd'."""
107        for tone in self.tones:108        for tone in self.tones:
108            if self._get_distance_from_root(tone) == MAJOR_THIRD_INTERVAL:109            if self._get_distance_from_root(tone) == MAJOR_THIRD_INTERVAL:
109                return True110                return True
110        return False111        return False
111112
112    def is_power_chord(self):113    def is_power_chord(self):
113        """Check if the chord is a power chord (not major or minor)."""114        """Check if the chord is a power chord (not major or minor)."""
114        return not (self.is_minor() or self.is_major())115        return not (self.is_minor() or self.is_major())
115116
116    def __add__(self, other):117    def __add__(self, other):
117        if isinstance(other, Tone):118        if isinstance(other, Tone):
118            return Chord(*self.tones, other)119            return Chord(*self.tones, other)
119        return Chord(*self.tones, *other.tones)120        return Chord(*self.tones, *other.tones)
120121
121    def __sub__(self, other):122    def __sub__(self, other):
122        if isinstance(other, Tone):123        if isinstance(other, Tone):
123            if other.name not in [tone.name for tone in self.tones]:124            if other.name not in [tone.name for tone in self.tones]:
124                raise TypeError(f"Cannot remove tone {str(other)} from chord {str(self)}")125                raise TypeError(f"Cannot remove tone {str(other)} from chord {str(self)}")
125            new_tones = [tone for tone in self.tones if tone.name != other.name]126            new_tones = [tone for tone in self.tones if tone.name != other.name]
126            return Chord(*new_tones)127            return Chord(*new_tones)
127128
128    def transposed(self, interval):129    def transposed(self, interval):
129        """Transpose the chord by a given interval."""130        """Transpose the chord by a given interval."""
130        transposed_tones = []131        transposed_tones = []
131        for tone in self.tones:132        for tone in self.tones:
t132            new_index = (self.list_of_tones.index(tone.name) + interval.number_of_semitones) % TOTAL_TONESt133            new_index = (self.LIST_OF_TONES.index(tone.name) + interval.number_of_semitones) % TOTAL_TONES
133            transposed_tones.append(Tone(self.list_of_tones[new_index]))134            transposed_tones.append(Tone(self.LIST_OF_TONES[new_index]))
134        return Chord(transposed_tones[0], *transposed_tones[1:])135        return Chord(transposed_tones[0], *transposed_tones[1:])
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1"""f1"""
2    This module provides classes and functions for representing musical2    This module provides classes and functions for representing musical
3    tones, intervals, and chords. It allows for operations such as3    tones, intervals, and chords. It allows for operations such as
4    adding tones to chords, removing tones from chords, and4    adding tones to chords, removing tones from chords, and
5    transposing chords using intervals.5    transposing chords using intervals.
6"""6"""
77
nn8 
8MINIMUM_UNIQUE_TONES = 19MINIMUM_UNIQUE_TONES = 1
9TOTAL_TONES = 1210TOTAL_TONES = 12
10MINOR_THIRD_INTERVAL = 311MINOR_THIRD_INTERVAL = 3
11MAJOR_THIRD_INTERVAL = 412MAJOR_THIRD_INTERVAL = 4
nn13 
1214
13class Tone:15class Tone:
14    """Represent a musical tone and methods to perform operations with intervals and other tones."""16    """Represent a musical tone and methods to perform operations with intervals and other tones."""
15    def __init__(self, name):17    def __init__(self, name):
16        self.name = name18        self.name = name
1719
18    def __str__(self):20    def __str__(self):
19        return self.name21        return self.name
2022
n21    def _get_tone_index(self, tone_name):n23    def get_tone_index(self):
22        return Chord.list_of_tones.index(tone_name)24        return Chord.list_of_tones.index(self.name)
2325
24    def __add__(self, other):26    def __add__(self, other):
25        if isinstance(other, Interval):27        if isinstance(other, Interval):
n26            tone_index = (self._get_tone_index(self.name) + other.number_of_semitones) % TOTAL_TONESn28            tone_index = (self.get_tone_index() + other.number_of_semitones) % TOTAL_TONES
27            return Tone(Chord.list_of_tones[tone_index])29            return Tone(Chord.list_of_tones[tone_index])
28        return Chord(self, other)30        return Chord(self, other)
2931
30    def __radd__(self, other):32    def __radd__(self, other):
31        raise TypeError("Invalid operation")33        raise TypeError("Invalid operation")
3234
33    def __sub__(self, other):35    def __sub__(self, other):
34        if isinstance(other, Interval):36        if isinstance(other, Interval):
n35            tone_index = (self._get_tone_index(self.name) - other.number_of_semitones) % TOTAL_TONESn37            tone_index = (self.get_tone_index() - other.number_of_semitones) % TOTAL_TONES
36            return Tone(Chord.list_of_tones[tone_index])38            return Tone(Chord.list_of_tones[tone_index])
n37        distance = (self._get_tone_index(self.name)n39        distance = (self.get_tone_index() - other.get_tone_index()) % TOTAL_TONES
38                    - self._get_tone_index(other.name)) % TOTAL_TONES
39        return Interval(distance)40        return Interval(distance)
4041
41    def __rsub__(self, other):42    def __rsub__(self, other):
42        raise TypeError("Invalid operation")43        raise TypeError("Invalid operation")
4344
nn45 
44class Interval:46class Interval:
45    """Represent a musical interval in semitones."""47    """Represent a musical interval in semitones."""
n46    intervals_name = {n48    INTERVALS_NAME = (
47        0: "unison",49        "unison",
48        1: "minor 2nd",50        "minor 2nd",
49        2: "major 2nd",51        "major 2nd",
50        3: "minor 3rd",52        "minor 3rd",
51        4: "major 3rd",53        "major 3rd",
52        5: "perfect 4th",54        "perfect 4th",
53        6: "diminished 5th",55        "diminished 5th",
54        7: "perfect 5th",56        "perfect 5th",
55        8: "minor 6th",57        "minor 6th",
56        9: "major 6th",58        "major 6th",
57        10: "minor 7th",59        "minor 7th",
58        11: "major 7th"60        "major 7th"
59        }61    )
6062
61    def __init__(self, number_of_semitones):63    def __init__(self, number_of_semitones):
62        self.number_of_semitones = number_of_semitones % TOTAL_TONES64        self.number_of_semitones = number_of_semitones % TOTAL_TONES
6365
64    def __neg__(self):66    def __neg__(self):
65        return Interval(-self.number_of_semitones)67        return Interval(-self.number_of_semitones)
6668
67    def __str__(self):69    def __str__(self):
n68        return f"{self.intervals_name[self.number_of_semitones]}"n70        return f"{self.INTERVALS_NAME[self.number_of_semitones]}"
6971
70    def __add__(self, other):72    def __add__(self, other):
71        new_semitones = (self.number_of_semitones + other.number_of_semitones) % TOTAL_TONES73        new_semitones = (self.number_of_semitones + other.number_of_semitones) % TOTAL_TONES
72        return Interval(new_semitones)74        return Interval(new_semitones)
7375
7476
75class Chord:77class Chord:
76    """Represent a musical chord of multiple tones."""78    """Represent a musical chord of multiple tones."""
77    list_of_tones = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]79    list_of_tones = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
7880
79    def __init__(self, root, *arg):81    def __init__(self, root, *arg):
80        self.tones = [root]82        self.tones = [root]
81        for tone in arg:83        for tone in arg:
82            if tone.name not in [t.name for t in self.tones]:84            if tone.name not in [t.name for t in self.tones]:
83                self.tones.append(tone)85                self.tones.append(tone)
8486
85        if len(self.tones) == MINIMUM_UNIQUE_TONES:87        if len(self.tones) == MINIMUM_UNIQUE_TONES:
86            raise TypeError("Cannot have a chord made of only 1 unique tone")88            raise TypeError("Cannot have a chord made of only 1 unique tone")
87        self.root_index = self.list_of_tones.index(root.name)89        self.root_index = self.list_of_tones.index(root.name)
88        self.sort_tones = sorted(self.tones, key=self._get_distance_from_root)90        self.sort_tones = sorted(self.tones, key=self._get_distance_from_root)
8991
90    def _get_distance_from_root(self, tone):92    def _get_distance_from_root(self, tone):
91        return (self.list_of_tones.index(tone.name) - self.root_index) % TOTAL_TONES93        return (self.list_of_tones.index(tone.name) - self.root_index) % TOTAL_TONES
9294
93    def __str__(self):95    def __str__(self):
94        return "-".join(str(tone) for tone in self.sort_tones)96        return "-".join(str(tone) for tone in self.sort_tones)
9597
96    def is_minor(self):98    def is_minor(self):
97        """Check if the formed chord is 'minor 3rd'."""99        """Check if the formed chord is 'minor 3rd'."""
98        for tone in self.tones:100        for tone in self.tones:
99            if self._get_distance_from_root(tone) == MINOR_THIRD_INTERVAL:101            if self._get_distance_from_root(tone) == MINOR_THIRD_INTERVAL:
100                return True102                return True
101        return False103        return False
102104
103    def is_major(self):105    def is_major(self):
104        """Check if the formed chord is 'major 3rd'."""106        """Check if the formed chord is 'major 3rd'."""
105        for tone in self.tones:107        for tone in self.tones:
106            if self._get_distance_from_root(tone) == MAJOR_THIRD_INTERVAL:108            if self._get_distance_from_root(tone) == MAJOR_THIRD_INTERVAL:
107                return True109                return True
108        return False110        return False
109111
110    def is_power_chord(self):112    def is_power_chord(self):
111        """Check if the chord is a power chord (not major or minor)."""113        """Check if the chord is a power chord (not major or minor)."""
n112        return not(self.is_minor() or self.is_major())n114        return not (self.is_minor() or self.is_major())
113115
114    def __add__(self, other):116    def __add__(self, other):
115        if isinstance(other, Tone):117        if isinstance(other, Tone):
116            return Chord(*self.tones, other)118            return Chord(*self.tones, other)
117        return Chord(*self.tones, *other.tones)119        return Chord(*self.tones, *other.tones)
118120
119    def __sub__(self, other):121    def __sub__(self, other):
120        if isinstance(other, Tone):122        if isinstance(other, Tone):
121            if other.name not in [tone.name for tone in self.tones]:123            if other.name not in [tone.name for tone in self.tones]:
122                raise TypeError(f"Cannot remove tone {str(other)} from chord {str(self)}")124                raise TypeError(f"Cannot remove tone {str(other)} from chord {str(self)}")
123            new_tones = [tone for tone in self.tones if tone.name != other.name]125            new_tones = [tone for tone in self.tones if tone.name != other.name]
124            return Chord(*new_tones)126            return Chord(*new_tones)
125127
126    def transposed(self, interval):128    def transposed(self, interval):
127        """Transpose the chord by a given interval."""129        """Transpose the chord by a given interval."""
128        transposed_tones = []130        transposed_tones = []
129        for tone in self.tones:131        for tone in self.tones:
t130            new_index = (self.list_of_tones.index(tone.name)t132            new_index = (self.list_of_tones.index(tone.name) + interval.number_of_semitones) % TOTAL_TONES
131                         + interval.number_of_semitones) % TOTAL_TONES
132            transposed_tones.append(Tone(self.list_of_tones[new_index]))133            transposed_tones.append(Tone(self.list_of_tones[new_index]))
133        return Chord(transposed_tones[0], *transposed_tones[1:])134        return Chord(transposed_tones[0], *transposed_tones[1:])
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op