Skip to content

Instantly share code, notes, and snippets.

@klingtnet
Created October 20, 2019 20:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save klingtnet/7e3dc92b9bf77a41a31981de7716ff2b to your computer and use it in GitHub Desktop.
Save klingtnet/7e3dc92b9bf77a41a31981de7716ff2b to your computer and use it in GitHub Desktop.
import unittest
import itertools
from typing import List
def flatten(f):
def wrapper(*args, **kwargs):
nested = f(*args, **kwargs)
return list(itertools.chain(*nested))
return wrapper
@flatten
def ecd(on: int, total: int) -> List[int]:
"""Source: https://github.com/dbkaplun/euclidean-rhythm/blob/master/euclidean-rhythm.js"""
if total < 0:
raise ArgumentException("total must be larger than zero")
if total == 0:
return []
if on == 0:
return [[0]] * total
if on == total:
return [[1]] * total
# Example ecd(3,4)
# groups = [[1],[1],[1],[0]]
groups = [[int(x < on)] for x in range(0, total)]
l = len(groups) - 1
while l > 0:
start = 0
first = groups[0]
while start < l and first == groups[start]:
start += 1
if start == l:
break
end = l
last = groups[l]
while end > 0 and last == groups[end]:
end -= 1
if end == 0:
break
cnt = min(start, l - end)
t_group = groups[0:cnt]
t_group = [group + groups[l - i] for (i, group) in enumerate(t_group)]
groups = t_group + groups[cnt:-cnt]
l = len(groups) - 1
return groups
class TestECD(unittest.TestCase):
def test_ecd(self):
for (args, expected) in [
((1, 2), [1, 0]),
((0, 4), [0, 0, 0, 0]),
((5, 5), [1, 1, 1, 1, 1]),
((2, 4), [1, 0, 1, 0]),
((5, 6), [1, 1, 1, 1, 1, 0]),
((5, 7), [1, 0, 1, 1, 0, 1, 1]),
((5, 8), [1, 0, 1, 1, 0, 1, 1, 0]),
]:
self.assertEqual(ecd(*args), expected)
if __name__ == "__main__":
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment