嵌套循环Ruby

时间:2013-06-13 16:19:17

标签: ruby iteration nested-loops

难以理解这个嵌套循环问题:

你有10个鹅卵石(编号为1-10)。它们默认为黑色。如果它们是黑色的,则必须将它们涂成白色,或者如果它们是白色则将它们涂成黑色。共有10轮。每一轮,你必须改变当前回合倍数的鹅卵石。 鹅卵石默认为黑色。

  • 第一轮,你改变每一块鹅卵石(将它们全部涂成白色)。
  • 第二轮,你改变所有其他鹅卵石(你画鹅卵石 #2,4,6,8,10 black)。
  • 第3轮,你改变鹅卵石#3,6,9。
  • 第4轮你改变鹅卵石#4,8。
  • ...
  • ...
  • 第10轮,你改变#10的卵石。

在第10轮之后,哪些鹅卵石被涂成黑色并涂成白色?

我的解决方案没有运行如下(我尝试通过制作一组数字(转换为字符串)并添加“w”(如果涂成白色)并删除“w”(如果涂成黑色)。

(我已经尝试过编辑它以使其运行,但我是嵌套循环的新手,我只是没有理解这个概念)。如果有人能向我解释我做错了什么并给出更好的解决方案,我将不胜感激。

pebbles = (1..10).map {|element| element.to_s}
pebble_colors = (1..10).map {|element| element.to_s}

(1..10).each do |round|
  pebbles_to_paint = []
  pebbles.each_with_index {|element, index| pebbles_to_paint << index if element % round == 0}
  pebbles_to_paint.each do |pebble_number|
    if pebble_color[pebble_number].include?("w")
      pebble_color[pebble_number].delete!("w")
    else
      pebble_color[pebble_number] << "w"
    end
  end
end

4 个答案:

答案 0 :(得分:2)

因为这是关于嵌套循环的,我只是想补充一点,你不一定要遍历每一轮的所有鹅卵石。 (这是10个鹅卵石的100次迭代!)

相反,您可以使用Range#step迭代每个第n个元素,从圆形索引开始:

(1..10).each { |r|
  print "%2d:" % r
  (r..10).step(r) { |i|
    print " #{i}"
  }
  puts
}

产生

 1: 1 2 3 4 5 6 7 8 9 10
 2: 2 4 6 8 10
 3: 3 6 9
 4: 4 8
 5: 5 10
 6: 6
 7: 7
 8: 8
 9: 9
10: 10

那只有27次迭代。一个很好的副作用是你不必再计算余数了。

完整示例:

pebbles = Hash[(1..10).map{|i| [i, :black]}]
toggle = {:black => :white, :white => :black}

(1..10).each { |r|
  (r..10).step(r) { |i|
    pebbles[i] = toggle[pebbles[i]]
  }
}
p pebbles
#=> {1=>:white, 2=>:black, 3=>:black, 4=>:white, 5=>:black, 6=>:black, 7=>:black, 8=>:black, 9=>:white, 10=>:black}

答案 1 :(得分:1)

您的主要问题似乎在于决定绘制哪些鹅卵石。以下是不对的:

element % round == 0

应该是:

(index+1) % round

你想要比较卵石的指数而不是鹅卵石的当前值。同样,您需要记住索引是从0开始的(即它们从0开始计数)。您需要将索引设置为1(因此添加1),否则第一个元素将始终更改而其他元素将关闭1.

pebble_color也有拼写错误,应为pebble_colors

你肯定可以重新考虑代码以缩短代码,但以下似乎可行(只做上面提到的最小变化):

pebbles = (1..10).map {|element| element.to_s}
pebble_colors = (1..10).map {|element| element.to_s}

(1..10).each do |round|
  pebbles_to_paint = []
  pebbles.each_with_index {|element, index| pebbles_to_paint << index if (index+1) % round == 0}
  pebbles_to_paint.each do |pebble_number|
    if pebble_colors[pebble_number].include?("w")
      pebble_colors[pebble_number].delete!("w")
    else
      pebble_colors[pebble_number] << "w"
    end
  end
  p pebble_colors
end

输出结果为:

["1w", "2w", "3w", "4w", "5w", "6w", "7w", "8w", "9w", "10w"]
["1w", "2", "3w", "4", "5w", "6", "7w", "8", "9w", "10"]
["1w", "2", "3", "4", "5w", "6w", "7w", "8", "9", "10"]
["1w", "2", "3", "4w", "5w", "6w", "7w", "8w", "9", "10"]
["1w", "2", "3", "4w", "5", "6w", "7w", "8w", "9", "10w"]
["1w", "2", "3", "4w", "5", "6", "7w", "8w", "9", "10w"]
["1w", "2", "3", "4w", "5", "6", "7", "8w", "9", "10w"]
["1w", "2", "3", "4w", "5", "6", "7", "8", "9", "10w"]
["1w", "2", "3", "4w", "5", "6", "7", "8", "9w", "10w"]
["1w", "2", "3", "4w", "5", "6", "7", "8", "9w", "10"]

答案 2 :(得分:1)

您的代码中存在一些问题。

  • 您使用element % round代替(index + 1) % round

  • 您修改数组pebble_color而不是pebble_colors

修复这两个问题,程序将pebble_colors留下值

["1w", "2", "3", "4w", "5", "6", "7", "8", "9w", "10"]

虽然我认为这不是你的想法!

你有三个阵列可以做。你需要的只是十种颜色的数组,从黑色开始。我会像这样编码

pebbles = Array.new(10, :black)

(1..10).each do |round|
  pebbles.each_with_index do |pebble, i|
    if (i + 1).remainder(round) == 0
      pebbles[i] = pebble == :black ? :white : :black
    end
  end
end

p pebbles

<强>输出

[:white, :black, :black, :white, :black, :black, :black, :black, :white, :black]

答案 3 :(得分:-1)

为了简化问题,我认为在更新卵石之前计算所有圆形倍数会更好。

pebbles = Array.new(10)  

10.times do |i|
  # calculate all multiples for each index
  multiples = Array(1..10).select {|j| j % (i + 1) == 0}

  # observer that we must have to sub 1 since Ruby use 0 indexed arrays
  multiples.map! {|j| j - 1}

  # update each pebble
  multiples.each do |j|
    pebbles[j] = pebbles[j] == 'b' ? 'w' : 'b'
  end
end

puts "Black pebbles: #{pebbles.select {|p| p == 'b'}.size}"