我怎么能把这个ruby kata解决方案变成一个递归方法呢?

时间:2014-12-09 16:16:09

标签: ruby recursion

我解决了一个kata,要求我构建一个方法,告诉你建造一个具有指定楼层的纸牌所需的卡数量。以下是对该kata的描述:

  

你想建立一个标准的纸牌屋,但你不知道你会有多少张牌   需要。编写一个程序,根据编号计算最小数量的卡片   你想要的楼层。例如,如果你想要一层楼的房子,你将需要7个   它们(底层有两对两张卡,一张水平卡和一对可以得到   第一层)。在这里你可以看到我的意思是哪种纸牌:   http://www.wikihow.com/Build-a-Tower-of-Cards *

     

详细信息:输入必须是大于0的整数,其他输入引发错误。*

以下是解决此问题的代码:

def house_of_cards(floors)
  raise StandardError if floors.class != Numeric && floors < 0
  cards_to_add_to_foundation = 0
  floors = floors
  until floors.zero? 
    cards_to_add_to_foundation += ((2 * (floors + 1)) + floors)
    floors -= 1
  end
 cards_to_add_to_foundation + 2
end

这不是我最初想要解决的问题。我尝试将其作为递归方法,如下所示。

def house_of_cards(floors)
 return cards_to_add_to_foundation + 2 if floors.zero? 
 cards_to_add_to_foundation = 0
 cards_to_add_to_foundation += ((2 * (floors + 1)) + floors)
 house_of_cards(floors - 1)
end

但是,这段代码给了我这个错误:    NameError: undefined local variable or method cards_to_add_to_foundation for main:Object

为什么我会收到此错误。我把它定义在第二行下面。如果我在return语句之前移动cards_to_add_to_foundation,该函数将继续将变量设置为零,这不是我想要的。有没有人有任何建议来完成这个递归方法。我一直在努力解决这个问题,但是我的大脑仍在努力解决这个问题。

最后,当我的初始代码解决了kata时,在这个特定的解决方案中,StandardError部分打破了kata并且不会通过提交。这是引发错误的正常方式吗?如果你查看描述,任务说如果输入小于零则引发错误os不是整数。还有哪些方法可以引发一般性错误?

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

您收到错误是因为您在没有定义的情况下添加到cards_to_add_to_foundation。

我修正了递归,但你确定0层的结果应该是2吗?

def house_of_cards(floors, cards_to_add_to_foundation = 0)
    return cards_to_add_to_foundation + 2 if floors.zero? 
    cards_to_add_to_foundation += ((2 * (floors + 1)) + floors)
    house_of_cards(floors - 1, cards_to_add_to_foundation )
end

2.1.2 :015 > house_of_cards 0
 => 2
2.1.2 :016 > house_of_cards 1
 => 7
2.1.2 :017 > house_of_cards 2
 => 15
2.1.2 :018 > house_of_cards 3
 => 26

此外,您可能希望验证输入为负数会导致SystemStackError:堆栈级别太深。我只想用floors.zero?

替换floors <= 0

答案 1 :(得分:0)

  

为什么我会收到此错误。我把它定义在第二行下面。

完全。每个函数调用都在它自己的堆栈上运行。因此局部变量仅在当前堆栈的范围内可用。因此,只要floors.zero?为真,就会对您的变量cards_to_add_to_foundation起作用,但在此堆栈中它是未定义的。

将其转换为递归函数的最简单方法是将要跟踪的变量与楼层一起传递

def house_of_cards(floors, cards_to_add_to_foundation = 0)
  return cards_to_add_to_foundation if floors.zero?
  return cards_to_add_to_foundation + 2 if floors == 1
  cards_to_add_to_foundation += ((2 * (floors + 1)) + floors)
  house_of_cards(floors - 1, cards_to_add_to_foundation)
end
  

如果您查看说明,该任务表示如果出现错误则引发错误   输入小于零操作系统不是整数。

您可以明确地引发错误

raise "error" if !floors.is_a? Integer || floors < 0

如果floors不是整数或者小于零,则应该引发错误。您可以将其直接放在house_of_cards方法中,也可以编写一个仅检查变量一次的包装器方法,然后在house_of_cards中传递它们。