在 Elixir 中,为什么我的算法在达到 33 时会变得很奇怪,我该如何解决?
In Elixir, why does my algorthm for finding prime factors go weird once it hits the number 33 and how can I fix it?
我有以下模块来查找质因数:
defmodule PrimeFactors do
def factors_for(number)
when number < 2,
do: []
def factors_for(number),
do: factors_for(number, _next_attempt = 2, _accumulator = [])
def factors_for(number, next_attempt, accumulator)
when next_attempt > number,
do:
accumulator
|> Enum.reverse()
def factors_for(number, next_attempt, accumulator) do
IO.inspect(label: "######## [next_attempt | accumulator] #{[next_attempt | accumulator]}: ")
if rem(number, next_attempt) === 0,
do: factors_for(div(number, next_attempt), next_attempt, [next_attempt | accumulator]),
else: factors_for(number, next_prime(next_attempt), accumulator)
end
defp next_prime(2),
do: 3
defp next_prime(n),
do: n + 2
|> IO.inspect(label: "######## NEXT ")
end
对于大多数数字,它按预期工作:
例如,PrimeFactors.factors_for(10200)
的输出以:
结尾
######## NEXT: : 17
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 17, 5, 5, 3, 2, 2, 2, 58, 32>>
]
[2, 2, 2, 3, 5, 5, 17]
但是对于一些数字,输出变得很古怪。
例如,如果我执行 PrimeFactors.factors_for(10201)
,我们注意到当它命中 next_attempt 33 时,输出非常意外:
######## NEXT: : 29
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 29, 58, 32>>
]
######## NEXT: : 31
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 31, 58, 32>>
]
######## NEXT: : 33
[label: "######## [next_attempt | accumulator] !: "]
######## NEXT: : 35
[label: "######## [next_attempt | accumulator] #: "]
...
######## NEXT: : 99
[label: "######## [next_attempt | accumulator] c: "]
######## NEXT: : 101
[label: "######## [next_attempt | accumulator] e: "]
[label: "######## [next_attempt | accumulator] ee: "]
'ee'
同样,PrimeFactors.factors_for(12221)
的值会下降:
######## NEXT: : 29
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 29, 11, 11, 58, 32>>
]
######## NEXT: : 31
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 31, 11, 11, 58, 32>>
]
######## NEXT: : 33
[label: "######## [next_attempt | accumulator] !\v\v: "]
######## NEXT: : 35
[label: "######## [next_attempt | accumulator] #\v\v: "]
...
[label: "######## [next_attempt | accumulator] a\v\v: "]
######## NEXT: : 99
[label: "######## [next_attempt | accumulator] c\v\v: "]
######## NEXT: : 101
[label: "######## [next_attempt | accumulator] e\v\v: "]
'\v\ve'
(我不知道它是否相关,但是在 exercism.com 的 Diffie Hellman 挑战中,我在尝试提升到 33 的幂时也注意到一些奇怪的行为......似乎让我的应用程序陷入无限循环...)
当您将一个整数列表插入一个字符串时,Elixir 假定该列表是一个 "IO data",因此该列表中的整数被视为字符代码。
要解决此问题,您需要替换此行
IO.inspect(label: "######## [next_attempt | accumulator] #{[next_attempt | accumulator]}: ")
进入这一行
IO.inspect([next_attempt | accumulator], label: "######## [next_attempt | accumulator]", charlists: :as_lists)
选项 charlists: :as_lists
强制 IO.inspect
将字符列表视为整数列表。
我有以下模块来查找质因数:
defmodule PrimeFactors do
def factors_for(number)
when number < 2,
do: []
def factors_for(number),
do: factors_for(number, _next_attempt = 2, _accumulator = [])
def factors_for(number, next_attempt, accumulator)
when next_attempt > number,
do:
accumulator
|> Enum.reverse()
def factors_for(number, next_attempt, accumulator) do
IO.inspect(label: "######## [next_attempt | accumulator] #{[next_attempt | accumulator]}: ")
if rem(number, next_attempt) === 0,
do: factors_for(div(number, next_attempt), next_attempt, [next_attempt | accumulator]),
else: factors_for(number, next_prime(next_attempt), accumulator)
end
defp next_prime(2),
do: 3
defp next_prime(n),
do: n + 2
|> IO.inspect(label: "######## NEXT ")
end
对于大多数数字,它按预期工作:
例如,PrimeFactors.factors_for(10200)
的输出以:
######## NEXT: : 17
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 17, 5, 5, 3, 2, 2, 2, 58, 32>>
]
[2, 2, 2, 3, 5, 5, 17]
但是对于一些数字,输出变得很古怪。
例如,如果我执行 PrimeFactors.factors_for(10201)
,我们注意到当它命中 next_attempt 33 时,输出非常意外:
######## NEXT: : 29
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 29, 58, 32>>
]
######## NEXT: : 31
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 31, 58, 32>>
]
######## NEXT: : 33
[label: "######## [next_attempt | accumulator] !: "]
######## NEXT: : 35
[label: "######## [next_attempt | accumulator] #: "]
...
######## NEXT: : 99
[label: "######## [next_attempt | accumulator] c: "]
######## NEXT: : 101
[label: "######## [next_attempt | accumulator] e: "]
[label: "######## [next_attempt | accumulator] ee: "]
'ee'
同样,PrimeFactors.factors_for(12221)
的值会下降:
######## NEXT: : 29
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 29, 11, 11, 58, 32>>
]
######## NEXT: : 31
[
label: <<35, 35, 35, 35, 35, 35, 35, 35, 32, 91, 110, 101, 120, 116, 95, 97,
116, 116, 101, 109, 112, 116, 32, 124, 32, 97, 99, 99, 117, 109, 117, 108,
97, 116, 111, 114, 93, 32, 32, 31, 11, 11, 58, 32>>
]
######## NEXT: : 33
[label: "######## [next_attempt | accumulator] !\v\v: "]
######## NEXT: : 35
[label: "######## [next_attempt | accumulator] #\v\v: "]
...
[label: "######## [next_attempt | accumulator] a\v\v: "]
######## NEXT: : 99
[label: "######## [next_attempt | accumulator] c\v\v: "]
######## NEXT: : 101
[label: "######## [next_attempt | accumulator] e\v\v: "]
'\v\ve'
(我不知道它是否相关,但是在 exercism.com 的 Diffie Hellman 挑战中,我在尝试提升到 33 的幂时也注意到一些奇怪的行为......似乎让我的应用程序陷入无限循环...)
当您将一个整数列表插入一个字符串时,Elixir 假定该列表是一个 "IO data",因此该列表中的整数被视为字符代码。
要解决此问题,您需要替换此行
IO.inspect(label: "######## [next_attempt | accumulator] #{[next_attempt | accumulator]}: ")
进入这一行
IO.inspect([next_attempt | accumulator], label: "######## [next_attempt | accumulator]", charlists: :as_lists)
选项 charlists: :as_lists
强制 IO.inspect
将字符列表视为整数列表。