트랙
/
Common Lisp
Common Lisp
/
연습 문제
/
기가초 기념일
기가초 기념일

기가초 기념일

학습 연습 문제

소개

날짜와 시간

Common Lisp에서 시간은 네 가지 방식으로 표현되는데, 여기서는 그중 두 가지를 살펴봐요.

  • 범용 시간은 절대 시간으로, 1900-01-01T00:00:00Z(UTC 기준 1900년 1월 1일 자정) 이후 지난 초의 개수를 나타내는 정수예요.
  • 디코드된 시간은 9개의 값으로 이루어진 튜플인데, 이 값들이 모여 특정 달력 시간을 나타내요: 초, 분, 시, 월 중 일, 월, 연도, 요일, 서머타임 플래그, 시간대. (아래에서 자세히 다뤄요.)

범용 시간

현재 범용 시간을 구하려면 get-universal-time이나 get-decoded-time을 사용해요. 전자는 1900-01-01T00:00Z 이후 지난 현재 초를 반환하고, 후자는 같은 데이터를 디코드된 형식으로 반환해요.

디코드된 시간

decode-universal-time과 encode-universal-time은 시간을 다루는 기본 함수예요. 전자는 범용 시간을 받아 다중 값으로 디코드된 시간 값을 반환하고, 후자는 디코드된 시간 값들을 인자로 받아 범용 시간을 반환해요.

두 함수 모두 선택적인 시간대 인자를 받아요. 시간대의 형식은 아래에서 살펴봐요.

디코드된 시간은 다음과 같은 값들의 모음이에요:

  • 초: 0에서 59 사이의 정수
  • 분: 0에서 59 사이의 정수
  • 시: 0에서 23 사이의 정수
  • 월 중 일: 1에서 31 사이의 정수(물론 상한은 월과 연도에 따라 달라져요)
  • 월: 1에서 12 사이의 정수
  • 연도: 연도를 나타내는 정수.
  • 요일: 0에서 6 사이의 정수. 0은 월요일, 1은 화요일 등을 뜻하고, 6은 일요일을 뜻해요.
  • 서머타임 플래그: 참 값이면 서머타임이 적용 중이라는 뜻이에요.
  • 시간대: UTC와의 차이를 나타내는 -24에서 24 사이의 시간 수예요. 이 수는 유리수이며 1/3600의 배수여야 해요.
(encode-universal-time 1 2 3 4 5 2000 0) ; => 3166398121
(decode-universal-time 3166398121)       ; => 1
                                         ;    2
                                         ;    3
                                         ;    4
                                         ;    5
                                         ;    2000
                                         ;    3 (Thursday)
                                         ;    NIL
                                         ;    0
(decode-universal-time 2208988800) ; => 0
                                   ;    0
                                   ;    0
                                   ;    1
                                   ;    1
                                   ;    1970
                                   ;    3
                                   ;    NIL
                                   ;    0

다중 값

Common Lisp에서 함수는 값을 하나만 반환하는 게 아니라 여러 개를 반환할 수도 있어요. 예를 들어 0을 향해 내림하는 floor는 두 개의 값을 반환하는데, 첫 번째는 내림한 값이고 두 번째는 나머지예요.

(floor 3.5) ; => 3
            ;    0.5

(여러 값을 반환하는 경우에는 결과를 여러 줄에 나눠서 표시해요.)

여러 값 반환하기

함수가 여러 값을 반환하게 하려면 values 접근자를 사용해요:

(defun three-numbers () (values 1 2 3))
(three-numbers) ; => 1
                ;    2
                ;    3

여러 값 다루기

첫 번째 값만 필요하다면 특별히 할 일은 없어요. 언어가 알아서 처리해 줘요:

(+ (values 1 2 3) (values 10 20 30)) ; => 11

하지만 나머지 값들에도 접근하고 싶다면 몇 가지 함수를 사용해야 해요. 주요 매크로 두 가지는 multiple-value-list와 multiple-value-bind예요. 이 둘은 여러 값을 반환하는 것을 감싸서 모든 값을 잡아내는 데 사용해요. 첫 번째는 모든 값의 배열을 만들고, 두 번째는 개별 값에 변수를 바인딩할 수 있게 해줘요.

(multiple-value-list (values 1 2 3))                   ; => (1 2 3)
(multiple-value-bind (a b c) (values 1 2 3) 
   (+ a b c)) ; => 6

또 다른 유용한 함수는 nth-value예요

지침

Lisp 외계인들은 기념일을 축하하는 걸 좋아해요. 그들에게 중요한 기념일은 바로 기가세컨드예요. 즉, 어떤 사건이 일어난 지 1,000,000,000초가 지난 시점이죠.

1. 기가세컨드 기념일 날짜 계산하기

from이라는 함수를 작성해요. 이 함수는 year, month, day, hour, min, sec 여섯 개의 매개변수를 받아 기가세컨드 기념일의 날짜와 시간을 계산해요. 이 함수는 입력 매개변수와 같은 순서와 의미를 가진 배열로 날짜를 반환해야 해요.

(from 2000 1 1 0 0 0) ; => (2031 9 9 1 46 40)
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Common Lisp Exercism

기가초 기념일 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Common Lisp 트랙을 개념 27개연습 문제 92개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.