Algorithms for moving the cursor to a date on a 12 month rotating calendar in Emacs

elisp, emacs

Solution

I must be missing something because it looks like the formulas are as simple as (pseudocode):

first  = 9 * ( rows - 1 ) 
second = 6 + 25 * ( cols - 1 )

based on your edit, you can calculate the rows and cols to move with:

if target > display
   difference = target - display
else 
   difference = 12 + target - display
 rows = difference / 3 
 cols = difference % 3
 rowmove = 9 * rows 
 colmove = 6 + 25 * cols

And then use the formula above.

My attempt at elisp:

(let difference (if (>= target-month display-month) 
                      (- target-month display-month) 
                    (- (+ target-month 12) display-month)))
(let rows (/ difference 3))
(let cols (% difference 3))
(let rowmove (* 9 rows))   
(let colmove (+ 6 (* 25 cols)))

Problem

GOAL: The goal of this thread is to create two (2) mathematical formulas to replace the long-hand solution by @lawlist in the function `lawlist-calendar-cursor-to-visible-date` (below). STORY PROBLEM There now exists a 12-month calendar in Emacs that scrolls forwards and backwards one month (or more) at a time. The function `lawlist-calendar-cursor-to-visible-date` is used to mark dates with overlays for designated events (e.g., birthdays, holidays, appointments, etc.); or, to simply move the cursor to a particular date. @lawlist has devised a solution by long-hand, which does not entirely use mathematical equations to calculate the cursor position for each of the 365 days that are displayed. It may be possible to create two (2) concise algorithms to replace the long-hand solution. A working draft of the 12-month scrolling calendar (without the long-hand solution) may be found here: https://stackoverflow.com/a/21409154/2112489 LEGEND: `displayed-month` (numbers 1 through 12) is the month that appears in the upper left-hand corner of the buffer, and this changes as the 12-month calendar is scrolled forwards or backwards. The target `month` (numbers 1 through 12) is the month that we need to locate with assistance from the two mathematical formulas -- its location varies depending upon the date being marked (e.g., birthday, holiday, appointment), and depending upon the `displayed-month` in the upper left-hand corner of the buffer. The target `month` can be in any one of 12 possible positions. There are three (3) possible `x` axis coordinates (i.e., 6, 31, or 56). There are four (4) possible `y` axis coordinates (i.e., 0, 9, 18 or 27). [Citation to x / y coordinates: http://www.mathsisfun.com/data/cartesian-coordinates.html ] A `row` is defined as 3 months horizontally. A `column` is defined as 4 months vertically. The first forumula must equal 0, 9, 18 or 27 depending upon whether the point is on `row` 1, 2, 3 or 4 -- i.e., from top to bottom. The second forumula must equal 6, 31, or 56 depending upon whether the point is on `column` 1, 2 or 3 -- i.e., from left to right. EXAMPLE: If `displayed-month` is January (i.e., 1) and the target `month` is August (i.e., 8), then `row` equals 18 and `column` equals 31. If `displayed-month` is February (i.e., 2) and the target `month` is August (i.e., 8), then `row` equals 18 and `column` equals 6. If `displayed-month` is March (i.e., 3) and the target `month` is August (i.e., 8), then `row` equals 9 and `column` equals 56. If `displayed-month` is April (i.e., 4) and target `month` is August (i.e., 8), then `row` equals 9 and `column` equals 31. If `displayed-month` is May (i.e., 5) and the target `month` is August (i.e., 8), then `row` equals 9 and `column` equals 6. The 12-month calendar looks like the following as the layout scrolls forward one month at a time: ``` ;; 1 2 3 ;; 4 5 6 ;; 7 8 9 ;; 10 11 12 ;; 2 3 4 ;; 5 6 7 ;; 8 9 10 ;; 11 12 1 ;; 3 4 5 ;; 6 7 8 ;; 9 10 11 ;; 12 1 2 ;; 4 5 6 ;; 7 8 9 ;; 10 11 12 ;; 1 2 3 ;; 5 6 7 ;; 8 9 10 ;; 11 12 1 ;; 2 3 4 ;; 6 7 8 ;; 9 10 11 ;; 12 1 2 ;; 3 4 5 ;; 7 8 9 ;; 10 11 12 ;; 1 2 3 ;; 4 5 6 ;; 8 9 10 ;; 11 12 1 ;; 2 3 4 ;; 5 6 7 ;; 9 10 11 ;; 12 1 2 ;; 3 4 5 ;; 6 7 8 ;; 10 11 12 ;; 1 2 3 ;; 4 5 6 ;; 7 8 9 ;; 11 12 1 ;; 2 3 4 ;; 5 6 7 ;; 8 9 10 ;; 12 1 2 ;; 3 4 5 ;; 6 7 8 ;; 9 10 11 ``` The long-hand solution by @lawlist is as follows: ``` (defun lawlist-calendar-cursor-to-visible-date (date) "Move the cursor to DATE that is on the screen." (let* ( (month (calendar-extract-month date)) (day (calendar-extract-day date)) (year (calendar-extract-year date)) (first-of-month-weekday (calendar-day-of-week (list month 1 year)))) (goto-line (+ 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (cond ;; 1 2 3 ;; 4 5 6 ;; 7 8 9 ;; 10 11 12 ((and (eq displayed-month 1) (memq month `(1 2 3))) 0) ((and (eq displayed-month 1) (memq month `(4 5 6))) 9) ((and (eq displayed-month 1) (memq month `(7 8 9))) 18) ((and (eq displayed-month 1) (memq month `(10 11 12))) 27) ;; 2 3 4 ;; 5 6 7 ;; 8 9 10 ;; 11 12 1 ((and (eq displayed-month 2) (memq month `(2 3 4))) 0) ((and (eq displayed-month 2) (memq month `(5 6 7))) 9) ((and (eq displayed-month 2) (memq month `(8 9 10))) 18) ((and (eq displayed-month 2) (memq month `(11 12 1))) 27) ;; 3 4 5 ;; 6 7 8 ;; 9 10 11 ;; 12 1 2 ((and (eq displayed-month 3) (memq month `(3 4 5))) 0) ((and (eq displayed-month 3) (memq month `(6 7 8))) 9) ((and (eq displayed-month 3) (memq month `(9 10 11))) 18) ((and (eq displayed-month 3) (memq month `(12 1 2))) 27) ;; 4 5 6 ;; 7 8 9 ;; 10 11 12 ;; 1 2 3 ((and (eq displayed-month 4) (memq month `(4 5 6))) 0) ((and (eq displayed-month 4) (memq month `(7 8 9))) 9) ((and (eq displayed-month 4) (memq month `(10 11 12))) 18) ((and (eq displayed-month 4) (memq month `(1 2 3))) 27) ;; 5 6 7 ;; 8 9 10 ;; 11 12 1 ;; 2 3 4 ((and (eq displayed-month 5) (memq month `(5 6 7))) 0) ((and (eq displayed-month 5) (memq month `(8 9 10))) 9) ((and (eq displayed-month 5) (memq month `(11 12 1))) 18) ((and (eq displayed-month 5) (memq month `(2 3 4))) 27) ;; 6 7 8 ;; 9 10 11 ;; 12 1 2 ;; 3 4 5 ((and (eq displayed-month 6) (memq month `(6 7 8))) 0) ((and (eq displayed-month 6) (memq month `(9 10 11))) 9) ((and (eq displayed-month 6) (memq month `(12 1 2))) 18) ((and (eq displayed-month 6) (memq month `(3 4 5))) 27) ;; 7 8 9 ;; 10 11 12 ;; 1 2 3 ;; 4 5 6 ((and (eq displayed-month 7) (memq month `(7 8 9))) 0) ((and (eq displayed-month 7) (memq month `(10 11 12))) 9) ((and (eq displayed-month 7) (memq month `(1 2 3))) 18) ((and (eq displayed-month 7) (memq month `(4 5 6))) 27) ;; 8 9 10 ;; 11 12 1 ;; 2 3 4 ;; 5 6 7 ((and (eq displayed-month 8) (memq month `(8 9 10))) 0) ((and (eq displayed-month 8) (memq month `(11 12 1))) 9) ((and (eq displayed-month 8) (memq month `(2 3 4))) 18) ((and (eq displayed-month 8) (memq month `(5 6 7))) 27) ;; 9 10 11 ;; 12 1 2 ;; 3 4 5 ;; 6 7 8 ((and (eq displayed-month 9) (memq month `(9 10 11))) 0) ((and (eq displayed-month 9) (memq month `(12 1 2))) 9) ((and (eq displayed-month 9) (memq month `(3 4 5))) 18) ((and (eq displayed-month 9) (memq month `(6 7 8))) 27) ;; 10 11 12 ;; 1 2 3 ;; 4 5 6 ;; 7 8 9 ((and (eq displayed-month 10) (memq month `(10 11 12))) 0) ((and (eq displayed-month 10) (memq month `(1 2 3))) 9) ((and (eq displayed-month 10) (memq month `(4 5 6))) 18) ((and (eq displayed-month 10) (memq month `(7 8 9))) 27) ;; 11 12 1 ;; 2 3 4 ;; 5 6 7 ;; 8 9 10 ((and (eq displayed-month 11) (memq month `(11 12 1))) 0) ((and (eq displayed-month 11) (memq month `(2 3 4))) 9) ((and (eq displayed-month 11) (memq month `(5 6 7))) 18) ((and (eq displayed-month 11) (memq month `(8 9 10))) 27) ;; 12 1 2 ;; 3 4 5 ;; 6 7 8 ;; 9 10 11 ((and (eq displayed-month 12) (memq month `(12 1 2))) 0) ((and (eq displayed-month 12) (memq month `(3 4 5))) 9) ((and (eq displayed-month 12) (memq month `(6 7 8))) 18) ((and (eq displayed-month 12) (memq month `(9 10 11))) 27) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (/ (+ day -1 (mod (- (calendar-day-of-week (list month 1 year)) calendar-week-start-day) 7)) 7))) (move-to-column (+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (cond ;; 1 2 3 ;; 4 5 6 ;; 7 8 9 ;; 10 11 12 ((and (eq displayed-month 1) (memq month `(1 4 7 10))) 6) ((and (eq displayed-month 1) (memq month `(2 5 8 11))) 31) ((and (eq displayed-month 1) (memq month `(3 6 9 12))) 56) ;; 2 3 4 ;; 5 6 7 ;; 8 9 10 ;; 11 12 1 ((and (eq displayed-month 2) (memq month `(2 5 8 11))) 6) ((and (eq displayed-month 2) (memq month `(3 6 9 12))) 31) ((and (eq displayed-month 2) (memq month `(4 7 10 1))) 56) ;; 3 4 5 ;; 6 7 8 ;; 9 10 11 ;; 12 1 2 ((and (eq displayed-month 3) (memq month `(3 6 9 12))) 6) ((and (eq displayed-month 3) (memq month `(4 7 10 1))) 31) ((and (eq displayed-month 3) (memq month `(5 8 11 2))) 56) ;; 4 5 6 ;; 7 8 9 ;; 10 11 12 ;; 1 2 3 ((and (eq displayed-month 4) (memq month `(4 7 10 1))) 6) ((and (eq displayed-month 4) (memq month `(5 8 11 2))) 31) ((and (eq displayed-month 4) (memq month `(6 9 12 3))) 56) ;; 5 6 7 ;; 8 9 10 ;; 11 12 1 ;; 2 3 4 ((and (eq displayed-month 5) (memq month `(5 8 11 2))) 6) ((and (eq displayed-month 5) (memq month `(6 9 12 3))) 31) ((and (eq displayed-month 5) (memq month `(7 10 1 4))) 56) ;; 6 7 8 ;; 9 10 11 ;; 12 1 2 ;; 3 4 5 ((and (eq displayed-month 6) (memq month `(6 9 12 3))) 6) ((and (eq displayed-month 6) (memq month `(7 10 1 4))) 31) ((and (eq displayed-month 6) (memq month `(8 11 2 5))) 56) ;; 7 8 9 ;; 10 11 12 ;; 1 2 3 ;; 4 5 6 ((and (eq displayed-month 7) (memq month `(7 10 1 4))) 6) ((and (eq displayed-month 7) (memq month `(8 11 2 5))) 31) ((and (eq displayed-month 7) (memq month `(9 12 3 6))) 56) ;; 8 9 10 ;; 11 12 1 ;; 2 3 4 ;; 5 6 7 ((and (eq displayed-month 8) (memq month `(8 11 2 5))) 6) ((and (eq displayed-month 8) (memq month `(9 12 3 6))) 31) ((and (eq displayed-month 8) (memq month `(10 1 4 7))) 56) ;; 9 10 11 ;; 12 1 2 ;; 3 4 5 ;; 6 7 8 ((and (eq displayed-month 9) (memq month `(9 12 3 6))) 6) ((and (eq displayed-month 9) (memq month `(10 1 4 7))) 31) ((and (eq displayed-month 9) (memq month `(11 2 5 8))) 56) ;; 10 11 12 ;; 1 2 3 ;; 4 5 6 ;; 7 8 9 ((and (eq displayed-month 10) (memq month `(10 1 4 7))) 6) ((and (eq displayed-month 10) (memq month `(11 2 5 8))) 31) ((and (eq displayed-month 10) (memq month `(12 3 6 9))) 56) ;; 11 12 1 ;; 2 3 4 ;; 5 6 7 ;; 8 9 10 ((and (eq displayed-month 11) (memq month `(11 2 5 8))) 6) ((and (eq displayed-month 11) (memq month `(12 3 6 9))) 31) ((and (eq displayed-month 11) (memq month `(1 4 7 10))) 56) ;; 12 1 2 ;; 3 4 5 ;; 6 7 8 ;; 9 10 11 ((and (eq displayed-month 12) (memq month `(12 3 6 9))) 6) ((and (eq displayed-month 12) (memq month `(1 4 7 10))) 31) ((and (eq displayed-month 12) (memq month `(2 5 8 11))) 56) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (* 3 (mod (- (calendar-day-of-week date) calendar-week-start-day) 7)))))) ```

Original source

Related problems