学习红宝石:如何用红宝石解决这个问题?

亚力山大

问题陈述

一所大学只有一个旋转门。它既可以用作出口也可以用作入口。不幸的是,有时很多人想通过旋转栅门,他们的方向可能会有所不同。第i个人在时间[i]到达旋转栅门,并且想要在Direction [i] = 1时退出大学,或者在direciton [i] = 0时进入大学。人们形成2个队列,一个队列退出,一个进入。它们按到达转闸的时间排序,如果时间相等,则按其索引排序。如果某人想同时进入大学而另一人想同时离开大学,则有以下三种情况:

• If in the previous second the turnstile was not used (maybe it was used before, but not at the previous second), then the person who wants to leave goes first.
• If in the previous second the turnstile was used as an exit, then the person who
wants to leave goes first
• If in the previous second the turnstile was used as an entrance, then the person 
who wants to enter goes first

经过旋转闸需要1秒

对于每个人,找到他们通过旋转闸门的时间

该函数必须返回由n个整数组成的数组,当第i个人通过旋转闸门时,index [i]处的值相同

该函数具有以下参数:

• time: an array of n integers where the value at index i is the time when the 
ith person will came to the turnstile
• direction: an array of n  integers where the value at index i is the direction 
of the ith  person

约束条件

• 1 <= n <= 105
• 0 <= time[i] <= 109 for 0 <= i <= n – 1
• time[i] <= time[i+1] for 0 <= i <= n - 2
• 0 <= direction [i] <= 1 for 0 <= i <= n – 1

例:

n = 4

时间= [0,0,1,5]

方向= [0,1,1,0]

输出= [2,0,1,5]

例子2

n = 5

时间= [0,1,1,3,3]

方向= [0,1,0,0,1]

输出= [0,2,1,4,3]


这是我的实际尝试

def getTimes(time, direction)
  persons = time.size - 1
  exits = []
  (0..persons).each do |person|
    if time[person] == time[person + 1]
      exits[person + 1] = time[person] if direction[person + 1] == 1 and direction[person] == 0
    else
      exits[person] = time[person] if direction[person] != direction[person + 1]
    end
  end

  p exits
end

我的回应[nil,0,1,5]

贾维连

stackoverflow通常不是代码编写服务。但是,事实证明这是一个有趣的问题。

因此,我为您编写了一些代码。这里是:

def calculate_turnstile_times(time, direction)
  current_time    = 0
  dir = direction.map { |d| d.zero? ? :enter : :exit }
  enter_queue, exit_queue = time.each_index.map do |i|
                              {person: i, time: time[i], direction: dir[i]}
                            end.partition do |h| 
                              h[:direction] == :enter
                            end.map do |arr| 
                              arr.sort_by { |h| h[:time] }
                            end  

  enterer         = enter_queue.shift
  exiter          = exit_queue.shift

  time.each_with_object([]) do |_t, to_return|
    person_to_go        = nil
    enterer           ||= enter_queue.shift
    exiter            ||= exit_queue.shift
    current_time        = [[enterer,exiter].map{|p|p.try(:[],:time)}.compact.min,current_time].max

    enterer_arrived     = enterer && enterer[:time] <= current_time
    exiter_arrived      = exiter && exiter[:time] <= current_time

    person_to_go    = :enterer if enterer_arrived && !exiter_arrived
    person_to_go  ||= :exiter  if exiter_arrived  && !enterer_arrived
    person_to_go  ||= :exiter  if exiter_arrived  && to_return.empty?
    person_to_go  ||= :exiter  if exiter_arrived  && ((to_return.last.try(:[],:time)||-2) != (current_time-1))
    person_to_go  ||= :enterer if enterer_arrived && to_return.last.try(:[],:direction) == :enter
    person_to_go  ||= :exiter  if exiter_arrived

    case person_to_go
    when :exiter
      person_to_go = exiter 
      exiter = nil
    when :enterer 
      person_to_go = enterer
      enterer = nil
    end

    person_to_go[:time] = current_time
    to_return << person_to_go
    current_time += 1

  end.sort_by{|p| p[:person]}.map{|p| p[:time]}
end

如果您想尝试一下,这是一个RSpec测试:

require 'rails_helper'

RSpec.describe "Turnstiles" do
  it "using calculate_turnstile_times" do 
    %i(calculate_turnstile_times).each do |method_sym|
      test_cases.each do |test_case|
        expect(send(method_sym,test_case[0],test_case[1])).to eq(test_case[2])
      end
    end
  end
end

def test_cases
  [
    [[10],[1],[10]],
    [[0,0,0],[0,0,1],[1,2,0]],
    [[0,0,1,5],[0,1,1,0],[2,0,1,5]],
    [[0,0],[0,1],[1,0]],
    [[0,0],[1,1],[0,1]],
    [[0,0],[1,0],[0,1]],
    [[4,4],[0,1],[5,4]],
    [[0,0,0],[0,1,1],[2,0,1]],
    [[0,0,0],[0,0,0],[0,1,2]],
    [[0,0,0,0],[0,1,1,1],[3,0,1,2]],
    [[0,0,0,5],[0,1,1,1],[2,0,1,5]],
    [[0,1,1,3,3],[0,1,0,0,1],[0,2,1,4,3]],
    [[0,1,1,3,3],[0,1,1,0,1],[0,1,2,4,3]],
    [[0,1,1,6,7],[0,1,1,0,1],[0,1,2,6,7]],
    [[0,1,1,3,6],[0,1,1,0,1],[0,1,2,3,6]],
    [[0,0,1,5],[0,1,1,0],[2,0,1,5]],
    [[0,1,1,3,3],[0,1,0,0,1],[0,2,1,4,3]]
  ]
end

def calculate_turnstile_times(time, direction)
  current_time    = 0
  dir = direction.map { |d| d.zero? ? :enter : :exit }
  enter_queue, exit_queue = time.each_index.map do |i|
                              {person: i, time: time[i], direction: dir[i]}
                            end.partition do |h| 
                              h[:direction] == :enter
                            end.map do |arr| 
                              arr.sort_by { |h| h[:time] }
                            end  

  enterer         = enter_queue.shift
  exiter          = exit_queue.shift

  time.each_with_object([]) do |_t, to_return|
    person_to_go    = nil
    enterer           ||= enter_queue.shift
    exiter            ||= exit_queue.shift
    current_time        = [[enterer,exiter].map{|p|p.try(:[],:time)}.compact.min,current_time].max

    enterer_arrived     = enterer && enterer[:time] <= current_time
    exiter_arrived      = exiter && exiter[:time] <= current_time

    person_to_go    = :enterer if enterer_arrived && !exiter_arrived
    person_to_go  ||= :exiter  if exiter_arrived  && !enterer_arrived
    person_to_go  ||= :exiter  if exiter_arrived  && to_return.empty?
    person_to_go  ||= :exiter  if exiter_arrived  && ((to_return.last.try(:[],:time)||-2) != (current_time-1))
    person_to_go  ||= :enterer if enterer_arrived && to_return.last.try(:[],:direction) == :enter
    person_to_go  ||= :exiter  if exiter_arrived

    case person_to_go
    when :exiter
      person_to_go = exiter 
      exiter = nil
    when :enterer 
      person_to_go = enterer
      enterer = nil
    end

    person_to_go[:time] = current_time
    to_return << person_to_go
    current_time += 1

  end.sort_by{|p| p[:person]}.map{|p| p[:time]}
end

这给了我:

11:44:24 - INFO - Running: spec/so/turnstiles_spec.rb

Turnstiles
  using calculate_turnstile_times

Finished in 0.14996 seconds (files took 1.06 seconds to load)
1 example, 0 failures

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章