Algorithm to calculate the target-year of the targ

2019-08-31 03:21发布

问题:

GOAL:  The goal of this thread is to create a mathematical formula to replace the long-hand solution by @lawlist in the function lawlist-target-year-function (below).

NOTE:  The solution to this thread is somewhat similar, but will nevertheless be different, than the algorithm written by @AShelly in a related thread: https://stackoverflow.com/a/21709710/2112489

                                                                      STORY PROBLEM

There now exists a 12-month calendar in Emacs that scrolls forwards and backwards one month (or more) at a time. A helper function called lawlist-target-year-function is used by sevaral holiday functions to place an overlay on each holiday.

A full working draft of the 12-month scrolling calendar (including the long-hand solution) may be found here -- [the Github source code has been revised to include the concise algorithm solution by @legoscia]:

             https://github.com/lawlist/calendar-yearly-scroll-by-month/blob/master/lawlist-cal.el

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 contains the holiday that will be marked with an overlay. There are three (3) possible x axis coordinates (i.e., column 1, column 2, or column 3). There are four (4) possible y axis coordinates (i.e., row 1, row 2, row 3, or row 4). [Citation to x / y coordinates: http://www.mathsisfun.com/data/cartesian-coordinates.html ]

The displayed-year is the year 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 year is the year of the target-month.

EXAMPLE:

  • When displayed-month is January (i.e., 1), then the year is the same for all target months.

  • When displayed-month is February (i.e., 2):

    (if (memq target-month `(2 3 4 5 6 7 8 9 10 11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is March (i.e., 3):

    (if (memq target-month `(3 4 5 6 7 8 9 10 11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is April (i.e., 4):

    (if (memq target-month `(4 5 6 7 8 9 10 11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is May (i.e., 5)

    (if (memq target-month `(5 6 7 8 9 10 11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is June (i.e., 6):

    (if (memq target-month `(6 7 8 9 10 11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is July (i.e., 7):

    (if (memq target-month `(7 8 9 10 11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is August (i.e, 8):

    (if (memq target-month `(8 9 10 11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is September (i.e., 9):

    (if (memq target-month `(9 10 11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is October (i.e., 10):

    (if (memq target-month `(10 11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is November (i.e., 11):

    (if (memq target-month `(11 12))
      displayed-year
      (+ displayed-year 1))
    
  • When displayed-month is December (i.e., 12):

    (if (memq target-month `(12))
      displayed-year
      (+ displayed-year 1))
    

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-target-year-function (target-month)
  (cond
    ;;  1 2 3
    ;;  4 5 6
    ;;  7 8 9
    ;;  10 11 12
    ((eq displayed-month 1)
      displayed-year)
    ;;  2 3 4
    ;;  5 6 7
    ;;  8 9 10
    ;;  11 12 1
    ((eq displayed-month 2)
      (if (memq target-month `(2 3 4 5 6 7 8 9 10 11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  3 4 5
    ;;  6 7 8
    ;;  9 10 11
    ;;  12 1 2
    ((eq displayed-month 3)
      (if (memq target-month `(3 4 5 6 7 8 9 10 11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  4 5 6
    ;;  7 8 9
    ;;  10 11 12
    ;;  1 2 3
    ((eq displayed-month 4)
      (if (memq target-month `(4 5 6 7 8 9 10 11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  5 6 7
    ;;  8 9 10
    ;;  11 12 1
    ;;  2 3 4
    ((eq displayed-month 5)
      (if (memq target-month `(5 6 7 8 9 10 11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  6 7 8
    ;;  9 10 11
    ;;  12 1 2
    ;;  3 4 5
    ((eq displayed-month 6)
      (if (memq target-month `(6 7 8 9 10 11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  7 8 9
    ;;  10 11 12
    ;;  1 2 3
    ;;  4 5 6
    ((eq displayed-month 7)
      (if (memq target-month `(7 8 9 10 11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  8 9 10
    ;;  11 12 1
    ;;  2 3 4
    ;;  5 6 7
    ((eq displayed-month 8)
      (if (memq target-month `(8 9 10 11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  9 10 11
    ;;  12 1 2
    ;;  3 4 5
    ;;  6 7 8
    ((eq displayed-month 9)
      (if (memq target-month `(9 10 11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  10 11 12
    ;;  1 2 3
    ;;  4 5 6
    ;;  7 8 9
    ((eq displayed-month 10)
      (if (memq target-month `(10 11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  11 12 1
    ;;  2 3 4
    ;;  5 6 7
    ;;  8 9 10
    ((eq displayed-month 11)
      (if (memq target-month `(11 12))
        displayed-year
        (+ displayed-year 1)))
    ;;  12 1 2
    ;;  3 4 5
    ;;  6 7 8
    ;;  9 10 11
    ((eq displayed-month 12)
      (if (memq target-month `(12))
        displayed-year
        (+ displayed-year 1))) ))

回答1:

Would this work?

(defun lawlist-target-year-function (target-month)
  (if (>= target-month displayed-month)
      displayed-year
    (1+ displayed-year)))


标签: emacs elisp