我正在尝试编码递归函数(使用的python)以计算11是否在不使用休息的情况下将数字划分为11。我只需要使用此规则https://en.wikipedia.org/wiki/11_(number)
代码有效,但是..我想知道是否有一种方法可以缩小它,也许无需变量" k"?
def f(n, k=0):
if n=="" : return 0
t = ((-1)**(len(n)-1))*int(n[0]) + f(n[1:],k+1)
if k == 0:
if t <= -11 or t >= 11:
return f(str(abs(t)))
elif t == 0:
return True
else:
return False
return t
让我们将设计翻转为(n不优化的)尾巴递归,因此,我们不要使用k
检测到最高级别,而是向下传递t
的增长值,并在最终计算时进行最终计算我们击中了基本情况:
def f(n, t=0):
if not n:
if -11 < t < 11:
return t == 0
return f(str(abs(t)))
return f(n[1:], int(n[0]) - t)
现在,我们总是返回布尔值,而不是以前的混合布尔和整数结果!
它应该是严格的重新调查吗?不允许迭代吗?为了避免将k用作递归深度,您可以使用半回收的方式,并通过迭代来计算t,并使用递归减少t。
def f(n):
t = 0
for i in range(len(n)):
t += (-1)**(i)*int(n[i])
if t == 0 :
return True
if t < 11 and t > -11:
return False
return f(str(abs(t)))
不是您要寻找的内容,但是您可以修改功能以计算n mod m
的结果,然后检查是否为零。类似的东西可以简化为:
def mod11(n):
if not n: return 0
diff = int(n[-1]) - mod11(n[:-1])
if diff < 0: diff = diff and 11 - mod11(str(-diff))
return diff
用法:
>>> mod11("242311") == 0
False
>>> not mod11("242311")
False
>>> not mod11("242308")
True
这是我到目前为止为纯递归(仅一个变量)所能做的最好的。如果字符串评估为零mod 11或否则,它将返回布尔值。
def f(s):
if not s:
return True
r = f(s[1:])
# If the rest of the string evaluates to
# to zero mod 11, there's no need to
# subtract it from the prefix.
if isinstance(r, bool):
return s[0]
n = int(s[0]) - int(r)
return True if n in [-11, 11, 0] else n
for x in ['11', '121', '54734', '1099989', '12', '65637', '1565432', '2345651']:
print (x, f(x))
规则Wiki谈论的是试图测量奇数和偶数位置数字之间的差异。
如果您稍微改写一点,那就意味着只要2个方面不互相操纵,就可以同时处理它们。
(我的现有模块在awk
中,但所有语言的概念方法都是相同的):
function mod11(__, _, ___, ____, _____, ______)
{
sub("^[^0-9+-]*[+-]?[0]*", "", __)
if ((____ = length(substr(__, ___ *= ___ *= _ = ___ += ___ ^= ___ < ___, _))) < _) {
return (! ____ ? __ % (--___ - _ * _) : ((substr(__, -_ < +_, ____ = _ * _) % (___ = --___ - _ * _)) (substr(__, ++____))) % (___))
}
___ = ____ = _____ = ______ = ""
______ = gsub("...." "...." "...." "..", "&=", __)
_____ ^= (____ = ! (___ = (_ *= _ += _ ^= _ < _) + (_ = _ * _ - ++_)))
do {
____ = ((____) substr(__, _____, -_____ + (_____ += ___))) % _
} while (--______)
return ((____) substr(__, _____)) % _
}
基本上做的是 -
如果输入足够小,只需直接使用内置的Modulo操作员
否则,将十进制数字分成14位数字的块
它从十进制数字的左端到右端运行,因为
mod (%) 11
是我所说的base-10 directionally-agnostic
- 含义 - 水平翻转数字,
的另一个例子mod 11
保持不变。"3"
是该每回合,我一次通过
% 11
运行一次,其余的人预先付费到下一轮的大量数字(因此14位数字是我可以从IEEE 754中挤出的最大值,而不会丢失精度)。- - 这是等同于将
的字符串-OPSrunning-remainder x 10**14
添加到下一轮设置块的方式可确保奇怪,甚至数字总是遵循自己的轨道而不是越过。该算法(可以在任何任意尺寸的输入中采用任何)是线性时间到十进制数字#(用二进制术语来说是相当不错的)
然后继续重复直到
2^53 - 1
下的最终块(加上剩余的预伪) - 在返回结果之前,包括1个最终模拟操作
这些想法是来自现有最佳实践的来源的零件,并将其调整为在基本10中直接进行处理,而无需过度转换为二进制。
(无需访问本机位移动操作员,不断将ASCII
字符串除以2的量相当昂贵。这全都基于没有字符串slices的语言,这在此特定用例中可能是有益的)