【问题标题】:Nested Loops Ruby嵌套循环 Ruby
【发布时间】:2013-06-10 03:15:43
【问题描述】:

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

你有 10 颗鹅卵石(编号为 1-10)。它们默认为黑色。如果它们是黑色的,您必须通过将它们涂成白色或如果它们是白色的将它们涂成黑色来改变它们。有10轮。每一轮,你必须改变当前轮数倍数的鹅卵石。 鹅卵石默认是黑色的。

  • 第一轮,你改变每一块鹅卵石(把它们涂成白色)。
  • 第二轮,你改变所有其他鹅卵石(你画鹅卵石 #2,4,6,8,10 黑色)。
  • 第三轮,你改变卵石#3,6,9。
  • 第四轮你改变卵石#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

【问题讨论】:

  • 你必须使用嵌套循环来解决这个问题吗?因为这是一个简单的问题,如果你尝试用翻转位来解决它。

标签: ruby iteration nested-loops


【解决方案1】:

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

相反,您可以使用 Range#step 迭代每个 nth 元素,从轮的索引开始:

(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}

【讨论】:

    【解决方案2】:

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

    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"]
    

    【讨论】:

      【解决方案3】:

      您的代码中有几个问题。

      • 你使用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]
      

      【讨论】:

        【解决方案4】:

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

        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}"
        

        【讨论】:

          猜你喜欢
          • 2015-11-22
          • 2016-10-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-05
          • 2020-09-15
          相关资源
          最近更新 更多