5

I am learning Clojure, and I need a push in the right direction with this problem I came up with.

I have a sequence of events. Each event includes a 'date'.

(def events
  [
   [1509 :marry   "Catherine of Aragon"]
   [1527 :unmarry "Catherine of Aragon"]
   [1533 :marry   "Anne Boleyn"]
   [1536 :unmarry "Anne Boleyn"]
   [1536 :marry   "Jane Seymour"]
   [1537 :unmarry "Jane Seymour"]
   [1540 :marry   "Anne of Cleves"]
   [1540 :unmarry "Anne of Cleves"]
   [1540 :marry   "Catherine Howard"]
   [1542 :unmarry "Catherine Howard"]
   [1543 :marry   "Catherine Parr"]])

I want to convert this into a lazy timeline, i.e. a sequence containing one vector per year. Starting with the year of the first event, and continuing to infinity.

[[[:marry "Catherine of Aragon"]] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [[:unmarry "Catherine of Aragon"]] [] [] [] [] [] [[:marry "Ane Boleyn"]] [] [] [[:unmarry "Anne Boleyn"] [:marry "Jayne Seymour"]] ...]
1

2 Answers 2

8
(def timeline
  (let [events-by-year (group-by first events)]
    (map #(map next (events-by-year %))
      (iterate inc (reduce min (keys events-by-year))))))

Quick test:

=> (take 30 timeline)
(((:marry "Catherine of Aragon")) () () () () () () () () () () () () () () () ()
 () ((:unmarry "Catherine of Aragon")) () () () () () ((:marry "Anne Boleyn")) ()
 () ((:unmarry "Anne Boleyn") (:marry "Jane Seymour")) ((:unmarry "Jane Seymour"))
 ())
Sign up to request clarification or add additional context in comments.

Comments

3

I would suggest something like:

(defn timeline
  ([] (timeline (ffirst *events*) *events*))
  ([time evts]
     (let [[now later] (split-with #(= time (first %)) evts)]
       (cons (map rest now)
             (lazy-seq (timeline (inc time) later))))))

Test:

user> (take 30 (timeline))
(((:marry "Catherine of Aragon")) () () () () () () () () () () () () () () () () () 
 ((:unmarry "Catherine of Aragon")) () () () () () ((:marry "Anne Boleyn")) () () 
 ((:unmarry "Anne Boleyn") (:marry "Jane Seymour")) ((:unmarry "Jane Seymour")) ()) 

I'm assuming that the list of events is infinite as well :)

Updated with improvements, and borrowing a couple of ideas from cgrand (thanks :)

2 Comments

Thanks. It breaks when there are more than one event on the same date i.e. [1515 :c] [1515 :d]. However, there are a lot of good pointers in there, so maybe I can figure the rest out myself.
@GHZ Ah, missed that. Well, cgrand's was nicer anyway :) Refactored, leaving as a second option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.