Домашни > Pitches love the D > Решения > Решението на Никола Георгиев

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

9 точки общо

32 успешни теста
5 неуспешни теста
Код (🎵🎶🥶)
Скрий всички коментари

  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:27

What kind of music are Balloons afraid of? Pop music.
История
Това решение има само една версия.