どう書く?org ;コインを減らす払い方 を commonlispで その2
コインを減らす払い方。できたつもり。
ずいぶん書き直したなぁ。これであってんのかなぁ。
まぁいいか。
;;コインを減らす払い方 c (defmacro make-coins(yen1 yen5 yen10 yen50 yen100 yen500) `'((1 ,yen1) (5 ,yen5) (10 ,yen10) (50 ,yen50) (100 ,yen100) (500 ,yen500))) (defun copy-coins(coins) `((1 ,(get-count coins 0)) (5 ,(get-count coins 1)) (10 ,(get-count coins 2)) (50 ,(get-count coins 3)) (100 ,(get-count coins 4)) (500 ,(get-count coins 5)))) (defmacro get-val (coins n) `(car (nth ,n ,coins))) (defmacro get-count (coins n) `(cadr (nth ,n ,coins))) (defun update-coins(coins n plus) (let ((c (copy-coins coins))) (setf (get-count c n) (+ (get-count c n) plus)) c)) (defun setvalue-coins(coins n val) (let ((c (copy-coins coins))) (setf (get-count c n) val) c)) (defun sum(coins) (let ((result 0)) (dolist (coin coins result) (setf result (+ result (* (car coin) (cadr coin))))))) (defun sum2(coins n) (let ((result 0)) (dotimes (var (1+ n) result) (setf result (+ result (* (get-val coins var) (get-count coins var))))))) (defun convert-coins(kingaku) (let ((nokori kingaku)) (reverse (mapcar #'(lambda (kin) (multiple-value-bind (su amari) (truncate nokori kin) (setf nokori (- nokori (* su kin))) (list kin su))) '(500 100 50 10 5 1))))) (defun get-upkingaku(kingaku n) (let ((coins (convert-coins kingaku))) (dotimes (var (1+ n)) (setf coins (setvalue-coins coins var 0))) (update-coins coins (1+ n) 1))) (defun get-remainder(x y) (multiple-value-bind (a remainder) (truncate x y) remainder)) (defun subtract-coin(coins n count) (if (= n 0) (subtract-1yen coins count) (let ((result coins) (val (get-val coins n)) (val-1 (get-val coins (1- n)))) (dotimes (var count result) (let ((sum (sum2 result (1- n)))) (if (< sum val) (setf result (update-coins result n -1)) (setf result (subtract-coin result (1- n) (/ val val-1))))))))) (defun subtract-1yen(coins count) (update-coins coins 0 (* -1 count))) (defun get-payment(coins kingaku) (if (< (sum coins) kingaku) nil (progn (let ((c coins) (shiharai kingaku) (val-lst '(1 5 10 50 100 500 1000))) (dotimes (var 6 c) (let* ((remainder (get-remainder shiharai (nth (1+ var) val-lst))) (maisu (get-count c var))) (cond ((= remainder 0)) ((< (* maisu (nth var val-lst)) remainder) (setf shiharai (sum (get-upkingaku shiharai var)))) (t (progn (setf shiharai (- shiharai remainder)) (setf c (subtract-coin c var (/ remainder (nth var val-lst))))))))))))) (defun pay(coins kingaku) (if (< (sum coins) kingaku) nil (let ((payment (get-payment coins kingaku))) `((1 ,(- (get-count coins 0) (get-count payment 0))) (5 ,(- (get-count coins 1) (get-count payment 1))) (10 ,(- (get-count coins 2) (get-count payment 2))) (50 ,(- (get-count coins 3) (get-count payment 3))) (100 ,(- (get-count coins 4) (get-count payment 4))) (500 ,(- (get-count coins 5) (get-count payment 5)))))))