Ruby 计数阈值点击

Ruby 计数阈值点击,ruby,loops,iterator,logic,time-series,Ruby,Loops,Iterator,Logic,Time Series,一个人跑步,需要帮助。如果你有一系列的数字,并且想计算价值观跨越障碍的次数,你会怎么做 series = [1, 6, 2, 4, 1, 9, 2] series.hit_counts(upper=7, middle=5, lower=3) #returns 3 详细信息 1 -> 6 = +1 (Going from 1 to 6 hits the lower and middle threshold) 6 -> 2 = +0 (The high value, 6, never

一个人跑步,需要帮助。如果你有一系列的数字,并且想计算价值观跨越障碍的次数,你会怎么做

series = [1, 6, 2, 4, 1, 9, 2]
series.hit_counts(upper=7, middle=5, lower=3) #returns 3
详细信息

1 -> 6 = +1 (Going from 1 to 6 hits the lower and middle threshold)
6 -> 2 = +0 (The high value, 6, never reached the upper threshold although it crosses the middle)
2 -> 4 = +0 (2 is below the lower threshold but has not hit the middle)
4 -> 1 = +0 (The series still has not reached the middle threshold)
1 -> 9 = +1 (The series hit the middle threshold)
9 -> 2 = +1 (The series has hit the high and middle thresholds)
limits = { LOWER: 3, MIDDLE: 5, UPPER: 7 }

series = [1, 6, 2, 4, 1, 9, 2]
p score(series,limits)  #=> 3

series = [1,5,12,8,10,4,13,3,1,4,6,4,6,9,1]
p score(series, limits) #=> 5
hit_counts
:统计值达到上限或下限阈值然后越过中间阈值的次数

上限:7

中位数:5

下限:3


所讨论的方法将返回
3
。任何想法都将不胜感激

假设我明白你想要什么,你可以试试这样的东西:

class Array
  def hit_counts(upper=7, middle=5, lower=3)
    limit_broken = false
    each_cons(2).count do |a,b|
      limit_broken = true unless (lower..upper).cover? a
      current_range = Range.new(*[a,b].sort)
      if limit_broken && current_range.cover?(middle)
        limit_broken = false
        true
      else
        false
      end
    end
  end
end

我采取了不同的方法来解决你的问题

代码

INF = Float::INFINITY

def score(series, limits)
  last =
    case series.first
    when (-INF..limits[:LOWER]) then :LOWER
    when (limits[:UPPER]..INF)  then :UPPER
    else :MIDDLE
    end
  series[1..-1].count do |n|
    if limits[last] <= n
      score = (last == :LOWER && n >= limits[:MIDDLE])
      last =
        case n
        when (-INF..limits[:MIDDLE]-1) then :LOWER
        when (limits[:UPPER]..INF) then :UPPER
        else :MIDDLE
        end
    else
      score = (last == :UPPER && n <= limits[:MIDDLE])
      last =
        case n
        when (-INF..limits[:LOWER]) then :LOWER
        when (limits[:MIDDLE]+1..INF) then :UPPER
        else :MIDDLE
        end
    end
    score
  end
end
@BroiSatse对这两个测试序列得到相同的结果

解释

我已将规则更改为我认为更简单的问题,具有相同的得分:

  • levels={LOWER:3,MIDDLE:5,UPPER:7}

  • 玩家从三个级别中的一个开始,
    :LOWER
    :MIDDLE
    :UPPER
    。如果
    f=series.first
    ,则由变量
    last
    保持的该级别为:

    • :下限
      如果
      f=限值[:上限]
    • :中间
      否则
      `
  • 玩家将在不同级别之间移动(或保持在当前级别),当从
    :LOWER
    移动到
    :MIDDLE
    :UPPER
    时,或当从
    :UPPER
    移动到
    :MIDDLE
    :LOWER
    时,将得分
    1

  • 对于每个
    i>0
    ,让
    f=series[i]
    。播放机位于最后一个。移动和计分规则如下:

    • 如果
      limits[last]=limits[:UPPER]
    • :中键
      否则
    • 如果玩家从
      :LOWER
      移动到
      :MIDDLE
      :UPPER
      ,则得分。 `
  • 如果
    f
    (移动到递减值),则玩家移动到(并且
    last
    变为):
    • :如果
      f限制[:中间]
    • :中键
      否则
    • 如果玩家从
      :上
      移动到
      :中
      :下
      ,则得分
  • 对序列中的每个后续元素重复该过程


  • 代码只是以一种简单的方式实现了这些规则。

    当您将更改计算为阈值命中时,并不完全清楚。我最初的猜测是,只有当
    a
    超出
    upper..lower
    范围,并且
    a..b
    包括
    middle
    时,[a,b]才算命中。对的此外,在您的详细信息
    9->2
    中还有一个额外的步骤,它不会出现在您的初始数组中。注释似乎已被截断?请让我知道什么不是clearHit太快进入,现在编辑。谢谢。更新了问题。只有当以前的值达到上限或下限阈值时,计数才会增加。因此,该方法必须考虑的不仅仅是[先前的_值,当前的_值]。当我尝试自己实现它时,我最终使用了一个变量来保存状态(无论它达到了上限还是下限)。因此,事实上,我们只需要对超过两个阈值的对进行计数?