Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
427 Newsletter

Friday the 13ths

For some reason, when the 13th day of the month is a Friday, we consider that unlucky. Because it's such a popular superstition (and even those who don't believe in it enjoy the fun), we're making a website for it. Our job is to write some backed routines that the frontend team will add to pages.

Write the following:

  • A function that tells you the next upcoming Friday the 13th.
  • A function that tells you all the Friday the 13ths in a given year.
  • A predicate that tells you if a given year + month had a Friday the 13th.
  • A predicate to know if a given date (year, month, day) is a Friday the 13th.
  • A function that when the next upcoming Friday the 13th falls in a given month.

If you're working in JVM Clojure, use the Java 8 java.time package.

Thanks to this site for the problem idea, where it is rated Hard in Ruby. The problem has been modified.

Please submit your solutions as comments on this gist.

To subscribe:

Copy link

steffan-westcott commented May 17, 2021

(import (java.time LocalDate DayOfWeek))

(defn- friday? [d]
  (= DayOfWeek/FRIDAY (.getDayOfWeek d)))

(defn- friday-13ths-from [d]
  (let [this-13th (.withDayOfMonth d 13)
        start (if (.isBefore this-13th d) (.plusMonths this-13th 1) this-13th)]
    (filter friday? (iterate #(.plusMonths % 1) start))))

(defn next-friday-13th []
  (first (friday-13ths-from (LocalDate/now))))

(defn friday-13ths-in-year [y]
  (take-while #(= y (.getYear %)) (friday-13ths-from (LocalDate/of y 1 1))))

(defn month-has-friday-13th? [y m]
  (friday? (LocalDate/of y m 13)))

(defn friday-13th? [d]
  (and (friday? d) (= 13 (.getDayOfMonth d))))

(defn next-friday-13th-with-month [m]
  (first (filter #(= m (.getMonthValue %)) (friday-13ths-from (LocalDate/now)))))

Copy link

heyarne commented May 17, 2021

(ns friday-13th
  (:import [java.time LocalDate DayOfWeek]
           [java.time.temporal ChronoUnit]))

(defn friday-13th?
  ([year month day]
   (friday-13th? (LocalDate/of year month day)))
  ([year month]
   (friday-13th? (LocalDate/of year month 13)))
   (and (= 13 (.getDayOfMonth date))
        (= DayOfWeek/FRIDAY (.getDayOfWeek date)))))

(defn- advance-to-next-13th [date]
  (.. date
      (plus 1 ChronoUnit/MONTHS)
      (withDayOfMonth 13)))

(defn next-friday-13th [start]
  (->> (iterate advance-to-next-13th start)
       (filter friday-13th?)

(defn friday-13ths-in-year [year]
  (->> (LocalDate/of year 1 13)
       (iterate advance-to-next-13th)
       (take 12)
       (filter friday-13th?)))

(defn next-friday-13th-with-month [month]
  (->> (LocalDate/now)
       (iterate advance-to-next-13th)
       (filter friday-13th?)
       (filter #(= month (.getMonthValue %)))

Copy link

mchampine commented May 17, 2021

(ns challenges.fridaythirteenth
  (:require [java-time :as jt]))

;; utils
(def dfmt (partial jt/format "MM/dd/yyyy"))
(defn is13th? [d] (= 13 (jt/as d :day-of-month)))
(defn f13? [d] (and (is13th? d) (jt/friday? d)))
(defn month-iter [y m d] (jt/iterate jt/plus (jt/local-date y m d) (jt/months 1)))
(defn cur-ymd [] (jt/as (jt/local-date) :year :month-of-year :day-of-month))

(defn thirteensseq []
  (let [[y m d] (cur-ymd)]
    (month-iter y (if (< d 13) m (inc m)) 13)))

(defn nextf13 [] (dfmt (first (filter f13? (thirteensseq)))))

(defn f13s-by-year [y]
  (map dfmt (filter jt/friday? (take 12 (month-iter y 1 13)))))

(defn hasf13-y-m? [y m] (f13? (jt/local-date y m 13)))
(defn is-f13-ymd? [y m d] (f13? (jt/local-date y m d)))

(defn nextf13-m [m]
  (let [f13m? (fn [d] (and (jt/friday? d) (= m (jt/as d :month-of-year))))]
    (dfmt (first (filter f13m? (thirteensseq))))))

Copy link

(ns friday13.core
  (:require [java-time :as jt]))

(defn- calendar 
   (->> (range)
        (map (fn [d] (jt/plus from-date (jt/days d))))))
  ([from-date to-date]
   (->> (calendar from-date)
        (take-while (fn [d] (jt/before? d (jt/plus to-date (jt/days 1))))))))

(defn friday13? 
  ([y m d] (friday13? (jt/local-date y m d)))
   (let [[dom dow] (jt/as date :day-of-month :day-of-week)]
     (and (= 13 dom) (= 5 dow)))))

(defn next-friday13 []
  (->> (calendar (jt/local-date))
       (drop-while (complement friday13?))

(defn friday13s-in-year [y]
  (let [first-day (jt/local-date y 1 1)
        last-day (jt/local-date y 12 31)]
    (->> (calendar first-day last-day)
         (filter friday13?))))

(defn friday13-in-year-month? [y m]
  (let [first-day (jt/local-date y m 1)
        last-day (jt/adjust (jt/local-date y m 1) :last-day-of-month)]
    (->> (calendar first-day last-day)
         (some friday13?)

(defn next-friday13-in-month? [m]
  (= m (jt/as (next-friday13) :month-of-year)))

Copy link

(defn get-day [year month day] 
        (let [d (.parse (java.text.SimpleDateFormat. "yyyy-MM-dd") (format "%s-%s-%s" year month day))]
             (.getDay d)))

(defn is-friday-the-thirteenth [year month day]
    (and (= day 13) (= (get-day year month day) 5)))

(defn get-friday-the-thirteenths
    ([year month] (if (is-friday-the-thirteenth year month 13) [year month 13] nil))
    ([year] (remove nil? (map #(get-friday-the-thirteenths year %) (range 1 13)))))

(defn has-friday-the-thirteenths
    ([year month] (not (nil? (get-friday-the-thirteenths year month))))
    ([year] (not (empty? (get-friday-the-thirteenths year)))))

(defn next-friday-the-thirteenths
    ([year] (apply concat (map #(get-friday-the-thirteenths %) (iterate inc year))))
    ([year month day] (drop-while (fn [[y m d]] (and (<= y year) (<= m month) (<= d day))) (next-friday-the-thirteenths year)))
    ([year month] (next-friday-the-thirteenths year month 1)))

(defn next-friday-the-thirteenth
    ([year] (first (next-friday-the-thirteenths year)))
    ([year month] (first (next-friday-the-thirteenths year month)))
    ([year month day] (first (next-friday-the-thirteenths year month day))))

Copy link

sztamas commented May 20, 2021

(ns eric-normand-newsletter-challenges.friday-13
  (:import [java.time DayOfWeek LocalDate]))

(defn friday? [y m d]
  (= DayOfWeek/FRIDAY (.getDayOfWeek (LocalDate/of y m d))))

(defn friday-the-13th?
  ([^LocalDate d]
   (friday-the-13th? (.getYear d) (.getMonthValue d) (.getDayOfMonth d)))
  ([y m d]
   (and (= d 13) (friday? y m d))))

(defn has-friday-the-13th? [y m]
  (friday-the-13th? y m 13))

(defn future-friday-the-13ths
  ([] (future-friday-the-13ths (LocalDate/now)))
   (let [first-f13 (.withDayOfMonth start-date 13)]
     (->> (range)
          (map #(.plusMonths first-f13 %))
          (drop-while #(.isBefore % start-date))
          (filter friday-the-13th?)))))

(def next-friday-the-13th (comp str first future-friday-the-13ths))

(defn all-friday-the-13ths [y]
  (->> (LocalDate/of y 1 1)
       (take-while #(= y (.getYear %)))
       (map str)))

  (friday? 2021 8 7) ;; => false
  (friday? 2021 8 6) ;; => true

  (friday-the-13th? 2021 7 13) ;; => false
  (friday-the-13th? 2021 8 13) ;; => true

  (has-friday-the-13th? 2021 7) ;; => false
  (has-friday-the-13th? 2021 8) ;; => true

  (all-friday-the-13ths 2020) ;; => ("2020-03-13" "2020-11-13")
  (all-friday-the-13ths 2021) ;; => ("2021-08-13")

  (take 5 (map str (future-friday-the-13ths)))
  ;; => ("2021-08-13" "2022-05-13" "2023-01-13" "2023-10-13" "2024-09-13")
  (take 5 (map str (future-friday-the-13ths (LocalDate/of 2000 1 1))))
  ;; => ("2000-10-13" "2001-04-13" "2001-07-13" "2002-09-13" "2002-12-13")

  (next-friday-the-13th) ;; => "2021-08-13"
  (next-friday-the-13th (LocalDate/of 2021 8 14)) ;; => "2022-05-13"


Copy link

KingCode commented May 22, 2021

;; utilities, with JVM's java.time interop at the bottom
(defn new-date 
  ([y m d]
   (java.time.LocalDate/of y m d)))

(defn now []

(def Friday java.time.DayOfWeek/FRIDAY)

(defn year-of [^java.time.LocalDate ld]
  (.getYear ld))

(defn month-of [^java.time.LocalDate ld]
  (.getMonthValue ld))

(defn days-in-month [^java.time.LocalDate ld]
  (.lengthOfMonth ld))

(defn day-of [^java.time.LocalDate ld]
  (.getDayOfMonth ld))

(defn as-day-13th [^java.time.LocalDate ld]
  (.withDayOfMonth ld 13))

(defn weekday-of [^java.time.LocalDate ld]
  (.getDayOfWeek ld))

(defn n-months-after [^long n ^java.time.LocalDate ld]
  (.plusMonths ld n))

(defn n-days-after [^long n ^java.time.LocalDate ld]
  (.plusDays ld n))

(defn n-years-after [^long n ^java.time.LocalDate ld]
  (.plusYears ld n))

(defn inc-year [ld]
  (n-years-after 1 ld))

(defn inc-month [ld]
  (n-months-after 1 ld))

(defn inc-day [ld]
  (n-days-after 1 ld))

(defn ->ymd [ld]
  (-> ld ((juxt year-of month-of day-of))))

(defn friday? [ld]
  (= Friday (weekday-of ld)))

(defn the-13th? [ld]
  (= 13 (day-of ld)))

(defn forward-units [from to period]
  (let [diff (- to from)]
    (if (<= 0 diff)
      (-> period (- from) (+ to)))))

(defn forward-to [to ld period rdr forwardr]
  (let [now (or ld (now))
        from (rdr now)
        dist (forward-units from to period)]
    (forwardr dist now)))

(defn next-date-having-month [m]
  (forward-to m nil 12 month-of n-months-after ))

(defn next-date-having-day13 [from-ld]
  (forward-to 13 from-ld (days-in-month from-ld) day-of n-days-after))

;;; user functions 
(defn friday-the-13th? 
  "A predicate to know if a given date (year, month, day) is a Friday the 13th."
  ([y m d]
   (friday-the-13th? (new-date y m d)))
   (and (the-13th? ld) (friday? ld))))

(defn next-friday-the-13th 
  "A function that tells you the next upcoming Friday the 13th."
   (next-friday-the-13th (now)))
   (->> ld next-date-having-day13
        (iterate inc-month)
        (filter friday?) first

(defn friday-the-13ths-for-year 
"A function that tells you all the Friday the 13ths in a given year."
  (->> (range 1 13)
       (map #(new-date yr % 13))
       (filter friday?)
       (map ->ymd)))

(defn next-friday-the-13th-having-month
"A function that when the next upcoming Friday the 13th falls in a given month."
  (->> m next-date-having-month as-day-13th
       (iterate inc-year)
       (some (fn [ld]
                 (when (friday? ld)

(->ymd (now))  
;;=> [2021 5 22]
;;=> [2021 8 13]
(friday-the-13ths-for-year 2020)
;;=> ([2020 3 13] [2020 11 13])
(next-friday-the-13th-having-month 1) ;; when is the next Friday-13th in January?
;;=> [2023 1 13]

;; Trivia time: 
;; - What is the most frightening count of f-13ths in any Gregorian calendar year so far?
;; - How many years have had it? 
;; - Which are the earliest/latest years?
;; - Which are the N most recent scariest years and their distribution of fright? 
(defn scariest-years-trivia [n-most-recent]
  (let [[scary-count scary-years]
        (->> (range 1582 2022)
             (map friday-the-13ths-for-year)
             (reduce (fn [[max-count f13-yrs] f13yr]
                       (if (<= max-count (count f13yr))
                         [(count f13yr), (conj f13-yrs f13yr)]
                         [max-count f13-yrs]))
                     [0 ()]))]
    (->> scary-years
         (filter #(= scary-count (count %)))
         (take n-most-recent)
         (sorted-map :1_How-many-scariest-years-so-far? 
                     (count scary-years)
                     (->> [(last scary-years), (first scary-years)]
                          (mapv ffirst))
                     (keyword :4_Which-are-the-friday13ths-of-the-most-recent-scariest-years?))))) 

(scariest-years-trivia 2)
;; {:1_How-many-scariest-years-so-far? 67,
;;; :2_What-is-the-max-count-of-scary-fridays-in-any-year? 3,
;;; :3_What-are-the-earliest-and-latest-scariest-years? [1582 2015],
;;; :4_Which-are-the-friday13ths-of-the-most-recent-scariest-years?
;;; (([2015 2 13] [2015 3 13] [2015 11 13])
;;;; ([2012 1 13] [2012 4 13] [2012 7 13]))}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment