Рассчитать будний день с дата (м-Д-Г)


Это общее упражнение на Lisp написать программу, которая может вычислить день недели с учетом строку формата "м-д-и." было более сложным, чем я ожидал. Если у вас есть предложения о том, как упростить этот код, я буду очень благодарна.

;;  2.7 Day of Week. A program for converting Gregorian dates in the form month-day-year to day of the
;;  week is the following. Let the Gregorian date be represented by M-D-Y where we have the following
;;  definitions:
;;    M is the month of the year. Let m be the month number derived from M by the rule m is M - 2 if M >= 3
;;    and m is M + 10 otherwise.
;;    d is the day of the month.
;;    y is the year of the century.
;;    c is the number of the previous century.
;;  The algorithm is as follows:
;;    (a) A is the integer part of (13m - 1)/5.
;;    (b) B is the integer parg of y/4.
;;    (c) C is the integer part of c/4.
;;    (d) D = A + B + C + d + y - 2c.
;;    (e) Make R equal to the remainder of D/7.
;;    (f ) Interpret R as Sunday if R = 0, Monday if R is 1, etc

(defun read-date () (format t "Enter the gregorian date in the format (M-D-Y): ~%") (read))


(defun flatten (the-list) 
  (cond ((null the-list) nil)
    ((atom the-list) (list the-list))
    (t (concatenate 'list (flatten (car the-list)) (flatten (cdr the-list))))))

(defun split (split-char string-to-split) 
  (let ((next-split-char (position split-char string-to-split)))
    (if next-split-char (flatten (list (safely-read-from-string (subseq string-to-split 0 next-split-char))
                  (split split-char (subseq string-to-split (+ 1 next-split-char)))))
      (list (safely-read-from-string string-to-split)))))

(defun weekday-code (bigM bigD bigY)
    (let* ((m (if (>= bigM 3) (- bigM 2) (+ bigM 10)))
          (y (mod bigY 100))
          (littleC (/ (- bigY y) 100))
          (A (floor (- (* 13 m) 1) 5))
          (B (floor y 4))
          (C (floor littleC 4))
          (D (- (+ A B C bigD y) (* 2 littleC)))
          (R (mod D 7)))
      (format t "m: ~a y: ~a c: ~a A: ~a B: ~a C: ~a D: ~a R: ~a ~%" m y littleC A B C D R)
      R))

(defun check-date-format (bigM bigD bigY)
  (cond ((or (< bigM 1) (> bigM 12)) (error "The month (~a) is not in the range 1-12." bigM))
    ((< bigY 0) (error "The year (~a) is less than 0." bigY))
    ((or (< bigD 1) (> bigD 31)) (error "The day (~a) is not in the range 1-31." bigD))))

(let ((gregorian-date (read-date)))
      (destructuring-bind (bigM bigD bigY) (split #\- gregorian-date)
    (check-date-format bigM bigD bigY)
    (format t "~a was (or will be) a ~[Sunday~;Monday~;Tuesday~;Wednesday~;Thursday~;Friday~;Saturday~]." gregorian-date (weekday-code bigM bigD bigY))))


756
5
задан 9 марта 2011 в 06:03 Источник Поделиться
Комментарии
2 ответа

Как правило, вы должны почти никогда не нужно использовать придавить функцию. Например, функция Split:

(defun split (split-char string-to-split) 
(let ((next-split-char (position split-char string-to-split)))
(if next-split-char (flatten (list (safely-read-from-string (subseq string-to-split 0 next-split-char))
(split split-char (subseq string-to-split (+ 1 next-split-char)))))
(list (safely-read-from-string string-to-split)))))

эквивалентно:

(defun split (split-char string-to-split) 
(let ((next-split-char (position split-char string-to-split)))
(if next-split-char
(cons (safely-read-from-string (subseq string-to-split 0 next-split-char))
(split split-char (subseq string-to-split (1+ next-split-char))))
(list (safely-read-from-string string-to-split)))))

Это безопасно для чтения из строки предполагает возврат такой же, как функция чтения. Функция расплющить Helper не нужен.

3
ответ дан 9 марта 2011 в 12:03 Источник Поделиться

Если вы разрешили использовать функции библиотеки, раскол уже существует в рамках модели CL-ppcre.


Есть довольно богатый набор функциями даты/времени в Lisp ядра, что делает это тривиальной. Если это в учебных целях, всеми средствами, идти вперед и делать это вручную. Но если вы думаете: "какой самый лучший способ получить день недели в Лиспе?", что на самом деле до смешного просто.

(defun day-of-week (day month year)
(nth-value 6 (decode-universal-time (encode-universal-time 0 0 0 day month year 0))))

Re-организовать порядок argumnents по вкусу. С понедельника по умолчанию-0, поэтому вы должны были бы повторно джиг ваш формат директивы. Если вы должны быть в состоянии обрабатывать даты до 1900 года, есть более надежные версии в общий Лисп кулинарную книгу.

3
ответ дан 9 марта 2011 в 12:03 Источник Поделиться