From: marc spitzer
Subject: A ruby quiz, want to do it in CL?
Date: 
Message-ID: <slrnfhtfcj.lcl.ms4720@sverige.freeshell.org>
this is ruby quiz 144, anybody feel like doing it in CL?

Time Window (#144)

by Brian Candler

Write a Ruby class which can tell you whether the current time (or any
given time) is within a particular "time window". Time windows are
defined by strings in the following format:

ruby
# 0700-0900 # every day between these times
# Sat Sun # all day Sat and Sun, no other times
# Sat Sun 0700-0900 # 0700-0900 on Sat and Sun only
# Mon-Fri 0700-0900 # 0700-0900 on Monday to Friday only
# Mon-Fri 0700-0900; Sat Sun # ditto plus all day Sat and Sun
# Fri-Mon 0700-0900 # 0700-0900 on Fri Sat Sun Mon
# Sat 0700-0800; Sun 0800-0900 # 0700-0800 on Sat, plus 0800-0900 on Sun

Time ranges should exclude the upper bound, i.e. 0700-0900 is 07:00:00
to 08:59:59. An empty time window means "all times everyday". Here are
some test cases to make it clearer:

ruby
class TestTimeWindow < Test::Unit::TestCase
def test_window_1
w = TimeWindow.new("Sat-Sun; Mon Wed 0700-0900; Thu 0700-0900 1000-1200")

assert ! w.include?(Time.mktime(2007,9,25,8,0,0)) # Tue
assert w.include?(Time.mktime(2007,9,26,8,0,0)) # Wed
assert ! w.include?(Time.mktime(2007,9,26,11,0,0))
assert ! w.include?(Time.mktime(2007,9,27,6,59,59)) # Thu
assert w.include?(Time.mktime(2007,9,27,7,0,0))
assert w.include?(Time.mktime(2007,9,27,8,59,59))
assert ! w.include?(Time.mktime(2007,9,27,9,0,0))
assert w.include?(Time.mktime(2007,9,27,11,0,0))
assert w.include?(Time.mktime(2007,9,29,11,0,0)) # Sat
assert w.include?(Time.mktime(2007,9,29,0,0,0))
assert w.include?(Time.mktime(2007,9,29,23,59,59))
end

def test_window_2
w = TimeWindow.new("Fri-Mon")
assert ! w.include?(Time.mktime(2007,9,27)) # Thu
assert w.include?(Time.mktime(2007,9,28))
assert w.include?(Time.mktime(2007,9,29))
assert w.include?(Time.mktime(2007,9,30))
assert w.include?(Time.mktime(2007,10,1))
assert ! w.include?(Time.mktime(2007,10,2)) # Tue
end

def test_window_nil
w = RDS::TimeWindow.new("")
assert w.include?(Time.mktime(2007,9,25,1,2,3)) # all times
end
end

marc

-- 
······@sdf.lonestar.org
SDF Public Access UNIX System - http://sdf.lonestar.org

From: ············@gmail.com
Subject: Re: A ruby quiz, want to do it in CL?
Date: 
Message-ID: <1193352721.876564.5420@o80g2000hse.googlegroups.com>
Ok, I did it.  You can check it out here:

http://www.lispcast.com/index.php/2007/10/time-window-matcher/

I have the code, plus some comments on it.

Eric
http://www.lispcast.com
From: Ken Tilton
Subject: Re: A ruby quiz, want to do it in CL?
Date: 
Message-ID: <rG9Ui.6952$qt4.1629@newsfe12.lga>
············@gmail.com wrote:
> Ok, I did it.  You can check it out here:
> 
> http://www.lispcast.com/index.php/2007/10/time-window-matcher/
> 
> I have the code, plus some comments on it.
> 


You requested feedback. Code looks great. Spotted this:

(some #'identity (mapcar (lambda (tw)
				(includesp tw time))
			      (rest tw))))

I am scratching my head, why not?:

   (some (lambda (tw) (includesp tw time)) (rest tw))

Also saves you from consing up all the results. You did the same later 
with (every 'identity (lambda ....

My next point would be you do not really need the result (which is a 
predicate anyway, not the matched tw) so find-if does as well and does 
not mislead the maintainer into thinking the result matters other than 
being non-nil.

Finally:

  (loop for tw in (rest tw)
        thereis (includesp tw time))

Not so many parentheses. :)

hth,kt

-- 
http://www.theoryyalgebra.com/

"Career highlights? I had two. I got an intentional walk
from Sandy Koufax and I got out of a rundown against the Mets."."
                                                   - Bob Uecker
From: Ken Tilton
Subject: Re: A ruby quiz, want to do it in CL?
Date: 
Message-ID: <mP9Ui.6954$qt4.353@newsfe12.lga>
Ken Tilton wrote:
> 
> 
> ············@gmail.com wrote:
> 
>> Ok, I did it.  You can check it out here:
>>
>> http://www.lispcast.com/index.php/2007/10/time-window-matcher/
>>
>> I have the code, plus some comments on it.
>>
> 
> 
> You requested feedback. Code looks great. Spotted this:

(defun hour-of (time)
   (multiple-value-bind (second minute hour) (decode-universal-time time)
     hour))

That would give me warnings about unused second and minute variables. I 
could declare ignore or:

   (nth-value 2 (decode....))

kt

-- 
http://www.theoryyalgebra.com/

"Career highlights? I had two. I got an intentional walk
from Sandy Koufax and I got out of a rundown against the Mets."."
                                                   - Bob Uecker
From: ············@gmail.com
Subject: Re: A ruby quiz, want to do it in CL?
Date: 
Message-ID: <1193451114.558776.19400@y42g2000hsy.googlegroups.com>
On Oct 24, 5:35 am, marc spitzer <······@sverige.freeshell.org> wrote:
> this is ruby quiz 144, anybody feel like doing it in CL?

Another solution (depends only on split-sequence):

(defvar *weekdays* '(mon tue wed thu fri sat sun))

(defclass time-window ()
  ((weekdays :accessor weekdays :initarg :weekdays)
   (from :accessor from :initarg :from)
   (to :accessor to :initarg :to)))

(defmethod print-object ((window time-window) stream)
  (print-unreadable-object (window stream :type t)
    (with-slots (weekdays from to) window
      (format stream "~A from ~A to ~A" weekdays from to))))

(defmethod includes ((windows list) (time list))
  (includes windows (apply #'encode-universal-time
			   (reverse (subseq (append time '(0 0 0)) 0 6)))))

(defmethod includes ((windows list) (time integer))
  (loop for window in windows when (includes window time) return t))

(defmethod includes ((window time-window) (time integer))
  (flet ((hhmmss-as-seconds (h &optional m s)
	   (+ (* 3600 h) (* 60 (or m 0)) (or s 0))))
    (multiple-value-bind (sec min hour date month year day)
	(decode-universal-time time)
      (declare (ignore date month year))
      (and (member (nth day *weekdays*) (weekdays window))
	   (<= (apply #'hhmmss-as-seconds (from window))
	       (hhmmss-as-seconds hour min sec))
	   (< (hhmmss-as-seconds hour min sec)
	      (apply #'hhmmss-as-seconds (to window)))))))

(defun create-windows (string)
  (loop for def in (split-sequence:split-sequence #\; string)
     append (let (days time-intervals)
	      (loop for item in (split-sequence:split-sequence #\Space def)
		 unless (string= item "")
		 do (ecase (length item)
		      (3 (push (read-from-string item) days))
		      (7 (let ((from-day (position (read-from-string (subseq item 0
3)) *weekdays*))
			       (to-day (position (read-from-string (subseq item 4 7))
*weekdays*)))
			   (when (< to-day from-day) (incf to-day 7))
			   (loop for i from from-day to to-day
			      do (pushnew (nth (mod i 7) *weekdays*) days))))
		      (9 (push item time-intervals))))
	      (loop for time-interval in (or time-intervals '("0000-2400"))
		 collect (make-instance 'time-window :weekdays (or days *weekdays*)
					:from (list (parse-integer (subseq time-interval 0 2))
						    (parse-integer (subseq time-interval 2 4)))
					:to (list (parse-integer (subseq time-interval 5 7))
						  (parse-integer (subseq time-interval 7 9))))))))

(progn
  (let ((windows (create-windows "Sat-Sun; Mon Wed 0700-0900; Thu
0700-0900 1000-1200")))
    (print windows)
    (print (list (not (includes windows '(2007 9 25 8 0 0)))
		 (includes windows '(2007 9 26 8 0 0))
		 (not (includes windows '(2007 9 26 11 0 0)))
		 (not (includes windows '(2007 9 27 6 59 59)))
		 (includes windows '(2007 9 27 7 0 0))
		 (includes windows '(2007 9 27 8 59 59))
		 (not (includes windows '(2007 9 27 9 0 0)))
		 (includes windows '(2007 9 27 11 0 0))
		 (includes windows '(2007 9 29 11 0 0))
		 (includes windows '(2007 9 29 0 0 0))
		 (includes windows '(2007 9 29 23 59 59)))))
  (let ((windows (create-windows "Fri-Mon")))
    (print windows)
    (print (list (not (includes windows '(2007 9 27)))
		 (includes windows '(2007 9 28))
		 (includes windows '(2007 9 29))
		 (includes windows '(2007 9 30))
		 (includes windows '(2007 10 1))
		 (not (includes windows '(2007 10 2))))) )
  (let ((windows (create-windows "")))
    (print windows)
    (print (list (includes windows '(2007 9 25 1 2 3))))))

;; (#<TIME-WINDOW (SUN SAT) from (0) to (24)>
;;  #<TIME-WINDOW (WED MON) from (7 0) to (9 0)>
;;  #<TIME-WINDOW (THU) from (10 0) to (12 0)>
;;  #<TIME-WINDOW (THU) from (7 0) to (9 0)>)
;; (T T T T T T T T T T T)
;; (#<TIME-WINDOW (MON SUN SAT FRI) from (0) to (24)>)
;; (T T T T T T)
;; (#<TIME-WINDOW (MON TUE WED THU FRI SAT SUN) from (0) to (24)>)
;; (T)
From: ············@gmail.com
Subject: Re: A ruby quiz, want to do it in CL?
Date: 
Message-ID: <1193471043.694606.24830@z9g2000hsf.googlegroups.com>
Thanks so much for the informative feedback!

Eric
http://www.lispcast.com