我正试图解决这个问题:
使用24小时制显示以小时和分钟为单位的时钟的两个时钟正在运行 速度。每个时钟都是每小时的精确分钟数。两个时钟都开始显示相同的时间 (00:00)并按照准确的计时器每小时(一小时后开始)定期检查。 两个时钟在第一次检查并显示同一时间时会显示几点? 注意:对于这个问题,我们只关心检查时的时钟匹配。 例如,假设第一个时钟快速运行1分钟(每小时),第二个时钟运行31分钟 快(每小时)。 •一小时后首次检查时钟时,第一个时钟将显示01:01和第二个时钟 将显示01:31; •两小时后检查时钟时,它们将显示02:02和03:02; •48小时后,时钟将显示00:48。
这是我的代码:
def add_delay(min,hash)
hash[:minutes] = (hash[:minutes] + min)
if hash[:minutes] > 59
hash[:minutes] %= 60
if min < 60
add_hour(hash)
end
end
hash[:hour] += (min / 60)
hash
end
def add_hour(hash)
hash[:hour] += 1
if hash[:hour] > 23
hash[:hour] %= 24
end
hash
end
def compare(hash1,hash2)
(hash1[:hour] == hash2[:hour]) && (hash1[:minutes] == hash2[:minutes])
end
#-------------------------------------------------------------------
first_clock = Integer(gets) rescue nil
second_clock = Integer(gets) rescue nil
#hash1 = if first_clock < 60 then {:hour => 1,:minutes => first_clock} else {:hour => 1 + (first_clock/60),:minutes => (first_clock%60)} end
#hash2 = if second_clock < 60 then {:hour => 1,:minutes => second_clock} else {:hour => 1 + (second_clock/60),:minutes => (second_clock%60)} end
hash1 = {:hour => 0, :minutes => 0}
hash2 = {:hour => 0, :minutes => 0}
begin
hash1 = add_hour(hash1)
hash1 = add_delay(first_clock,hash1)
hash2 = add_hour(hash2)
p hash2.to_s
hash2 = add_delay(second_clock,hash2)
p hash2.to_s
end while !compare(hash1,hash2)
#making sure print is good
if hash1[:hour] > 9
if hash1[:minutes] > 9
puts hash1[:hour].to_s + ":" + hash1[:minutes].to_s
else
puts hash1[:hour].to_s + ":0" + hash1[:minutes].to_s
end
else
if hash1[:minutes] > 9
puts "0" + hash1[:hour].to_s + ":" + hash1[:minutes].to_s
else
puts "0" + hash1[:hour].to_s + ":0" + hash1[:minutes].to_s
end
end
#-------------------------------------------------------------------
对于1和31,代码按预期运行。对于任何更大的东西,比如5和100,它似乎进入一个无限循环,我不知道bug在哪里。出了什么问题?
答案 0 :(得分:0)
您的代码
让我们看看您的代码,同时做一些小的改进。
将分钟数转换为小时和分钟,然后将小时数转换为一天内的小时数, add_delay
需要一定的分钟数才能添加到散列中。一个问题是,如果时钟每小时增加超过59分钟,则可能需要将小时数增加一个以上。尝试编写它并add_hours
像这样:
def add_delay(min_to_add, hash)
mins = hash[:minutes] + min_to_add
hrs, mins = mins.divmod 60
hash[:minutes] = mins
add_hours(hash, hrs)
end
def add_hours(hash, hours=1)
hash[:hours] = (hash[:hours] + hours) % 24
end
我们不一定关心这些方法中的任何一个返回,因为它们修改了参数hash
。
这使用非常方便的方法Fixnum#divmod将分钟转换为小时和分钟。
(旁白:一些Rubie不会使用hash
作为变量的名称,因为它也是Ruby方法的名称。)
接下来,compare
确定密钥:hour
和:minutes
的两个哈希是否相等。您可以查看哈希是否相等,而不是检查小时和分钟是否匹配:
def compare(hash1, hash2)
hash1 == hash2
end
获取时钟快速的每小时分钟数:
first_clock = Integer(gets) rescue nil
second_clock = Integer(gets) rescue nil
现在初始化哈希值并逐步进行,直到找到匹配项,然后返回哈希:
def find_matching_time(first_clock, second_clock)
hash1 = {:hours => 0, :minutes => 0}
hash2 = {:hours => 0, :minutes => 0}
begin
add_delay(first_clock, hash1)
add_hours(hash1)
add_delay(second_clock, hash2)
add_hours(hash2)
end until compare(hash1, hash2)
hash1
end
让我们试一试:
find_matching_time(1, 31)
# => {:hours=>0, :minutes=>48}
find_matching_time(5, 100)
#=> {:hours=>0, :minutes=>0}
find_matching_time(5, 5)
#=> {:hours=>1, :minutes=>5}
find_matching_time(0, 59)
#=> {:hours=>0, :minutes=>0}
这些结果与我在下面获得的结果相匹配。您不会返回从现在起的小时数,直到时间相同,但您可能不需要它。
我还没有确定为什么你会得到无限循环,但也许通过这种分析,你将能够找到它。
我建议另外两个小的变化:1)在add_hours
中加入add_delay
并重命名后者,以及2)摆脱compare
,因为它非常简单且仅使用在一个地方:
def add_hour_and_delay(min_to_add, hash)
mins = hash[:minutes] + min_to_add
hrs, mins = mins.divmod 60
hash[:minutes] = mins
hash[:hours] = (hash[:hours] + 1 + hrs) % 24
end
def find_matching_time(first_clock, second_clock)
hash1 = {:hours => 0, :minutes => 0}
hash2 = {:hours => 0, :minutes => 0}
begin
add_hour_and_delay(first_clock, hash1)
add_hour_and_delay(second_clock, hash2)
end until hash1 == hash2
hash1
end
替代方法
这是编写方法的另一种方法。让:
f0
:第一个时钟快速的每小时分钟f1
:第二个时钟快速的每小时分钟然后我们可以计算下次他们将显示如下相同的时间。
<强>代码强>
MINS_PER_DAY = (24*60)
def find_matching_time(f0, f1)
elapsed_hours = (1..Float::INFINITY).find { |i|
(i*(60+f0)) % MINS_PER_DAY == (i*(60+f1)) % MINS_PER_DAY }
[elapsed_hours, "%d:%02d" % ((elapsed_hours*(60+f0)) % MINS_PER_DAY).divmod(60)]
end
<强>实施例强>
find_matching_time(1, 31)
#=> [48, "0:48"]
在48
小时后,两个时钟将显示&#34; 0:48&#34;的时间。
find_matching_time(5, 100)
#=> [288, "0:00"]
find_matching_time(5, 5)
#=> [1, "1:05"]
find_matching_time(0, 59)
#=> [1440, "0:00"]
<强>解释强>
经过i
小时后,两个时钟将分别显示一天内的以下分钟数:
(i*(60+f0)) % MINS_PER_DAY # clock 0
(i*(60+f1)) % MINS_PER_DAY # clock 1
然后使用 Enumerable#find确定这两个值相等时的第一个经过时数i
。我们不知道可能需要多长时间,因此我列举了以1
开头的所有正整数。 (我想它可能不会超过59小时,所以我可以编写(1..n).find..
n
是大于58
的任何整数。)find
返回的值是分配给变量elapsed_hours
。
两个时钟将在elapsed_hours
之后显示相同的时间,因此我们可以计算时钟显示的时间。我已选择为时钟0
执行此操作。对于第一个示例(f0=1
,f1=31
)
elapsed_hours #=> 48
所以
mins_clock0_advances = elapsed_hours*(60+1)
#=> 2928
mins_clock_advances_within_day = mins_clock0_advances % MINS_PER_DAY
#=> 48
然后我们将其转换为小时和分钟:
mins_clock_advances_within_day.divmod(60)
#=> [0, 48]
然后我们可以使用方法String#%来适当地格式化此结果:
"%d:%02d" % mins_clock_advances_within_day.divmod(60)
#=> "0:48"
有关使用%
时格式化的信息,请参阅Kernel#sprintf。在"%02d"
中,d
用于&#34;十进制&#34;,2
是字段宽度,0
表示填充左侧为零。