cs61a3_2Design

这篇博客探讨了如何使用Python手动编码超级马里奥的音频,介绍了一个接受条件函数和数字n,打印出满足条件的数字的函数。此外,还讨论了更高阶的函数概念,包括柯里化和延迟打印,以及设计能够重复打印n次参数的函数。
摘要由CSDN通过智能技术生成

Design

前面三个部分Function Abstraction、Choosing Names、Which Values Deserve a Name都是前面讲过的知识,重点在于这次的example,手动编码超级马里奥的音频:

Function Example: Sounds

请添加图片描述

所有的wav文件都是声音波长函数编码而来,波长每个时刻都有其振幅(amplitude),相当于是一个近似连续的间断性函数,用尽可能多的点描述连续的声音,通常声音都是从真实世界中录取的,但是同样也可以通过直接编码来创造,有一些数学函数提供了简单标准的波长,比如上图中的sine,square,triangle,sawtooth,在电子乐中有很多应用,这个例子中主要就是以triangle波长函数才创造音乐的

from wave import open
from struct import Struct #以wav文件需要的形式编码整型
from math import floor

frame_rate = 11025 #帧率,每秒有多少个声波函数对应的值

def encode(x):
    """encode float x between -1 and 1 as two bytes"""
    i = int(16384 * x)
    return Struct('h').pack(i)

def play(sampler, name = 'song.wav', seconds = 2):
    """Write the output of a sampler function as a wav file"""
    out = open(name, 'wb')
    out.setnchannels(1)
    out.setsampwidth(2)
    out.setframerate(frame_rate)
    t = 0
    while t < seconds * frame_rate:
        sample = sampler(t)
        out.writeframes(encode(sample))
        t = t + 1
    out.close()

def tri(frequency, amplitude = 0.3):
    """A continuous triangle wave"""
    period = frame_rate // frequency #一个周期里要取多少个点
    def sampler(t):
        saw_wave = t / period - floor(t / period +0.5)
        tri_wave = 2 * abs(2 * saw_wave) - 1
        return amplitude * tri_wave
    return sampler

c_freq, e_freq, g_freq = 261.63, 329.63, 392.00
def both(f, g):
    return lambda t: f(t) + g(t)

def note(f, start, end, fade = 0.01):
    def sampler(t):
        seconds = t / frame_rate
        if seconds < start or seconds > end:
            return 0
        elif seconds < start + fade:
            return (seconds - start) / fade * f(t)
        elif seconds > end - fade:
            return (end - seconds) / fade * f(t)
        else:
            return f(t)
    return sampler

def mario_at(octave):
    c, e = tri(octave * c_freq), tri(octave * e_freq)
    g, low_g = tri(octave * g_freq), tri(octave * g_freq * 0.5)
    return mario(c, e, g, low_g)
# play(both(note(c, 0, 1/4), note(e, 1/2, 1)))

def mario(c, e, g, low_g):
    z = 0
    song = note(e, z ,z + 1/8)
    z += 1/8
    song = both(song, note(e, z ,z + 1/8))
    z += 1/4
    song = both(song, note(e, z ,z + 1/8))
    z += 1/4
    song = both(song, note(c, z ,z + 1/8))
    z += 1/8
    song = both(song, note(e, z ,z + 1/8))
    z += 1/4
    song = both(song, note(g, z ,z + 1/4))
    z += 1/2
    song = both(song, note(low_g, z ,z + 1/8))
    z += 1/2
    return song

play(both(mario_at(1), mario_at(0.5)))

Disc 02: Higher-Order Functions, Self Reference

Question

1.1Write a function that takes in a function cond and a number n and prints numbers from 1 to n where calling cond on that number returns True.

def keep_ints(cond, n):
    """Print out all integers 1..i..n where cond(i) is true
    >>> def is_even(x):
    ...     # Even numbers have remainder 0 when divided by 2.
    ...     return x % 2 == 0
    >>> keep_ints(is_even, 5)
    2
    4
    """
    i = 1
    while i <= n:
        if cond(i) == True:
            print(i)
        i += 1

1.2 Tutorial: Write a function similar to keep_ints like before, but now it takes in a number n and returns a function that has one parameter cond. The returned function prints out numbers from 1 to n where calling cond on that number returns True.相当于对前面一个函数做了柯里化

def make_keeper(n):
    """Returns a function which takes one parameter cond and prints out
    all integers 1..i..n where calling cond(i) returns True.
    >>> def is_even(x):
    ...     # Even numbers have remainder 0 when divided by 2.
    ...     return x % 2 == 0
    >>> make_keeper(5)(is_even)
    2
    4
    """
    def make_ints(cond):
        i = 1
        while i <= n:
            if cond(i) == True:
                print(i)
            i += 1
    return make_ints

1.3 Draw the environment diagram that results from executing the code below.

def curry2(h):
	def f(x):
		def g(y):
			return h(x, y)
		return g
	return f
make_adder = curry2(lambda x, y: x + y)
add_three = make_adder(3)
add_four = make_adder(4)
five = add_three(2) #5

1.4 Write curry2 as a lambda function.

lambda h: lambda x: labmda y: h(x, y)

1.5 Tutorial: Draw the environment diagram that results from executing the code below.

n = 7

def f(x):
	n = 8
	return x + 1
	
def g(x):
	n = 9
	def h():
		return x + 1
	return h
	
def f(f, x):
	return f(x + n)

f = f(g, n)
g = (lambda y: y())(f) #15

1.6 The following question is more challenging than the previous ones. Nonetheless, it’s a fun problem to try. Draw the environment diagram that results from executing the code below. Note that using the + operator with two strings results in the second string being appended to the first. For example “C” + “S” concatenates the two strings into one string “CS”.

y = "y"
h = y
def y(y):
	h = "h"
	if y == h:
		return y + "i"
	y = lambda y: y(h)
	return lambda h: y(h)
y = y(y)(y)  #"hi"有点复杂但是逻辑清楚了就可以算出来

1.7 Write a function print delayed that delays printing its argument until the next function call. print delayed takes in an argument x and returns a new function delay print. When delay print is called, it prints out x and returns another delay print.

def print_delayed(x):
    """Return a new function. This new function, when called,
    will print out x and return another function with the same
    behavior.
    >>> f = print_delayed(1)
    >>> f = f(2)
    1
    >>> f = f(3)
    2
    >>> f = f(4)(5)
    3
    4
    >>> f("hi")
    5
    <function print_delayed> # a function is returned
    """
    def delay_print(y):
        print(x)
        return print_delayed(y)
    return delay_print

1.8 Tutorial: Write a function print n that can take in an integer n and returns a repeatable print function that can print the next n parameters. After the nth parameter, it just prints ”done”.

def print_n(n):
    """
    >>> f = print_n(2)
    >>> f = f("hi")
    hi
    >>> f = f("hello")
    hello
    >>> f = f("bye")
    done
    >>> g = print_n(1)
    >>> g("first")("second")("third")
    first
    done
    done
    <function inner_print>
    """
    def inner_print(x):
        if n <= 0:
            print("done")
        else:
            print(x)
        return print_n(n-1)
    return inner_print

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值