Ruby:试图理解为什么我的代码有时会完美地工作,但是其他时候会陷入循环

时间:2014-09-09 21:24:27

标签: ruby oop loops random multidimensional-array

因此,我正在为App Academy的训练营进行额外的准备工作,其中一个示例问题是创建一个方法,swingers,它接受一对夫妇的参数并返回一对类似的数组混淆了。

论证的格式如下:([[男,女],[男,女] ..])

我的问题是,大多数时候我执行代码,我收到正确的输出。 但是,有时代码不会执行并陷入循环(我假设)

我确定我没有编写最好的代码,也许我可以改变一些来阻止这个问题。

这是我的代码:

def swingers(couples)
    new_couples = []
    target_size = couples.size
    i = 0 

    males   = couples.each_with_object([]) {|(male,female),arr| arr << male}
    females = couples.each_with_object([]) {|(male,female),arr| arr << female}

    until new_couples.size == target_size
        while true
            current_male   = males[rand(0..males.size-1)]
            current_female = females[rand(0..females.size-1)]

            if !couples.include?([current_male,current_female])
                break
            end
        end

        males.delete(current_male)
        females.delete(current_female)

        new_couples[i] = [current_male, current_female]
        i += 1
    end
    new_couples
end

p swingers([
  ["Clyde", "Bonnie"],
  ["Paris", "Helen"],
  ["Romeo", "Juliet"]
])

当我按下ctrl + c(我正在从Windows运行命令行)时,我收到的错误说明:

  

swingers.rb:14:in include?': Interrupt from swingers.rb:14:in swingers'           来自swingers.rb:32:在''

感谢任何帮助,谢谢!

2 个答案:

答案 0 :(得分:1)

由于这个测试,你永远结束循环:

        if !couples.include?([current_male,current_female])
            break
        end

最后两对夫妇可能会与原始合作伙伴配对,在这种情况下永远无法联系到break

例如,根据您的输入

["Clyde", "Bonnie"],
["Paris", "Helen"],
["Romeo", "Juliet"]

如果你的第一对是克莱德和海伦,而你的第二对是巴黎和邦妮,那只剩下罗密欧与朱丽叶的搭档。你的循环将测试你原来的['Romeo', 'Juliet']数组中是否存在couples,他们会这样做,所以它会尝试生成一个新的配对,但是只剩下一个男性和一个女性,所以它永远不会逃避你的while true

更适合http://codereview.stackexchange.com

的一些注释
  1. 不要这样做:

    males   = couples.each_with_object([]) {|(male,female),arr| arr << male}
    

    这样做:

    males = couples.map(&:first)
    
  2. 不要这样做:

    current_male   = males[rand(0..males.size-1)]
    

    这样做:

    current_male = males.sample
    
  3. 略微更天真(但更短且保证完成,假设至少有两对作为输入)方法。这会生成一组完整的新配对,然后会测试原始配对中是否存在任何新配对。

    def swingers(pairs)
      while true
        new_pairs = pairs.map(&:first).zip(pairs.map(&:last).shuffle)
        return new_pairs unless new_pairs.any? { |pair| pairs.include? pair }
      end
    end
    

答案 1 :(得分:0)

偶尔最后一对最终会与原始合作伙伴结束,因此循环无休止地循环。

某些方法可能会简化您的代码。看看Array#transpose。此外,您可能需要重新考虑您的算法:loop until it fits容易出现此类错误,而您无法预测它将花费多长时间。

假设您将女性数组旋转一个随机数量的位置(Array#rotate)并压缩两个列表以激发新的配对(Array#zip)。