首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Collatz图猜想

Collatz图猜想
EN

Code Review用户
提问于 2022-01-14 23:08:12
回答 1查看 118关注 0票数 3

我有一个赋值任务,我为一系列从1到N的初值编写了Collatz猜想程序,并绘制了两幅图:迭代次数与初始值和计算数与初始值。指派提示符是:

现在,修改您的程序,以便它计算3个向量。第一个向量s(k)是起始数( N ),向量f(k)在迭代时将计算出的数作为起始数N的函数存储,g(N)是到达数字1所需的迭代次数。例如,如果N=4、s、f和g看起来是:= 1,2,2,3,3,3,3,3,3,3,4,4 = 1,2,1,3,10,16,8,4,2,1,4,2,1 = 0,1,7,2,则可以在一个窗口中绘制这些值的图,并使其x和y轴范围从1到N,对两个轴都使用从1到200的数字范围。

这是我的密码。

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt

# INPUTS
# Set N to a positive integer. The Hailstone problem program
# will be evaluated for starting numbers from 1 to N.
N = 200
marker_size = 7

s_no_repeats = range(1, N+1) # starting number vector (with NO repeating starting values)

def flatten(t):
    ''' Create flatlist out of list of lists '''
    return [item for sublist in t for item in sublist]

def find_repeat(numbers):
    '''Check repeating value in list and returns the value'''
    seen = set()
    for num in numbers:
        if num in seen:
            return num
        seen.add(num)

def Collatz(n):
    k = 0 # current iteration number
    computed_nums = [n] # sequence of computed numbers from n to 1
    iterations = [0]
    while n != 1:
        if n % 2 == 0:
            n = (n / 2)
        else:
            n = ((n * 3) + 1)
        k += 1
        computed_nums.append(n)
        iterations.append(k)
    
    map(int, computed_nums)
    return (computed_nums, k)

s = [] # starting number vector (with repeating starting values)
f = [] # computed number vector as function of starting number N at iteration k
g = [] # number of iterations required to get to 1

for starting_num in s_no_repeats:
    temp_f, temp_g = Collatz(starting_num)
    #print(temp_f)
    f.append(temp_f)
    g.append(temp_g)
    s.append([starting_num] * (temp_g + 1))

s = flatten(s)
f = flatten(f)

print("s vector (starting nums): " + str(s))
print("f vector (computed nums): " + str(f))
print("g vector (iterations): " + str(g))

fig, (ax1, ax2) = plt.subplots(1, 2)

# left subplot (for computed values)
ax1.scatter(s, f, color="blue", s=marker_size, clip_on=False, zorder = 10)
ax1.set_title('range of computed values during iteration')
ax1.set_xlabel('starting value')
ax1.set_xlim([1, N])
ax1.set_ylim([1, N])

# right subplot (for iterations)
ax2.scatter(s_no_repeats, g, color="red", s=marker_size, clip_on=False, zorder = 10)
ax2.set_title('number of iterations')
ax2.set_xlabel('starting value')
ax2.set_xlim([1, N])
ax2.set_ylim([1, N])

fig.tight_layout() # automatically adjusts enough space between subplots

我想知道这能不能得到改善?

EN

回答 1

Code Review用户

发布于 2022-01-15 20:38:48

您不使用Numpy,所以删除您的导入。

N是一个参数,而不是常量-因此,将代码重构为传递它的函数,从而从全局命名空间中删除代码。

删除flatten函数,使用list.extend而不是append来构建列表。

find_repeat不用于删除它。

Collatz应该是PEP8的小写.

考虑使用divmod执行组合除法2和模数2。

从您的iterations函数中删除collatz,因为您不使用它。

为您的sfg列表和axis对象提供更有意义的名称。

clip_onzorder只是把它们弄得一团糟,把它们删除。

增加一个__main__守卫。

在你的两个子图之间改变颜色是没有价值的,因为它们有独立的轴。如果您试图在相同的轴上绘制两个数据集,您将需要单独的颜色。

添加PEP484类型提示。

考虑减少点的α通道,以便更容易地说明点密度。

您的map调用的返回未使用,所以请删除它。

建议

代码语言:javascript
复制
import matplotlib.pyplot as plt


def collatz(n: int) -> tuple[
    list[int],  # computed_nums
    int,        # current iteration number
]:
    k = 0                # current iteration number
    computed_nums = [n]  # sequence of computed numbers from n to 1
    while n != 1:
        half_n, odd = divmod(n, 2)
        if odd:
            n = n*3 + 1
        else:
            n = half_n
        k += 1
        computed_nums.append(n)

    return computed_nums, k


def collatz_all(n: int) -> tuple[
    list[int],  # starting
    list[int],  # computed
    list[int],  # iterations
    range,      # starting_no_repeats
]:
    starting_no_repeats = range(1, n + 1)  # starting number vector (with NO repeating starting values)

    starting = []  # starting number vector (with repeating starting values)
    computed = []  # computed number vector as function of starting number N at iteration k
    iterations = []  # number of iterations required to get to 1

    for starting_num in starting_no_repeats:
        temp_f, temp_g = collatz(starting_num)
        computed.extend(temp_f)
        iterations.append(temp_g)
        starting.extend([starting_num] * (temp_g + 1))

    return starting, computed, iterations, starting_no_repeats


def plot(starting, computed, iterations, starting_no_repeats, n: int) -> plt.Figure:
    fig, (ax_computed, ax_iterations) = plt.subplots(nrows=1, ncols=2)
    style = {
        's': 7,
        'alpha': 0.2,
    }

    # left subplot (for computed values)
    ax_computed.scatter(starting, computed, **style)
    ax_computed.set_title('range of computed values during iteration')
    ax_computed.set_xlabel('starting value')
    ax_computed.set_ylim((0, n))

    # right subplot (for iterations)
    ax_iterations.scatter(starting_no_repeats, iterations, **style)
    ax_iterations.set_title('number of iterations')
    ax_iterations.set_xlabel('starting value')
    ax_iterations.set_ylim((0, n))

    fig.tight_layout()  # automatically adjusts enough space between subplots
    return fig


def main() -> None:
    # INPUTS
    # Set N to a positive integer. The Hailstone problem program
    # will be evaluated for starting numbers from 1 to N.
    n = 200

    starting, computed, iterations, starting_no_repeats = collatz_all(n)
    print(f"s vector (starting nums): {starting}")
    print(f"f vector (computed nums): {computed}")
    print(f"g vector (iterations): {iterations}")

    plot(starting, computed, iterations, starting_no_repeats, n)
    plt.show()


if __name__ == '__main__':
    main()

该地块位于一个大窗口中,因此透明度效果并不十分明显:

对于一个浓缩的窗口来说,它变得更重要:

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/272993

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档