【问题标题】:Creating chains that loop on themselves创建自循环的链
【发布时间】:2016-05-30 22:16:26
【问题描述】:

我希望有一个数字可以分成 2 个其他数字并检查结束条件,断开每个数字​​直到满足条件。

我想出了下面的例子来试图弄清楚。取一个数字,然后将其分成 2 个数字:一个是原始数字乘以 2,另一个数字是原始数字除以 3,没有余数 (//)。这一直持续到一个数字大于 100、等于 6 或一个平方。

我想记录每一个被退回并在最后打印出来的链。我目前只能通过检查链中的第二个数字来做到这一点,而且我还不够聪明,无法弄清楚如何检查这两个数字。我希望每次将号码分成 2 个新号码时创建一个新链。

目前,这是我所拥有的:

import numpy as np

def check_conditions(number):
    if number > 100:
        return False
    if number == 6:
        return False
    if np.sqrt(number) % 1 == 0:
        return False
    return True

def find_decay(number):
    '''
    Rule: Number is broken into two chains. First chain is 
    mulitplied by 2. Seconds chain is // 3. Same thing happens
    to both chains unless end condition is met:
    1. number is greater than 100
    2. number is equal to 6
    3. number is a perfect square
    '''
    master_chain = []
    while check_conditions(number):
        new_chain1 = [number * 2]
        master_chain.append(new_chain1)
        new_chain2 = [number // 3]
        master_chain.append(new_chain2)
        number = new_chain2[-1]
    return master_chain

if __name__ == '__main__':
    print find_decay(int(raw_input('Number: ')))

有没有人知道如何在 while 循环中检查 2 个单独的数字的条件?

【问题讨论】:

  • 所以你要不断地应用find_decay函数,直到两个数字都满足你的条件?
  • 这些不会是这样的“链”;您将生成一棵树,因为您在每一步都分成两部分。
  • 您正在生成一棵由数字组成的;每个数字分支到两个方向。当然,您仍然可以将所有数字添加到列表中。您需要决定是要一直沿着一个分支向下(深度优先)还是逐级扫描树(呼吸优先)。
  • 深度优先,你最终会得到一个非常无聊的序列:要么你总是以16 结束(沿着//3 分支)要么总是> 100(往下走)。
  • 我认为最好先进入深度。是的,生成树比链更好。

标签: python recursion while-loop


【解决方案1】:

这类问题通常适用于trees 和/或recursion。但是,与满足条件的速度相比,您产生新工作的速度相当高。 (即,虽然每个值的一个乘积不需要太多的操作来超过 100,但在任一叉上找到完美正方形或正好 6 的机会很小)

因此,您需要为您的实现设置一个最大递归深度,否则您将遇到解释器的限制 (sys.getrecursionlimit()) 并且会失败。

我在下面提供了一个简单的示例,说明您可以如何执行此操作,递归地构建一棵树。

但这并不是特别有效,如果您对非常长的“链”感兴趣,那么您可能需要考虑以另一种方式解决这个问题。

import sys
import numpy as np

class Node(object):
    def __init__(self,number,parent):
        self._parent = parent
        self._number = number
        self._satisfied = number > 100 or number == 6 or np.sqrt(number) % 1 == 0
        self._left = None
        self._right = None
        self._depth = parent.depth + 1 if parent != None else 1

    @property
    def parent(self):
        return self._parent

    @property
    def number(self):
        return self._number

    @property
    def satisfied(self):
        return self._satisfied

    @property
    def depth(self):
        return self._depth

    @property
    def left(self):
        return self._left

    @left.setter
    def left(self,value):
        self._left = value

    @property
    def right(self):
        return self._right

    @right.setter
    def right(self,value):
        self._right = value

def print_all_chains(node,chain=[]):
    if node.left is None:
        chain.append(node.number)
        print '{0}: {1}'.format(node.satisfied, chain)
    else:
        print_all_chains(node.left, chain[:] + [node.number])
        print_all_chains(node.right, chain[:] + [node.number])

def build_tree(node, maxDepth):
    if not node.satisfied and node.depth<maxDepth:
        node.left = Node(node.number*2, node)
        build_tree(node.left,maxDepth)
        node.right = Node(node.number//3, node)
        build_tree(node.right,maxDepth)

def find_decay(number):
    root = Node(number,None)
    build_tree(root,maxDepth=10)
    print_all_chains(root)

if __name__ == '__main__':
    find_decay(int(raw_input('Number: ')))

【讨论】:

    【解决方案2】:

    使用简单的Node 类,这可以让您了解树结构。这会按级别顺序遍历树(保证找到最短的链):

    from collections import deque
    import numpy as np
    
    def check_conditions(number):
        return number > 100 or number == 6 or np.sqrt(number) % 1 == 0
    
    class Node():
        def __init__(self, value, parent=None):
            self.value, self.parent = value, parent
    
        def chain(self):
            node = self
            while node:
                yield node.value
                node = node.parent
    
    def find_decay(number):
        agenda = deque([Node(number)])
    
        while agenda:
            node = agenda.popleft()  # use pop() for depth-first
            num = node.value
            if check_conditions(num):
                return list(node.chain())
            agenda.append(Node(num//3, parent=node))
            agenda.append(Node(num*2, parent=node))
    
    
    if __name__ == '__main__':
        for x in find_decay(int(raw_input('Number: '))):
            print x,
    
    37: 37 12 4
    

    【讨论】:

      猜你喜欢
      • 2015-06-09
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 2020-10-31
      • 2017-12-10
      • 2021-09-02
      • 2014-03-06
      • 1970-01-01
      相关资源
      最近更新 更多