Домашни > Pitches love the D > Решения > Решението на Димитър Фенерски

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

10 точки общо

37 успешни теста
0 неуспешни теста
Код

  1from functools import cmp_to_key
  2
  3
  4TONES = (
  5    "A",
  6    "A#",
  7    "B",
  8    "C",
  9    "C#",
 10    "D",
 11    "D#",
 12    "E",
 13    "F",
 14    "F#",
 15    "G",
 16    "G#",
 17)
 18INTERVALS = [
 19    "unison",
 20    "minor 2nd",
 21    "major 2nd",
 22    "minor 3rd",
 23    "major 3rd",
 24    "perfect 4th",
 25    "diminished 5th",
 26    "perfect 5th",
 27    "minor 6th",
 28    "major 6th",
 29    "minor 7th",
 30    "major 7th",
 31]
 32
 33
 34class Tone:
 35    def __init__(self, tone_literal):
 36        assert tone_literal in TONES
 37        self.tone_literal = tone_literal
 38
 39    def __str__(self):
 40        return self.tone_literal
 41
 42    def __add__(self, other):
 43        if isinstance(other, Tone):
 44            return Chord(self, other)
 45        elif isinstance(other, Interval):
 46            return Tone(TONES[(TONES.index(self.tone_literal) + other.interval_length) % 12])
 47
 48    def __sub__(self, other):
 49        if isinstance(other, Tone):
 50            return Interval(Tone.get_tone_gap(other, self))
 51        elif isinstance(other, Interval):
 52            return Tone(TONES[(TONES.index(self.tone_literal) - other.interval_length) % 12])
 53
 54    @staticmethod
 55    def get_tone_gap(a, b):
 56        start_index = TONES.index(str(a))
 57        end_index = TONES.index(str(b))
 58        gap = 0
 59        while TONES[start_index % 12] != TONES[end_index]:
 60            start_index += 1
 61            gap += 1
 62        return gap
 63
 64
 65class Interval:
 66    def __init__(self, interval_length):
 67        assert isinstance(interval_length, int)
 68        self.interval_length = interval_length % 12
 69
 70    def __str__(self):
 71        return INTERVALS[self.interval_length]
 72
 73    def __add__(self, other):
 74        if isinstance(other, Tone):
 75            raise TypeError("Invalid operation")
 76        elif isinstance(other, Interval):
 77            return Interval(self.interval_length + other.interval_length)
 78
 79    def __sub__(self, other):
 80        if isinstance(other, Tone):
 81            raise TypeError("Invalid operation")
 82
 83    def __neg__(self):
 84        return Interval(-self.interval_length)
 85
 86
 87class Chord:
 88    def __init__(self, main_tone, *rest_tones):
 89        if len(set([str(main_tone), *[str(tone) for tone in rest_tones]])) == 1:
 90            raise TypeError("Cannot have a chord made of only 1 unique tone")
 91
 92        self.main_tone = main_tone
 93        self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str(
 94            main_tone)]), key=cmp_to_key(lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))]
 95
 96    def __str__(self):
 97        return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]])
 98
 99    def __add__(self, other):
100        if isinstance(other, Tone):
101            return Chord(self.main_tone, *self.rest_tones, other)
102        if isinstance(other, Chord):
103            return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones)
104
105    def __sub__(self, other):
106        if isinstance(other, Tone):
107            if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])):
108                raise TypeError(f"Cannot remove tone {
109                                str(other)} from chord {str(self)}")
110            return Chord(*[tone for tone in [self.main_tone, *self.rest_tones] if str(tone) != str(other)])
111
112    def transposed(self, interval):
113        assert isinstance(interval, Interval)
114        return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones])
115
116    def is_minor(self):
117        return any([INTERVALS[Tone.get_tone_gap(self.main_tone, tone)] == "minor 3rd" for tone in self.rest_tones])
118
119    def is_major(self):
120        return any([INTERVALS[Tone.get_tone_gap(self.main_tone, tone)] == "major 3rd" for tone in self.rest_tones])
121
122    def is_power_chord(self):
123        return not self.is_minor() and not self.is_major()

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

OK

Дискусия
Виктор Бечев
04.11.2024 14:34

Що се отнася до дължината на редовете - we don't mind either way, просто казвам да не го правиш специално заради нас.
Виктор Бечев
04.11.2024 14:33

Това изглежда като нещо, което идва от средата / редактора. Пуснах кода ти без каквото и да е от `typing` и проблем няма. Разтърси се от къде идва, за да не се налага всеки път да ти оставяме коментари по темата _(а коментари ще оставяме, защото е напълно безсмислено да извършваш въпросната операция, тъй като функционално няма как да има проблем)_.
Димитър Фенерски
04.11.2024 14:30

> Така като гледам следващият ред ти е по-дълъг от този, дори да не слагаш съобщението на нов ред, така че не е голяма драма да го оставиш. не знам как на silence-на линтера, автоматично го форматира и постоянно се оплаква https://ibb.co/M2xmq2X
Димитър Фенерски
04.11.2024 14:19

@Виктор Без `Any` каст имам ерор, иначе и мен ме дразнят. Не открих чисто решение в нета и затова кастнах: ``` Argument of type "int" cannot be assigned to parameter "key" of type "Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]" in function "__getitem__"   Type "int" is not assignable to type "Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"     "int" is not assignable to type "Literal[0]"     "int" is not assignable to type "Literal[1]"     "int" is not assignable to type "Literal[2]"     "int" is not assignable to type "Literal[3]"     "int" is not assignable to type "Literal[4]"     "int" is not assignable to type "Literal[5]"     "int" is not assignable to type "Literal[6]" [reportArgumentType] ```
История

f1from functools import cmp_to_keyf1from functools import cmp_to_key
22
33
4TONES = (4TONES = (
5    "A",5    "A",
6    "A#",6    "A#",
7    "B",7    "B",
8    "C",8    "C",
9    "C#",9    "C#",
10    "D",10    "D",
11    "D#",11    "D#",
12    "E",12    "E",
13    "F",13    "F",
14    "F#",14    "F#",
15    "G",15    "G",
16    "G#",16    "G#",
17)17)
18INTERVALS = [18INTERVALS = [
19    "unison",19    "unison",
20    "minor 2nd",20    "minor 2nd",
21    "major 2nd",21    "major 2nd",
22    "minor 3rd",22    "minor 3rd",
23    "major 3rd",23    "major 3rd",
24    "perfect 4th",24    "perfect 4th",
25    "diminished 5th",25    "diminished 5th",
26    "perfect 5th",26    "perfect 5th",
27    "minor 6th",27    "minor 6th",
28    "major 6th",28    "major 6th",
29    "minor 7th",29    "minor 7th",
30    "major 7th",30    "major 7th",
31]31]
3232
3333
34class Tone:34class Tone:
35    def __init__(self, tone_literal):35    def __init__(self, tone_literal):
36        assert tone_literal in TONES36        assert tone_literal in TONES
37        self.tone_literal = tone_literal37        self.tone_literal = tone_literal
3838
39    def __str__(self):39    def __str__(self):
40        return self.tone_literal40        return self.tone_literal
4141
42    def __add__(self, other):42    def __add__(self, other):
43        if isinstance(other, Tone):43        if isinstance(other, Tone):
44            return Chord(self, other)44            return Chord(self, other)
45        elif isinstance(other, Interval):45        elif isinstance(other, Interval):
46            return Tone(TONES[(TONES.index(self.tone_literal) + other.interval_length) % 12])46            return Tone(TONES[(TONES.index(self.tone_literal) + other.interval_length) % 12])
4747
48    def __sub__(self, other):48    def __sub__(self, other):
49        if isinstance(other, Tone):49        if isinstance(other, Tone):
50            return Interval(Tone.get_tone_gap(other, self))50            return Interval(Tone.get_tone_gap(other, self))
51        elif isinstance(other, Interval):51        elif isinstance(other, Interval):
52            return Tone(TONES[(TONES.index(self.tone_literal) - other.interval_length) % 12])52            return Tone(TONES[(TONES.index(self.tone_literal) - other.interval_length) % 12])
5353
54    @staticmethod54    @staticmethod
55    def get_tone_gap(a, b):55    def get_tone_gap(a, b):
56        start_index = TONES.index(str(a))56        start_index = TONES.index(str(a))
57        end_index = TONES.index(str(b))57        end_index = TONES.index(str(b))
58        gap = 058        gap = 0
59        while TONES[start_index % 12] != TONES[end_index]:59        while TONES[start_index % 12] != TONES[end_index]:
60            start_index += 160            start_index += 1
61            gap += 161            gap += 1
62        return gap62        return gap
6363
6464
65class Interval:65class Interval:
66    def __init__(self, interval_length):66    def __init__(self, interval_length):
67        assert isinstance(interval_length, int)67        assert isinstance(interval_length, int)
68        self.interval_length = interval_length % 1268        self.interval_length = interval_length % 12
6969
70    def __str__(self):70    def __str__(self):
71        return INTERVALS[self.interval_length]71        return INTERVALS[self.interval_length]
7272
73    def __add__(self, other):73    def __add__(self, other):
74        if isinstance(other, Tone):74        if isinstance(other, Tone):
75            raise TypeError("Invalid operation")75            raise TypeError("Invalid operation")
76        elif isinstance(other, Interval):76        elif isinstance(other, Interval):
77            return Interval(self.interval_length + other.interval_length)77            return Interval(self.interval_length + other.interval_length)
7878
79    def __sub__(self, other):79    def __sub__(self, other):
80        if isinstance(other, Tone):80        if isinstance(other, Tone):
81            raise TypeError("Invalid operation")81            raise TypeError("Invalid operation")
8282
83    def __neg__(self):83    def __neg__(self):
84        return Interval(-self.interval_length)84        return Interval(-self.interval_length)
8585
8686
87class Chord:87class Chord:
88    def __init__(self, main_tone, *rest_tones):88    def __init__(self, main_tone, *rest_tones):
89        if len(set([str(main_tone), *[str(tone) for tone in rest_tones]])) == 1:89        if len(set([str(main_tone), *[str(tone) for tone in rest_tones]])) == 1:
90            raise TypeError("Cannot have a chord made of only 1 unique tone")90            raise TypeError("Cannot have a chord made of only 1 unique tone")
9191
92        self.main_tone = main_tone92        self.main_tone = main_tone
93        self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str(93        self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str(
94            main_tone)]), key=cmp_to_key(lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))]94            main_tone)]), key=cmp_to_key(lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))]
9595
96    def __str__(self):96    def __str__(self):
97        return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]])97        return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]])
9898
99    def __add__(self, other):99    def __add__(self, other):
100        if isinstance(other, Tone):100        if isinstance(other, Tone):
101            return Chord(self.main_tone, *self.rest_tones, other)101            return Chord(self.main_tone, *self.rest_tones, other)
102        if isinstance(other, Chord):102        if isinstance(other, Chord):
103            return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones)103            return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones)
104104
105    def __sub__(self, other):105    def __sub__(self, other):
106        if isinstance(other, Tone):106        if isinstance(other, Tone):
107            if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])):107            if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])):
108                raise TypeError(f"Cannot remove tone {108                raise TypeError(f"Cannot remove tone {
109                                str(other)} from chord {str(self)}")109                                str(other)} from chord {str(self)}")
110            return Chord(*[tone for tone in [self.main_tone, *self.rest_tones] if str(tone) != str(other)])110            return Chord(*[tone for tone in [self.main_tone, *self.rest_tones] if str(tone) != str(other)])
111111
112    def transposed(self, interval):112    def transposed(self, interval):
113        assert isinstance(interval, Interval)113        assert isinstance(interval, Interval)
114        return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones])114        return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones])
115115
116    def is_minor(self):116    def is_minor(self):
n117        return any([INTERVALS[(Tone.get_tone_gap(self.main_tone, tone))] == "minor 3rd" for tone in self.rest_tones])n117        return any([INTERVALS[Tone.get_tone_gap(self.main_tone, tone)] == "minor 3rd" for tone in self.rest_tones])
118118
119    def is_major(self):119    def is_major(self):
t120        return any([INTERVALS[(Tone.get_tone_gap(self.main_tone, tone))] == "major 3rd" for tone in self.rest_tones])t120        return any([INTERVALS[Tone.get_tone_gap(self.main_tone, tone)] == "major 3rd" for tone in self.rest_tones])
121121
122    def is_power_chord(self):122    def is_power_chord(self):
123        return not self.is_minor() and not self.is_major()123        return not self.is_minor() and not self.is_major()
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1from functools import cmp_to_keyf1from functools import cmp_to_key
n2from typing import Any, castn
32
43
5TONES = (4TONES = (
6    "A",5    "A",
7    "A#",6    "A#",
8    "B",7    "B",
9    "C",8    "C",
10    "C#",9    "C#",
11    "D",10    "D",
12    "D#",11    "D#",
13    "E",12    "E",
14    "F",13    "F",
15    "F#",14    "F#",
16    "G",15    "G",
17    "G#",16    "G#",
18)17)
n19INTERVALS = dict([n18INTERVALS = [
20    (0, "unison"),19    "unison",
21    (1, "minor 2nd"),20    "minor 2nd",
22    (2, "major 2nd"),21    "major 2nd",
23    (3, "minor 3rd"),22    "minor 3rd",
24    (4, "major 3rd"),23    "major 3rd",
25    (5, "perfect 4th"),24    "perfect 4th",
26    (6, "diminished 5th"),25    "diminished 5th",
27    (7, "perfect 5th"),26    "perfect 5th",
28    (8, "minor 6th"),27    "minor 6th",
29    (9, "major 6th"),28    "major 6th",
30    (10, "minor 7th"),29    "minor 7th",
31    (11, "major 7th"),30    "major 7th",
32])31]
3332
3433
35class Tone:34class Tone:
n36    def __init__(self, rep):n35    def __init__(self, tone_literal):
37        assert rep in TONES36        assert tone_literal in TONES
38        self.rep = rep37        self.tone_literal = tone_literal
3938
40    def __str__(self):39    def __str__(self):
n41        return self.repn40        return self.tone_literal
4241
43    def __add__(self, other):42    def __add__(self, other):
44        if isinstance(other, Tone):43        if isinstance(other, Tone):
45            return Chord(self, other)44            return Chord(self, other)
46        elif isinstance(other, Interval):45        elif isinstance(other, Interval):
n47            return Tone(TONES[(TONES.index(self.rep) + other.rep) % 12])n46            return Tone(TONES[(TONES.index(self.tone_literal) + other.interval_length) % 12])
4847
49    def __sub__(self, other):48    def __sub__(self, other):
50        if isinstance(other, Tone):49        if isinstance(other, Tone):
51            return Interval(Tone.get_tone_gap(other, self))50            return Interval(Tone.get_tone_gap(other, self))
52        elif isinstance(other, Interval):51        elif isinstance(other, Interval):
n53            return Tone(TONES[(TONES.index(self.rep) - other.rep) % 12])n52            return Tone(TONES[(TONES.index(self.tone_literal) - other.interval_length) % 12])
5453
55    @staticmethod54    @staticmethod
56    def get_tone_gap(a, b):55    def get_tone_gap(a, b):
57        start_index = TONES.index(str(a))56        start_index = TONES.index(str(a))
58        end_index = TONES.index(str(b))57        end_index = TONES.index(str(b))
59        gap = 058        gap = 0
60        while TONES[start_index % 12] != TONES[end_index]:59        while TONES[start_index % 12] != TONES[end_index]:
61            start_index += 160            start_index += 1
62            gap += 161            gap += 1
63        return gap62        return gap
6463
6564
66class Interval:65class Interval:
n67    def __init__(self, rep):n66    def __init__(self, interval_length):
68        normalized_rep = rep % 1267        assert isinstance(interval_length, int)
69        assert normalized_rep in INTERVALS68        self.interval_length = interval_length % 12
70        self.rep = normalized_rep
7169
72    def __str__(self):70    def __str__(self):
n73        return INTERVALS[self.rep]n71        return INTERVALS[self.interval_length]
7472
75    def __add__(self, other):73    def __add__(self, other):
76        if isinstance(other, Tone):74        if isinstance(other, Tone):
77            raise TypeError("Invalid operation")75            raise TypeError("Invalid operation")
78        elif isinstance(other, Interval):76        elif isinstance(other, Interval):
n79            return Interval(self.rep + other.rep)n77            return Interval(self.interval_length + other.interval_length)
8078
81    def __sub__(self, other):79    def __sub__(self, other):
82        if isinstance(other, Tone):80        if isinstance(other, Tone):
83            raise TypeError("Invalid operation")81            raise TypeError("Invalid operation")
8482
85    def __neg__(self):83    def __neg__(self):
n86        return Interval(-self.rep)n84        return Interval(-self.interval_length)
8785
8886
89class Chord:87class Chord:
90    def __init__(self, main_tone, *rest_tones):88    def __init__(self, main_tone, *rest_tones):
n91        if len(set([str(main_tone), *[str(tone)n89        if len(set([str(main_tone), *[str(tone) for tone in rest_tones]])) == 1:
92                    for tone in rest_tones]])) == 1:
93            raise TypeError("Cannot have a chord made of only 1 unique tone")90            raise TypeError("Cannot have a chord made of only 1 unique tone")
9491
95        self.main_tone = main_tone92        self.main_tone = main_tone
n96        self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str(main_tone)]), key=cmp_to_key(n93        self.rest_tones = [Tone(tone) for tone in sorted(set([str(tone) for tone in rest_tones if str(tone) != str(
97            lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))]94            main_tone)]), key=cmp_to_key(lambda a, b: Tone.get_tone_gap(main_tone, Tone(a)) - Tone.get_tone_gap(main_tone, Tone(b))))]
9895
99    def __str__(self):96    def __str__(self):
100        return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]])97        return "-".join([str(self.main_tone), *[str(tone) for tone in self.rest_tones]])
10198
102    def __add__(self, other):99    def __add__(self, other):
103        if isinstance(other, Tone):100        if isinstance(other, Tone):
104            return Chord(self.main_tone, *self.rest_tones, other)101            return Chord(self.main_tone, *self.rest_tones, other)
105        if isinstance(other, Chord):102        if isinstance(other, Chord):
106            return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones)103            return Chord(self.main_tone, *self.rest_tones, other.main_tone, *other.rest_tones)
107104
108    def __sub__(self, other):105    def __sub__(self, other):
109        if isinstance(other, Tone):106        if isinstance(other, Tone):
110            if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])):107            if not any((str(tone) == str(other) for tone in [self.main_tone, *self.rest_tones])):
111                raise TypeError(f"Cannot remove tone {108                raise TypeError(f"Cannot remove tone {
112                                str(other)} from chord {str(self)}")109                                str(other)} from chord {str(self)}")
n113            if len(self.rest_tones) == 1:n110            return Chord(*[tone for tone in [self.main_tone, *self.rest_tones] if str(tone) != str(other)])
114                raise TypeError(
115                    "Cannot have a chord made of only 1 unique tone")
116            return Chord(*list(filter(lambda tone: str(tone) != str(other), [self.main_tone, *self.rest_tones])))
117111
118    def transposed(self, interval):112    def transposed(self, interval):
119        assert isinstance(interval, Interval)113        assert isinstance(interval, Interval)
120        return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones])114        return Chord(self.main_tone + interval, *[tone + interval for tone in self.rest_tones])
121115
122    def is_minor(self):116    def is_minor(self):
n123        return any([INTERVALS[cast(Any, Tone.get_tone_gap(self.main_tone, tone))] == "minor 3rd" for tone in self.rest_tones])n117        return any([INTERVALS[(Tone.get_tone_gap(self.main_tone, tone))] == "minor 3rd" for tone in self.rest_tones])
124118
125    def is_major(self):119    def is_major(self):
t126        return any([INTERVALS[cast(Any, Tone.get_tone_gap(self.main_tone, tone))] == "major 3rd" for tone in self.rest_tones])t120        return any([INTERVALS[(Tone.get_tone_gap(self.main_tone, tone))] == "major 3rd" for tone in self.rest_tones])
127121
128    def is_power_chord(self):122    def is_power_chord(self):
129        return not self.is_minor() and not self.is_major()123        return not self.is_minor() and not self.is_major()
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op