1

我正在处理 Codewars Ruby 问题,但不明白我看到的错误。以下是说明:

用阶乘编码十进制数是一种在依赖阶乘而不是数字幂的基础系统中写出数字的方法。在此系统中,最后一位数字始终为 0,并且以 0 为基数!之前的数字是 0 或 1,并且以 1 为基数!之前的数字是 0、1 或 2,并且以 2 为基数!更一般地,倒数第 n 个数字始终为 0、1、2、... 或 n,并且以 n! 为基数。

示例:十进制数 463 编码为“341010”

因为 463(以 10 为底)= 3×5!+ 4×4!+ 1×3!+ 0×2!+ 1×1!+ 0×0!

如果我们仅限于数字 0...9,我们可以编码的最大数字是 10!- 1。

所以我们用字母 A 到 Z 扩展 0..9。有了这 36 个数字,我们最多可以编码 36 个!− 1 = 37199332678990121746799944815083519999999910(基数为 10)

我们编写了两个函数,第一个将编写一个十进制数并返回一个具有阶乘表示的字符串:“dec2FactString(nb)”

第二个将解码具有阶乘表示的字符串并生成十进制表示:“factString2Dec(str)”。

给定的数字将是正数。

笔记

您可以希望在 Clojure、Python、Ruby、Haskel 中使用大整数进行测试,但不能使用 Java 和其他“dec2FactString(nb)”中的数字“nb”至多很长的东西。

参考:http ://en.wikipedia.org/wiki/Factorial_number_system

def dec2FactString(nb)
  if nb <= 0 then
    num = 1
  else
    num = (nb * dec2FactString(nb - 1))
  end
  return num
end

请注意,此方法只是问题的前半部分。此代码似乎可以工作,因为它返回正确的阶乘,在使用此测试时作为 Fixnum:

Test.assert_equals(dec2FactString(4), "24") 

由于指令要求输入字符串,我通常认为只需将“.to_s”添加到 num 变量就可以解决这个问题,但我看到的是一致的“字符串不能被强制转换为 Fixnum (TypeError) “ 错误信息。我尝试将输出推送到数组并从那里打印,但看到了同样的错误。

我对 Fixnum 进行了一些阅读,并且我理解将 Fixnum 添加到字符串中的错误不起作用,但我认为在这种情况下我不会这样做 - 我只想转换 Fixnum 输出成一个字符串。我错过了什么吗?

观察 - 此代码中断并在其下方产生错误:

def dec2FactString(nb)
  if nb <= 0 then
    num = 1
  else
    num = (nb * dec2FactString(nb - 1))
  end
  return num.to_s
end

Example from description
 `*': String can't be coerced into Fixnum (TypeError)
    from `dec2FactString'
    from  `dec2FactString'
    from  `dec2FactString'
    from  `dec2FactString'
    from  `block in 
'
    from  `block in describe'
    from  `measure'
    from  `describe'
    from  `
'
4

2 回答 2

4

您正在递归调用此函数。如果您计算了 1 的阶乘并to_s留在那里,那很好,因为您没有重用该变量。

但是,如果您确实放置to_s在那里,您希望结果num = (nb * dec2FactString(nb - 1))是什么? dec2FactString将返回 astr而不是 a Fixnum,并且您不能/不应该能够在数字和字符串之间进行乘法运算。

您可以做的是通过创建两种方法来拆分字符串化和计算的职责——一种委托给递归函数,另一种将其结果强制转换为字符串。

def dec2FactString(nb)
    return fact(nb).to_s
end

def fact(nb)
    if nb <= 0 then
        1
    else
        nb * fact(nb - 1)
    end
end
于 2015-08-03T17:59:34.567 回答
0

首先,阶乘仅在非负数上定义,因此您的第一个测试不正确(如果 nb <= 0)。当数字为 0 时,递归应该停止,并且应该在该点返回 1。

因为您的递归返回的是字符串而不是数字,所以您不能在下一轮递归中将字符串乘以 Fixnum。您的递归可以通过替换方法扩展到以下内容。

dec2FactString(5)
5 * dec2FactString(4)
5 * 4 * dec2FactString(3)
5 * 4 * 3 * dec2FactString(2)
5 * 4 * 3 * 2 * dec2FactString(1)
5 * 4 * 3 * 2 * 1 * dec2FactString(0)
5 * 4 * 3 * 2 * 1 * "1"

...这就是递归以错误结束的点,因为 dec2FactString(0) 返回“1”

把它分成两个功能会好得多。一种递归计算阶乘,一种将最终答案转换为字符串。此外,您不需要在 Ruby 中显式返回值。函数的最后一行是返回值。

我不会给你完整的代码,因为你不会学到任何东西。作为一些提示,请对 Ruby 中的尾调用优化、递归和返回值进行一些研究。这将使您能够更好地实现递归函数。

快乐编码!

于 2015-08-03T19:49:11.253 回答