Renages

All,

I have a requirement to translate a time between 0000 and 2359 in to a
single character ‘interval ID’ based on the time. For example, if the
time is between 0000 and 0059, ‘0’ should be returned, if it’s between
0100 and 0159, ‘1’ should be return. The problem is that 0700-0729
should return ‘A’, 0730-0759 should return ‘B’, i.e. it’s not a simple
mapping.

I have the following, but I can’t help thinking there’s a much more
efficient way of doing it - can anyone advise, as I’m a little stuck!

xlate = [ [ ‘0000’, ‘0059’, ‘0’ ], [ ‘0100’, ‘0159’, ‘1’ ],
[ ‘0200’, ‘0259’, ‘2’ ], [ ‘0300’, ‘0359’, ‘3’ ],
[ ‘0400’, ‘0459’, ‘4’ ], [ ‘0500’, ‘0559’, ‘5’ ],
[ ‘0600’, ‘0659’, ‘6’ ], [ ‘0700’, ‘0729’, ‘A’ ],
[ ‘0730’, ‘0759’, ‘B’ ], [ ‘0800’, ‘0829’, ‘C’ ],
[ ‘0830’, ‘0859’, ‘D’ ], [ ‘0900’, ‘0929’, ‘E’ ],
[ ‘0930’, ‘0959’, ‘F’ ], [ ‘1000’, ‘1029’, ‘G’ ],
[ ‘1030’, ‘1059’, ‘H’ ], [ ‘1100’, ‘1129’, ‘I’ ],
[ ‘1130’, ‘1159’, ‘J’ ], [ ‘1200’, ‘1229’, ‘K’ ],
[ ‘1230’, ‘1259’, ‘L’ ], [ ‘1300’, ‘1329’, ‘M’ ],
[ ‘1330’, ‘1359’, ‘N’ ], [ ‘1400’, ‘1429’, ‘O’ ],
[ ‘1430’, ‘1459’, ‘P’ ], [ ‘1500’, ‘1529’, ‘Q’ ],
[ ‘1530’, ‘1559’, ‘R’ ], [ ‘1600’, ‘1629’, ‘S’ ],
[ ‘1630’, ‘1659’, ‘T’ ], [ ‘1700’, ‘1729’, ‘U’ ],
[ ‘1730’, ‘1759’, ‘V’ ], [ ‘1800’, ‘1829’, ‘W’ ],
[ ‘1830’, ‘1859’, ‘X’ ], [ ‘1900’, ‘1959’, ‘Y’ ],
[ ‘2000’, ‘2059’, ‘Z’ ], [ ‘2100’, ‘2159’, ‘7’ ],
[ ‘2200’, ‘2259’, ‘8’ ], [ ‘2300’, ‘2359’, ‘9’ ] ]

xlate.each do |range|
return range[2] if time >= range[0] && time <= range[1]
end

…and I have no idea how ‘Renages’ ended up in the subject!

On Sun, Jul 03, 2011 at 05:40:42AM +0900, Peter H. wrote:

…and I have no idea how ‘Renages’ ended up in the subject!

I figured it was a weird typo for “ranges”.

On Jul 2, 2011, at 13:37 , Peter H. wrote:

I have a requirement to translate a time between 0000 and 2359 in to a
single character ‘interval ID’ based on the time. For example, if the
time is between 0000 and 0059, ‘0’ should be returned, if it’s between
0100 and 0159, ‘1’ should be return. The problem is that 0700-0729
should return ‘A’, 0730-0759 should return ‘B’, i.e. it’s not a simple
mapping.

It is very much a simple mapping, it just isn’t a 1:1 mapping anymore.
All you need to do is figure out which hour and half hour of the day it
is, and return the code for that.

Given a time t, t.min / 30 gives you 0 or 1 based on which half hour
you’re in. t.hour gives you 0 to 23 based on which hour you’re in. So:

t.hour * 2 + (t.hour / 30)

Gives you a number from 0 to 47. From there you can either look it up
from a pre-populated array or hash or whatever…

xlate = “00112233445566ABCDEFGHIJKLMNOPQRSTUVWXYZ778899”.split(//)

t = Time.now
p [t.hour, t.min] # => [14, 10]
p xlate[t.hour * 2 + (t.hour / 30)] # => “O”

On Sun, 2011-07-03 at 06:12 +0900, Ryan D. wrote:

It is very much a simple mapping, it just isn’t a 1:1 mapping anymore. All you
need to do is figure out which hour and half hour of the day it is, and return the
code for that.

John, Ryan, thank you so much - a brilliantly simple and minimal idea
that I didn’t even think of.

Peter

Afternoon,

On Sat, Jul 2, 2011 at 1:37 PM, Peter H. [email protected]
wrote:

efficient way of doing it - can anyone advise, as I’m a little stuck!
[ ‘1230’, ‘1259’, ‘L’ ], [ ‘1300’, ‘1329’, ‘M’ ],
return range[2] if time >= range[0] && time <= range[1]
end

How about this

#Setup a string with all 48 options (splitting into half hours)
results = “00112233445566ABCDEFGHIJKLMNOPQRSTUVWXYYZZ778899”

#Convert our time into which of the 48 half hour slots it fits
time = ‘1734’
slot = (time[0…1].to_i * 60 + time[2…3].to_i) / 30 #> 35

#Return the result for the slot
results[slot] #> V

John

On Sun, Jul 3, 2011 at 11:21 AM, Peter H. [email protected]
wrote:

On Sun, 2011-07-03 at 06:12 +0900, Ryan D. wrote:

It is very much a simple mapping, it just isn’t a 1:1 mapping anymore. All you
need to do is figure out which hour and half hour of the day it is, and return the
code for that.

John, Ryan, thank you so much - a brilliantly simple and minimal idea
that I didn’t even think of.

You just need to be aware that the approach works only as long as the
shortest interval length is 30 minutes AND all interval endpoints are
aligned with this interval length. If you need to be able to easily
change any of those intervals in between you need to change the whole
logic.

As worst case fallback you could assume minimal resolution 1 minute
and use your original input to generate an String of length 1440 (= 24

  • 60, minutes per day) from it for efficient lookup. Then you have
    xlate[t.hour * 60 + t.min].

Kind regards

robert

On Jul 2, 2011, at 4:37 PM, Peter H. wrote:

efficient way of doing it - can anyone advise, as I’m a little stuck!
[ ‘1230’, ‘1259’, ‘L’ ], [ ‘1300’, ‘1329’, ‘M’ ],
return range[2] if time >= range[0] && time <= range[1]
end


Peter H. [email protected]

You just need to check from the “end” on back and pick the first one
that matches.

xlate = [ [ ‘0000’, ‘0’ ], [ ‘0100’, ‘1’ ], [ ‘0200’, ‘2’ ],
[ ‘0300’, ‘3’ ],
[ ‘0400’, ‘4’ ], [ ‘0500’, ‘5’ ], [ ‘0600’, ‘6’ ],
[ ‘0700’, ‘A’ ],
[ ‘0730’, ‘B’ ], [ ‘0800’, ‘C’ ], [ ‘0830’, ‘D’ ],
[ ‘0900’, ‘E’ ],
[ ‘0930’, ‘F’ ], [ ‘1000’, ‘G’ ], [ ‘1030’, ‘H’ ],
[ ‘1100’, ‘I’ ],
[ ‘1130’, ‘J’ ], [ ‘1200’, ‘K’ ], [ ‘1230’, ‘L’ ],
[ ‘1300’, ‘M’ ],
[ ‘1330’, ‘N’ ], [ ‘1400’, ‘O’ ], [ ‘1430’, ‘P’ ],
[ ‘1500’, ‘Q’ ],
[ ‘1530’, ‘R’ ], [ ‘1600’, ‘S’ ], [ ‘1630’, ‘T’ ],
[ ‘1700’, ‘U’ ],
[ ‘1730’, ‘V’ ], [ ‘1800’, ‘W’ ], [ ‘1830’, ‘X’ ],
[ ‘1900’, ‘Y’ ],
[ ‘2000’, ‘Z’ ], [ ‘2100’, ‘7’ ], [ ‘2200’, ‘8’ ],
[ ‘2300’, ‘9’ ],
].reverse

Note the .reverse here

time = Time.now.strftime(‘%H%M’)
xlate.detect{|(start,code)| time >= start}

Then you can vary the start times and not be concerned about the
“breaks” in the mapping or whether there is a 30-minute boundary. (And
not build an 60x24 entry string or array of minutes even though that
might be more efficient depending on how many lookups you need to do.)

-Rob

Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/

On Jul 5, 2011, at 10:34 , Rob B. wrote:

      [ '2000', 'Z' ], [ '2100', '7' ], [ '2200', '8' ], [ '2300', '9' ],
      ].reverse

Note the .reverse here

time = Time.now.strftime(’%H%M’)
xlate.detect{|(start,code)| time >= start}

simple benchmark:

real math 1.180000 0.000000 1.180000 ( 1.193925)
table lookup 13.460000 0.040000 13.500000 ( 14.111571)