【问题标题】:I need to arrange my list in a specific way - python我需要以特定方式排列我的列表 - python
【发布时间】:2019-05-10 12:03:59
【问题描述】:

基本上,用户输入任何正数,然后程序应该安排一个列表,其中包含直到输入的数字的所有正数,以便列表中 2 个连续元素的总和是一个平方数。如果输入的数字不允许排序,我只想让程序打印错误。这是到目前为止的代码:

u = int(input("ENTER: "))
l = []
for i in range(1, u + 1):
    l.append(i)
o = l
t = []
for elem in l:
    for x in o:
        p = elem + x
        p = math.sqrt(p)
        if p%1 == 0:
            if x == elem:
                break
            else:
                t.append(x)
                t.append(elem)

例如,如果我输入 15,那么列表 t 最终看起来像这样:

[3, 1, 8, 1, 15, 1, 1, 3, 6, 3, 13, 3, 5, 4, 12, 4, 4, 5, 11, 5, 3, 6, 10, 6, 2, 7, 9, 7, 1, 8, 7, 9, 6, 10, 15, 10, 5, 11, 14, 11, 4, 12, 13, 12, 3, 13, 12, 13, 2, 14, 11, 14, 1, 15, 10, 15]

该列表包含理论上可行的所有对,我坚持安排此列表,以便每个数字出现一次,并且每个连续数字都遵循上述属性。

所以我最终要寻找的列表是这样的:

[8, 1, 15, 10, 6, 3, 13, 12, 4, 5, 11, 14, 2, 7, 9]

提前感谢您的任何帮助。

【问题讨论】:

  • 你了解图论或寻路吗?您成功地找到了数字之间的所有联系——现在您需要找到使用这些联系的“最大路径”。搜索并了解这些主题。
  • 感谢您接受我的回答,但我对此感觉不对。我的回答是基于 Jayjayyy 的:主要想法是他(或她)的,而我的更改提高了速度但仍然相对较小。他激励我仔细研究这个问题,我的目的是回馈社区,而不是剥夺他的利益。我以前解决过类似的问题,但他的方法比我的好。请接受他的回答而不是我的回答。

标签: python list function math list-comprehension


【解决方案1】:

我将对@Jayjayyy 的答案进行一些细微的改进。这段代码从@Jayjayyy 稍微修改,稍微复杂一些,但也更快。对于n = 15,此代码在我的系统上快了 7.5 倍以上,对于 n = 30,它快了 19 倍以上。这种速度的提高是通过减少总和为平方数的检查次数并加快这些检查来实现的。我还移动了平方数检查以减少例程自身调用的次数。

最后,我更改了一些变量名,使其更具自我记录性。不过@Jayjayyy 的代码简洁还是很值得称赞的。

import math

def f(listsofar, numbersleft):
    if not numbersleft:
        return listsofar
    result = False
    for i in numbersleft:
        if not listsofar or math.sqrt(listsofar[-1] + i).is_integer():
            result = f(listsofar + [i], [j for j in numbersleft if j != i])
            if result:
                break
    return result

n = int(input("Arrange numbers from 1 to ").strip())
numbers = list(range(1, n+1))
print("Input:", numbers)
print("Output:", f([], numbers))

【讨论】:

    【解决方案2】:

    这将是一种具有递归函数的蛮力方法:

    import math
    
    def f(temp, numbers):
        for i, j in zip(temp[:-1], temp[1:]):
            sqrt = math.sqrt(i+j)
            if int(sqrt) != sqrt:
                return False
        if not numbers:
            return temp
        for i in numbers:
            result = f(temp + [i], [j for j in numbers if j != i])
            if result:
                break
        return result
    
    n = int(input("Arrange numbers from 1 to ").strip())
    numbers = list(range(1, n+1))
    print("Input:", numbers)
    print("Output:", f([], numbers))
    

    以 4 为例:

    Arrange numbers from 1 to 4
    Input: [1, 2, 3, 4]
    Output: False
    

    以 15 为例:

    Arrange numbers from 1 to 15
    Input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
    Output: [8, 1, 15, 10, 6, 3, 13, 12, 4, 5, 11, 14, 2, 7, 9]
    

    【讨论】:

    • @Jayjayyy 这行做了什么:for i, j in zip(temp[:-1], temp[1:]):
    【解决方案3】:

    你快到了。您可以使用 Graphs 完成最后的步骤。列表 t 最好作为表示边的元组对。

    您也可以稍后修改列表,如下所示。

    t =[3, 1, 8, 1, 15, 1, 1, 3, 6, 3, 13, 3, 5, 4, 12, 4, 4, 5, 11, 5, 3, 6, 10, 6, 2, 7, 9, 7, 1, 8, 7, 9, 6, 10, 15, 10, 5, 11, 14, 11, 4, 12, 13, 12, 3, 13, 12, 13, 2, 14, 11, 14, 1, 15, 10, 15]
    t = list(zip(t[::2],t[1::2]))
    

    我建议稍微修改您的原始代码。

    import networkx as nx
    import math
    
    u = int(input("ENTER: "))
    l = []
    for i in range(1, u + 1):
        l.append(i)
    o = l
    t = []
    for elem in l:
        for x in o:
            p = elem + x
            p = math.sqrt(p)
            if p%1 == 0:
                if x == elem:
                    break
                else:
                    t.append((x, elem)) #to keep tuples instead
    

    现在,把它变成一个图形问题。递归查找所有邻居,直到获得最大长度。跟踪您已经访问过的邻居,以避免再次遍历相同的路径。

    G = nx.Graph()
    G.add_edges_from(t)
    #Now, you need to find "new" neighbours for all possible combinations that make the longest chain in your case
    def findPaths(G, current_node, n, to_exclude = None):
        if to_exclude == None:
            to_exclude = set([current_node])
        else:
            to_exclude.add(current_node)
        if n==1:
            return [[current_node]]
        paths = [[current_node]+path for neighbor in G.neighbors(current_node) if neighbor not in to_exclude for path in findPaths(G,neighbor,n-1,to_exclude)]
        to_exclude.remove(current_node)
        return paths
    
    
    allpaths = []
    for node in G:
        allpaths.extend(findPaths(G, node, G.number_of_nodes()))
    if allpaths:
        print('match found')
        [print(x) for x in allpaths]
    else:
        print('no matches')
    

    【讨论】:

      【解决方案4】:

      当您使用两个 For 循环时,您通常会相互添加相同的数字,而不是列表中的下一个 (elem in l == x in o) 总是正确的

      当你使用 (p%1 == 0) 另一个总是 True

      要删除重复项,更正您的代码,然后您可以轻松地将列表变成这样的集合:

      NoDuplicatedList = set(t)

      t 是您要从中删除重复的列表。

      您仍然可能会丢失您拥有的列表的顺序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-15
        • 1970-01-01
        • 2012-06-21
        • 1970-01-01
        • 2010-09-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多