記事の最後に載せたプログラムのコメントにも書きましたが、ポイントは2つあります。
- 基準日の年と生年の差
- 基準日がその年の誕生日よりも前のときは1を減算する
2015/8/31
NARITA Shoさんから「Excel 界隈では「基準日」という語が使われているみたいですね。」とのコメントを頂きました。ありがとうございました。
以下、xyzzy lispとC#での実装を記載します。
2015/9/2
C#での実装例を追加しました。
(defun backet-sort (v backet-count)
"バケツソート"
(let ((backet (array-to-backet v backet-count)))
(backet-to-array backet (length v))))
(defun array-to-backet (arr backet-count)
"配列からバケツを構成する"
(let ((backet (make-array backet-count :initial-element 0)))
(dotimes (i (length arr) backet)
(let ((n (aref arr i)))
(setf (aref backet n) (1+ (aref backet n)))))))
(defun backet-to-array (backet array-length)
"バケツからソート済みの配列を構成する"
(let ((arr (make-array array-length)))
(loop with arr-index = 0
for i below (length backet)
when (< 0 (aref backet i))
do (loop repeat (aref backet i)
do (setf (aref arr arr-index) i)
(setq arr-index (1+ arr-index))))
arr))
(defun main ()
"動作確認のための関数"
(let ((l (loop with state = (make-random-state t)
repeat 10
collect (random 10 state))))
(print (sort (make-array (length l) :initial-contents l) #'<))
(print (backet-sort (make-array (length l) :initial-contents l) 10))))
(main)
[Section1] Key1=Value1 Key2=Value2 [Section2] Key1=Value1 [Section3]
;; inifile.l
(defun read-lines (input)
(loop as line = (read-line input nil nil)
while line
collect line))
(defun sectionp (line)
(and (stringp line)
(<= 2 (length line))
(eq #\[ (char line 0))
(eq #\] (char line (1- (length line))))))
(defun keyvaluep (line)
(and (stringp line)
(<= 3 (length line))
(find #\= line)
(< 0 (position #\= line))))
(defun strip-section (line)
(if (not (sectionp line))
line
(subseq line 1 (1- (length line)))))
(defun split-keyvalue (line)
(if (not (keyvaluep line))
line
(list (subseq line 0 (position #\= line))
(subseq line (1+ (position #\= line))))))
(defun convert-to-alist (alist line)
(cond ((sectionp line)
(cons (list (strip-section line)) alist))
((keyvaluep line)
(cons (append (car alist) (list (split-keyvalue line))) (cdr alist)))
(t alist)))
(defun ini-assoc (section key alist)
(car (last
(assoc key
(cdr (assoc section alist :test 'string-equal))
:test 'string-equal))))
;; 以下実行部
(setf ini-alist (reduce 'convert-to-alist (read-lines *standard-input*)
:initial-value '()))
(format t "~A~%" ini-alist)
(format t "~A ~A = ~A~%" "Section2" "Key1"
(ini-assoc "Section2" "Key1" ini-alist))
(format t "~A ~A = ~A~%" "SECTION1" "KEY2"
(ini-assoc "SECTION1" "KEY2" ini-alist))
$ cat sample.ini | clisp inifile.l ((Section3) (Section2 (Key1 Value1)) (Section1 (Key1 Value1) (Key2 Value2))) Section2 Key1 = Value1 SECTION1 KEY2 = Value2
; convert-xml
(defparameter *conversion-alist*
'((#\< . "<")
(#\> . ">")
(#\& . "&")
(#\" . """)
(#\' . "'")))
(defun convert-xml ()
(interactive "*")
(let ((input-buffer (window-buffer (selected-window))))
(with-output-to-temp-buffer ("*Converted*")
(with-open-stream (s (make-buffer-stream input-buffer))
(loop
(let ((c (read-char s nil)))
(if c (format t "~A" (convert-char c *conversion-alist*))
(return nil))))))))
(defun convert-char (c alist)
(let ((conversion (assoc c alist)))
(if conversion (cdr conversion)
c)))