52 lines
2.0 KiB
Python
52 lines
2.0 KiB
Python
#!python3
|
|
import random
|
|
|
|
"""generates a musical instrument by choosing at random a hornbostel-sachs category.
|
|
|
|
this version is uniformly distributed between the options at each level, but does not include suffxes."""
|
|
|
|
|
|
strip_dashes_and_dots = lambda x: x.replace("-", "").replace(".", "").replace(" ", "")
|
|
def generate_instrument(listing):
|
|
""" listing contains a hornbostel-sachs dictionary; this steps through index-by-index
|
|
picking numbers at random one by one until it's gotta stop, so this has even chances
|
|
of every category, rather than an even chance to every listing."""
|
|
|
|
nice_from_stripped = {strip_dashes_and_dots(x): x for x in listing.keys()}
|
|
stripped_keys = [strip_dashes_and_dots(x) for x in listing.keys()]
|
|
|
|
prefix = random.choice([x for x in stripped_keys if len(x) == 1])
|
|
|
|
final_code = pick_code(prefix, [x for x in stripped_keys if x.startswith(prefix)])
|
|
return nice_from_stripped[final_code]
|
|
|
|
# this defines a threshhold for quitting early dependent on the length of the code so far.
|
|
# so there's a 0% chance of stopping with a zero-length code, 0% with a 1-length code, 1% with 2-length...
|
|
chance_of_stopping = [0, 0, 0.01, 0.01, 0.01, 0.05, 0.05, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
|
|
def pick_code(prefix, keys):
|
|
if random.random() < chance_of_stopping[len(prefix)]:
|
|
return prefix
|
|
|
|
# only look at keys that are one longer than the current key
|
|
next_keys = [x for x in keys if len(x) == len(prefix) + 1]
|
|
if len(next_keys) == 0:
|
|
return prefix # if we can't find any successors then stop
|
|
|
|
next_prefix = random.choice(next_keys)
|
|
|
|
return pick_code(next_prefix, [x for x in keys if x.startswith(next_prefix)])
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
with open("Hornbostel-Sachs") as f:
|
|
hornbostelsachs = {line.split(" ")[0]: " ".join(line.split(" ")[1:]) for line in f.readlines()}
|
|
|
|
val = generate_instrument(hornbostelsachs)
|
|
|
|
parents = [val[0:x+1] for x in range(len(val)) if val[x].isdigit()]
|
|
|
|
for x in parents:
|
|
print(x, " : ", hornbostelsachs[x].strip())
|