2017-03-18 52 views
1
 def stock_picker prices 
     min_day , max_day , profit = 0 , 0 , 0 
     i = 1 
     while i < prices.length  
      (0...i).each do |day| 
       if prices[i] - prices[day] > profit 
        min_day , max_day , profit = day , i , prices[i] - prices[day] 
       end 
       #i += 1 
      end 
      i += 1 
     end 

      return "[#{min_day}, #{max_day}]" 
     end 

     prices = [17,3,6,9,15,8,6,1,10] 

     puts stock_picker prices 

我的目標是實現一個方法#stock_picker,它接受一個股票價格數組,每個假設的一天。它應該返回一對代表最佳購買日期和最佳銷售日期的日子。天從0開始。更改我的代碼的順序導致錯誤?

我的問題是爲什麼如果我刪除第11行並將其寫入第9行,代碼將不起作用。那麼這將導致錯誤如下:

**PS C:\Users\dlim\mystuff> ruby stockpicker.rb 
stockpicker.rb:8:in `block in stock_picker': undefined method `-' for nil:NilClass (NoMethodError) 
     from stockpicker.rb:7:in `each' 
     from stockpicker.rb:7:in `stock_picker' 
     from stockpicker.rb:29:in `<main>' 

回答

0

哪裏會發生這種情況?

你的錯誤

stockpicker.rb:8:in `block in stock_picker': undefined method `-' for nil:NilClass (NoMethodError) 
    from stockpicker.rb:7:in `each' 
    from stockpicker.rb:7:in `stock_picker' 
    from stockpicker.rb:29:in `<main>' 

是在8號線發生

if prices[i] - prices[day] > profit 

當它試圖訪問prices[i]i = 9prices回報nil, 不迴應歌劇減去- TOR。

爲什麼會發生這種情況?

你是一個循環

(0...i).each do |day| 
    if prices[i] - prices[day] > profit 
     min_day , max_day , profit = day , i , prices[i] - prices[day] 
    end 
    #i += 1 
end 

這裏增加i指數計數器變量並沒有真正意義內的循環,因爲 的day已經在範圍(0...i)和 增加i遍歷值在這個循環內意味着它將prices 數組中的每個值與內部的prices內的下一個day值一次進行比較陣列,這 僅包括prices的前三個值(在 意的值prices數組的末尾,如110永遠不會對 彼此進行比較);例如

i = 1 
prices = [17,3,6,9,15,8,6,1,10] 

# iteration 0 
if prices[i] - prices[day] > profit 
#   3 - 17 > 0 # => false 


# iteration 1 
i += 1 # => 2 
day # => 0 

if prices[i] - prices[day] > profit 
#   6 - 17 > 0 # => false 

i += 1 # => 3 
day # => 1 


# iteration 2 
if prices[i] - prices[day] > profit 
#   9 - 3 > 0 # => true 
min_day, max_day, profit = 1, 3, 6 

i += 1 # => 4 
day # => 0 


# iteration 3 
if prices[i] - prices[day] > profit 
#   15 - 17 > 0 # => false 

i += 1 # => 5 
day # => 1 


# iteration 4 
if prices[i] - prices[day] > profit 
#   8 - 3 > 0 # => true 

min_day, max_day, profit = 1, 5, 5 
i += 1 # => 6 
day # => 2 


# iteration 5 
if prices[i] - prices[day] > profit 
#   6 - 6 > 0 # => false 

i += 1 # => 7 
day # => 3 


# iteration 6 
if prices[i] - prices[day] > profit 
#   1 - 9 > 0 # => false 

i += 1 # => 8 
day # => 0 


# iteration 7 
if prices[i] - prices[day] > profit 
#   10 - 17 > 0 # => false 

i += 1 # => 9 
day # => 1 


# iteration 8 
if prices[i] - prices[day] > profit 
#  nil - 3 > 0 # => NoMethodError 

在第8次迭代,外環,導致發出出界錯誤的時訪問所述價格陣列prices[i] ,但仍與的(0...7)的範圍這是後的設定的 第二環路內迭代第5次迭代,所以 它沒有達到你的while循環的escape子句/表達式 while i < prices.length

可能的解決方案:

你可以繼續你的工作的解決方案,或者您可以通過使用 另一個範圍爲外環

(1...prices.length).each do |i| 
    # ... 
end 

而不是內增加一個索引計數器變量簡化代碼while循環

i = 1 
while i < prices.length 
    # ... 
    i +=1 
end 

看起來像這樣

def stock_picker prices 
    min_day , max_day , profit = 0 , 0 , 0 
    (1...prices.length).each do |i| 
    (0...i).each do |day| 
     if prices[i] - prices[day] > profit 
     min_day , max_day , profit = day , i , prices[i] - prices[day] 
     end 
    end 
    end 

    return "[#{min_day}, #{max_day}]" 
end 

prices = [17,3,6,9,15,8,6,1,10] 

puts stock_picker prices 

它會遍歷下面對天的,按您的要求

[i, day] 
# => [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [7, 0], [8, 0], 
# [2, 1], [3, 1], [4, 1], [5, 1], [6, 1], [7, 1], [8, 1], 
# [3, 2], [4, 2], [5, 2], [6, 2], [7, 2], [8, 2], 
# [4, 3], [5, 3], [6, 3], [7, 3], [8, 3], 
# [5, 4], [6, 4], [7, 4], [8, 4], 
# [6, 5], [7, 5], [8, 5], 
# [7, 6], [8, 6], 
# [8, 7] 

UPDATE:

您也再次與Ruby Array combination method

(0...prices.length).to_a.combination(2) 
簡化它

要生成s AME天爲迭代的唯一且不可重複對在範圍暗示,這將是這樣的

def stock_picker prices 
    min_day , max_day , profit = 0 , 0 , 0 
    (0...prices.length).to_a.combination(2).each do |day, i| 
    if prices[i] - prices[day] > profit 
     min_day , max_day , profit = day , i , prices[i] - prices[day] 
    end 
    end 

    return "[#{min_day}, #{max_day}]" 
end 

prices = [17,3,6,9,15,8,6,1,10] 

puts stock_picker prices 

|day, i|將訪問組合的陣列中日指數對陣列中的第一和第二變量,而重用您使用的現有變量名稱。

+0

喜在迭代例子,你是怎麼算天數?不應該每次按照範圍(0 ... 1)迭代時+1。從我的理解是,在迭代0,一天應該是0,在迭代1,一天應該是1,迭代2天應該是2等等。我認爲我誤解了那裏的某些部分。 – roppo

+0

重新運行您的原始代碼在遇到'nil'之前,我會獲得以下幾個'[i,day]':[1,0],[2,0],[3,1],[4,0], [5,1],[6,2],[7,3],[8,0],[9,1]'。 對於迭代0和迭代1,它是'0'兩次的原因是因爲使用了包容性與獨佔範圍;例如'(0..1).to_a#=> [0,1]'vs'(0 ... 1).to_a#=> [0]'。因此,範圍'(0 ... 1)'將運行一次,這是迭代0,並且對於範圍'(0 ... 2)',這是迭代1和2的兩次。 >使用'構造的範圍。 。從頭到尾包容性地運行。那些使用'...'創建的排除了最終值。 – sonna

1

你基本上試圖改寫combinationmax_by

prices = [17, 3, 6, 9, 15, 8, 6, 1, 10] 
days = (0...prices.size).to_a 
p days.combination(2).max_by { |day1, day2| prices[day2] - prices[day1] } 
# => [1,4] 

如果你想同時日子和相應的價格:

[17,3,6,9,15,8,6,1,10].each.with_index.to_a. 
         combination(2).max_by{|(buy, day1), (sell, day2)| 
         sell-buy 
         } 
# => [[3, 1], [15, 4]] 
相關問題