Skip to content

Instantly share code, notes, and snippets.

@Preinfarction
Created September 23, 2022 01:25
Show Gist options
  • Save Preinfarction/368b6d684cc5f6f466a0b82ddb15b392 to your computer and use it in GitHub Desktop.
Save Preinfarction/368b6d684cc5f6f466a0b82ddb15b392 to your computer and use it in GitHub Desktop.
import re
def scale_interval(scalar, interval):
scaled_interval = (i * scalar for i in interval)
return tuple(scaled_interval)
def interval_difference(interval1, interval2):
interval_difference = (e1 - e2 for (e1, e2) in zip(interval1, interval2))
return tuple(interval_difference)
def interval_sum(interval1, interval2):
interval_sum = (e1 + e2 for (e1, e2) in zip(interval1, interval2))
return tuple(interval_sum)
def quality_and_ordinal_to_interval(quality, ordinal):
base_name_to_interval = {
"P1": (0, 0),
"m2": (1, 1),
"M2": (2, 1),
"m3": (3, 2),
"M3": (4, 2),
"P4": (5, 3),
"P5": (7, 4),
"m6": (8, 5),
"M6": (9, 5),
"m7": (10, 6),
"M7": (11, 6),
}
name = quality + str(ordinal)
if name in base_name_to_interval:
return base_name_to_interval[name]
if ordinal < 1:
return interval_difference(quality_and_ordinal_to_interval(quality, ordinal + 7), (12, 7))
if ordinal > 7:
return interval_sum(quality_and_ordinal_to_interval(quality, ordinal - 7), (12, 7))
if re.match(r"[d]+", quality):
degree_of_diminution = len(quality)
if ordinal in [1, 4, 5]:
return interval_sum(quality_and_ordinal_to_interval("P", ordinal), (-degree_of_diminution, 0))
if ordinal in [2, 3, 6, 7]:
return interval_sum(quality_and_ordinal_to_interval("m", ordinal), (-degree_of_diminution, 0))
if re.match(r"[A]+", quality):
degree_of_augmentation = len(quality)
if ordinal in [1, 4, 5]:
return interval_sum(quality_and_ordinal_to_interval("P", ordinal), (degree_of_augmentation, 0))
if ordinal in [2, 3, 6, 7]:
return interval_sum(quality_and_ordinal_to_interval("M", ordinal), (degree_of_augmentation, 0))
def name_to_interval(name):
_, quality, ordinal, _ = re.split(r"^([AdMmP]+)([0-9\-]+)$", name)
ordinal = int(ordinal)
interval = quality_and_ordinal_to_interval(quality, ordinal)
return interval
def pprint(interval_string):
interval_string = re.sub(r"dP", r"d", interval_string)
interval_string = re.sub(r"dm", r"d", interval_string)
interval_string = re.sub(r"AP", r"A", interval_string)
interval_string = re.sub(r"AM", r"A", interval_string)
return interval_string
def interval_to_quality(interval):
A1, d2 = interval
if d2 >= 7:
return interval_to_quality((A1 - 12, d2 - 7))
if d2 < 0:
return interval_to_quality((A1 + 12, d2 + 7))
if interval in [(0, 0), (5, 3), (7, 4), (12, 7)]:
return "P"
if interval in [(1, 1), (3, 2), (8, 5), (10, 6)]:
return "m"
if interval in [(2, 1), (4, 2), (9, 5), (11, 6)]:
return "M"
if d2 == 0 and A1 < 0:
return "d" + interval_to_quality((A1 + 1, d2))
if d2 == 0 and A1 > 0:
return "A" + interval_to_quality((A1 - 1, d2))
if d2 == 1 and A1 < 1:
return "d" + interval_to_quality((A1 + 1, d2))
if d2 == 1 and A1 > 2:
return "A" + interval_to_quality((A1 - 1, d2))
if d2 == 2 and A1 < 3:
return "d" + interval_to_quality((A1 + 1, d2))
if d2 == 2 and A1 > 4:
return "A" + interval_to_quality((A1 - 1, d2))
if d2 == 3 and A1 < 5:
return "d" + interval_to_quality((A1 + 1, d2))
if d2 == 3 and A1 > 5:
return "A" + interval_to_quality((A1 - 1, d2))
if d2 == 4 and A1 < 7:
return "d" + interval_to_quality((A1 + 1, d2))
if d2 == 4 and A1 > 7:
return "A" + interval_to_quality((A1 - 1, d2))
if d2 == 5 and A1 < 8:
return "d" + interval_to_quality((A1 + 1, d2))
if d2 == 5 and A1 > 9:
return "A" + interval_to_quality((A1 - 1, d2))
if d2 == 6 and A1 < 10:
return "d" + interval_to_quality((A1 + 1, d2))
if d2 == 6 and A1 > 11:
return "A" + interval_to_quality((A1 - 1, d2))
return "?"
def interval_to_name(interval):
A1, d2 = interval
ordinal = str(d2 + 1)
quality = interval_to_quality(interval)
name = quality + ordinal
name = pprint(name)
return name
def quality_and_ordinal_to_interval(quality, ordinal):
base_name_to_interval = {
"P1": (0, 0),
"m2": (1, 1),
"M2": (2, 1),
"m3": (3, 2),
"M3": (4, 2),
"P4": (5, 3),
"P5": (7, 4),
"m6": (8, 5),
"M6": (9, 5),
"m7": (10, 6),
"M7": (11, 6),
}
name = quality + str(ordinal)
if name in base_name_to_interval:
return base_name_to_interval[name]
if ordinal < 1:
return interval_difference(quality_and_ordinal_to_interval(quality, ordinal + 7), (12, 7))
if ordinal > 7:
return interval_sum(quality_and_ordinal_to_interval(quality, ordinal - 7), (12, 7))
if re.match(r"[d]+", quality):
degree_of_diminution = len(quality)
if ordinal in [1, 4, 5]:
return interval_sum(quality_and_ordinal_to_interval("P", ordinal), (-degree_of_diminution, 0))
if ordinal in [2, 3, 6, 7]:
return interval_sum(quality_and_ordinal_to_interval("m", ordinal), (-degree_of_diminution, 0))
if re.match(r"[A]+", quality):
degree_of_augmentation = len(quality)
if ordinal in [1, 4, 5]:
return interval_sum(quality_and_ordinal_to_interval("P", ordinal), (degree_of_augmentation, 0))
if ordinal in [2, 3, 6, 7]:
return interval_sum(quality_and_ordinal_to_interval("M", ordinal), (degree_of_augmentation, 0))
def name_to_interval(name):
_, quality, ordinal, _ = re.split(r"^([AdMmP]+)([0-9\-]+)$", name)
ordinal = int(ordinal)
interval_coordinates = quality_and_ordinal_to_interval(quality, ordinal)
A1, d2 = interval_coordinates
i = Interval(A1, d2, name)
return i
class Interval():
def __init__(self, A1, d2, name=""):
self.A1 = A1
self.d2 = d2
self.name = name
self.coordinates = (self.A1, self.d2)
if self.name == "":
self.name = interval_to_name((A1, d2))
def __str__(self):
return "({0},{1})".format(self.A1, self.d2)
#return str((self.A1, self.d2))
def __add__(self, i):
sum = Interval(self.A1 + i.A1, self.d2 + i.d2)
return sum
def __sub__(self, i):
difference = Interval(self.A1 - i.A1, self.d2 - i.d2)
return difference
def __mul__(self, number):
product = Interval(self.A1 * number, self.d2 * number)
return product
def __eq__(self, i):
return (self.A1 == i.A1 and self.d2 == i.d2)
def __ne__(self, i):
return (self.A1 != i.A1 or self.d2 != i.d2)
def __lt__(self, i):
diff = self - i
if diff.A1 == 0 and diff.d2 == 0:
return False
if diff.A1 <= 0 and diff.d2 <= 0:
return True
if diff.A1 >= 0 and diff.d2 >= 0:
return False
if diff.A1 < 0 and diff.d2 > 0:
return (abs(diff.A1) >= diff.d2)
if diff.A1 > 0 and diff.d2 < 0:
# In this case, either self is larger (when diff.A1 >= abs(diff.d2)), or the intervals are incomparable. Either way, self isn't less than i, so return false.
return False
def __le__(self, i):
if self == i:
return True
return (self < i)
def __gt__(self, i):
diff = self - i
if diff.A1 == 0 and diff.d2 == 0:
return False
if diff.A1 <= 0 and diff.d2 <= 0:
return False
if diff.A1 >= 0 and diff.d2 >= 0:
return True
if diff.A1 < 0 and diff.d2 > 0:
# In this case, either i is larger (when diff.A1 >= abs(diff.d2)), or the intervals are incomparable. Either way, self isn't greater than i, so return false.
return False
if diff.A1 > 0 and diff.d2 < 0:
return (diff.A1 >= abs(diff.d2))
def __ge__(self, i):
if self == i:
return True
return (self > i)
base_interval_names = ["P1", "AA0", "d2", "A1", "m2", "AA1", "dd3", "M2", "d3", "A2", "m3", "AA2", "dd4", "M3", "d4", "A3", "P4", "AA3", "dd5", "A4", "d5", "AA4", "dd6", "P5", "d6", "A5", "m6", "AA5", "dd7", "M6", "d7", "A6", "m7", "AA6", "dd8", "M7", "d8", "A7", "dd9", "P8"]
for bin1 in base_interval_names:
i1 = name_to_interval(bin1)
for bin2 in base_interval_names:
i2 = name_to_interval(bin2)
if not (i1 >= i2) and not (i2 >= i1):
print(i1.name, "><", i2.name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment