# A Solution to the Five Weekends Problem in Common Lisp

I’ve been enjoying playing around with Rosetta Code problems lately. Here’s a solution I posted last week for the Five Weekends problem in Common Lisp:

```  ;;; http://rosettacode.org/wiki/Five_weekends

;; Given a date, get the day of the week.  Adapted from
;; http://lispcookbook.github.io/cl-cookbook/dates_and_times.html

(defun day-of-week (day month year)
(nth-value
6
(decode-universal-time
(encode-universal-time 0 0 0 day month year 0)
0)))

(defparameter *long-months* '(1 3 5 7 8 10 12))

(defun sundayp (day month year)
(= (day-of-week day month year) 6))

(defun ends-on-sunday-p (month year)
(sundayp 31 month year))

;; We use the "long month that ends on Sunday" rule.
(defun has-five-weekends-p (month year)
(and (member month *long-months*)
(ends-on-sunday-p month year)))

;; For the extra credit problem.
(defun has-at-least-one-five-weekend-month-p (year)
(let ((flag nil))
(loop for month in *long-months* do
(if (has-five-weekends-p month year)
(setf flag t)))
flag))

(defun solve-it ()
(let ((good-months '())
(loop for year from 1900 to 2100 do
;; First form in the PROGN is for the extra credit.
(progn (unless (has-at-least-one-five-weekend-month-p year)
(loop for month in *long-months* do
(when (has-five-weekends-p month year)
(push (list month year) good-months)))))
(let ((len (length good-months)))
(format t "~A months have five weekends.~%" len)
(format t "First 5 months: ~A~%" (subseq good-months (- len 5) len))
(format t "Last 5 months: ~A~%" (subseq good-months 0 5))
(format t "Years without a five-weekend month: ~A~%" bad-years))))
```