def pitch_unidir(time, correct): """ Unidirectional pitch-shift into a specified pitch. Starts at most 3 semitones away from the desired pitch. """ trans = ratio(window(1.) + correct) origin = ratio(correct) return interleave([trans, origin], [0., time * 1000], [1, window(.75)])
def env_jagged(etime): """ Jagged envelope: Picks at most 4, at least 2 events for each second of the event time. Each event is categorized by a random amplitude value and time distribution w/ a curve. """ dests = [0.] times = [0.] time_error = 0. loctime = etime while loctime > 0: if loctime > 1.: correct = 1 else: correct = loctime numevents = int((random() * 3. + 2.) * loctime) dests += [random() for i in range(numevents)] time_add = [random() / numevents for i in range(numevents)] next_error = 1. - sum(time_add) if len(time_add) > 0: time_add[0] += time_error times += time_add time_error = next_error loctime -= 1. dests[len(dests) - 1] = 0. times[len(times) - 1] += etime - sum(times) times = [1000. * t for t in times] curves = [0.] + [window(.75) for i in range(1, len(dests) - 1)] + [0.] return interleave(dests, times, curves)
def pitch_peak(time, correct): """ A triangle-wave-like pitch shift. Moves up / down from no-transposition and returns to normal. Guaranteed to reach its destination within the first 75% of the time requested. """ ms = lambda t: _ms(t, time) trans = ratio(window(1.) + correct) origin = ratio(correct) attack_time = random() * .75 + .2 decay_time = 1. - attack_time dest = [origin, trans, origin] times = [0., ms(attack_time), ms(decay_time)] curves = [1.] + window([.75, .75]) return interleave(dest, times, curves)
def amp_in_out(time): """ An AHD envelope. Attack (in the first 75 percent of the time) Hold @ sustain value (20 percent of the time) Sustain value is in between .5 and 1. Decay to 0. for the time remaining """ ms = lambda t: _ms(t, time) attack_time = random() * .55 + .2 sustain_val = random() * .5 + .5 hold_time = random() * .2 decay_time = 1. - attack_time - hold_time dest = [0., sustain_val, sustain_val, 0.] times = [0., ms(attack_time), ms(hold_time), ms(decay_time)] curves = [1., window(.75), 1., window(.75)] return interleave(dest, times, curves)
def env_uniform(etime): """ Uniform cresendo or diminuendo; """ dests = [0., random() * .1 + .05, random() * .25 + .75, 0.] times = [0., 30., etime * 1000. - 60., 30.] curves = [0.] + window([.85, .85]) + [0.] if random() < .5: return interleave(dests, times, curves) return interleave(dests[-1::-1], [0.] + times[-1:0:-1], curves)
def amp_in(time): """ A double-attack crescendo. """ ms = lambda t: _ms(t, time) first_time = random() * .35 + .2 second_time = random() * .3 + .2 decay_time = 1 - first_time - second_time first_val = random() * .4 + .4 dest = [0., first_val, 1., 0.] times = [0., ms(first_time), ms(second_time), ms(decay_time)] curves = [1.] + window([.75, .75, .75]) return interleave(dest, times, curves)
def pitch_cross(time, correct): """ Shifts up then down (or down then up), before returning to the original pitch of the sample. """ ms = lambda t: _ms(t, time) _ts = lambda: random() * .33 + .1 shifts = window([1., 1.]) if (shifts[0] * shifts[1]) > 0: shifts[one([0, 1])] *= -1 trans = [] for s in shifts: trans.append(s + correct) trans = ratio(trans) first = _ts() second = 1 - _ts() - first decay = 1. - (first + second) origin = ratio(correct) dest = [origin] + trans + [origin] times = [0., ms(first), ms(second), ms(decay)] curves = [1.] + window([.75, .75, .75]) return interleave(dest, times, curves)
import numpy as np data = [int(l) for l in read_input('data.input.day9')] # do we care about processing? at least we'll use generators... # walk a window of preamble + 1, the last being the one we check def check(w): p = map(math.fsum, combinations(w[:-1], 2)) v = w[-1] return any(map(lambda n: n == v, p)) preamble = 25 ans = next(x for x in drop(preamble, window(preamble + 1, data)) if not check(x))[-1] # part 2 # find some set of at least 2 numbers that add to value from part 1 # i guess i still don't care about processing though... def check_invalid(n, l): return math.fsum(l) <= n p = partial(check_invalid, ans) l = map(lambda v: drop(v, data), range(0, len(data) - 2)) solns = next(x for x in map(lambda v: last(take_while_list(p, v)), l) if math.fsum(x) == ans) print(min(solns) + max(solns))