How to resolve the algorithm Calendar step by step in the Clojure programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Calendar step by step in the Clojure programming language

Table of Contents

Problem Statement

Create a routine that will generate a text calendar for any year.
Test the calendar by generating a calendar for the year 1969, on a device of the time. Choose one of the following devices:

(Ideally, the program will generate well-formatted calendars for any page width from 20 characters up.) Kudos (κῦδος) for routines that also transition from Julian to Gregorian calendar. This task is inspired by Real Programmers Don't Use PASCAL by Ed Post, Datamation, volume 29 number 7, July 1983. For further Kudos see task CALENDAR, where all code is to be in UPPERCASE. For economy of size, do not actually include Snoopy generation in either the code or the output, instead just output a place-holder.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Calendar step by step in the Clojure programming language

Source code in the clojure programming language

(require '[clojure.string :only [join] :refer [join]])

(def day-row "Su Mo Tu We Th Fr Sa")

(def col-width (count day-row))

(defn month-to-word 
  "Translate a month from 0 to 11 into its word representation."
  [month]
  ((vec (.getMonths (new java.text.DateFormatSymbols))) month))

(defn month [date]
  (.get date (java.util.Calendar/MONTH))) 

(defn total-days-in-month [date]
  (.getActualMaximum date (java.util.Calendar/DAY_OF_MONTH)))

(defn first-weekday [date]
  (.get date (java.util.Calendar/DAY_OF_WEEK)))
         
(defn normal-date-string
  "Returns a formatted list of strings of the days of the month."
  [date]		 
  (map #(join " " %)
    (partition 7
      (concat
        (repeat (dec (first-weekday date)) "  ")
        (map #(format "%2s" %)
               (range 1 (inc (total-days-in-month date))))
        (repeat (- 42 (total-days-in-month date)
                      (dec (first-weekday date)) ) "  ")))))
         
		 
(defn oct-1582-string
  "Returns a formatted list of strings of the days of the month of October 1582."
  [date]
  (map #(join " " %)
    (partition 7
      (concat
         (repeat (dec (first-weekday date)) "  ")
         (map #(format "%2s" %)
                 (concat (range 1 5) 
                         (range 15 (inc (total-days-in-month date)))))
         (repeat (- 42 
                    (count (concat (range 1 5) 
		                   (range 15
                                          (inc (total-days-in-month date)))))
                    (dec (first-weekday date)) ) "  ")))))


(defn center-string 
  "Returns a string that is WIDTH long with STRING centered in it."
  [string width]
  (let [pad (- width (count string))
        lpad (quot pad 2) 
        rpad (- pad (quot pad 2))]
    (if (<= pad 0)
    string
    (str (apply str (repeat lpad " "))  ; remove vector
          string 
         (apply str (repeat rpad " "))))))


(defn calc-columns 
  "Calculates the number of columns given the width in CHARACTERS and the 
   MARGIN SIZE."
  [characters margin-size]
  (loop [cols 0 excess  characters ]
    (if (>= excess  col-width)
        (recur (inc cols) (- excess (+ margin-size col-width)))
         cols)))

(defn month-vector 
  "Returns a vector with the month name, day-row and days
   formatted for printing."
  [date]
  (vec (concat 
         (vector (center-string (month-to-word (month date)) col-width))
         (vector day-row)
 		 (if (and (= 1582 (.get date (java.util.Calendar/YEAR)))
		 		  (= 9 (month date)))
		     (oct-1582-string date)
                     (normal-date-string date)))))

(defn year-vector [date]
  "Returns a 2d vector of all the months in the year of DATE."
  (loop [m [] c (month date)]
    (if (= c 11 )
        (conj m (month-vector date)) 
        (recur (conj m (month-vector date))
               (do (.add date (java.util.Calendar/MONTH ) 1)
                   (month date))))))

(defn print-months
  "Prints the months to standard output with NCOLS and MARGIN."
  [ v ncols margin]
  (doseq [r (range (Math/ceil (/ 12 ncols)))]
    (do (doseq [i (range 8)]
          (do (doseq [c (range (* r ncols) (* (+ r 1) ncols))
		                :while (< c 12)]
              (printf (str (apply str (repeat margin " ")) "%s")
		      (get-in v [c i])))
          (println)))
        (println))))

(defn print-cal
  "(print-cal [year [width [margin]]])
   Prints out the calendar for a given YEAR with WIDTH characters wide and
   with MARGIN spaces between months."
  ([] 
     (print-cal 1969 80 2))
  ([year] 
     (print-cal year 80 2))
  ([year width]
   (print-cal year width 2))
  ([year width margin]
     (assert (>= width (count day-row)) "Width should be more than 20.")
     (assert (> margin 0) "Margin needs to be more than 0.")
     (let [date (new java.util.GregorianCalendar year 0 1)
           column-count (calc-columns width margin)
           total-size (+ (* column-count (count day-row))
                         (* (dec column-count) margin))]
       (println (center-string "[Snoopy Picture]" total-size))
       (println (center-string (str year) total-size))
       (println)
       (print-months (year-vector date) column-count margin))))


  

You may also check:How to resolve the algorithm Minimal steps down to 1 step by step in the C# programming language
You may also check:How to resolve the algorithm Anagrams step by step in the Lua programming language
You may also check:How to resolve the algorithm Cyclotomic polynomial step by step in the Sidef programming language
You may also check:How to resolve the algorithm Rep-string step by step in the REXX programming language
You may also check:How to resolve the algorithm URL decoding step by step in the Oberon-2 programming language