Shammer's Philosophy

My private adversaria

16進数を10進数に戻す関数-20130202

16進数を10進数に戻す関数・改 - Shammerismの内容で終わりにしようかと思ったが、使用すべき文字はわかっているしdolistを止めたいとか、改善したいと思ったので書き換えた。

(defun hex2decimal (x)
  (labels ((is-hexable (l)
	     (let ((available-chars '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\A #\B #\C #\D #\E #\F #\a #\b #\c #\d #\e #\f)))
	       (if (consp l)
		   (and (is-hexable (car l)) (is-hexable (cdr l)))
		   (cond ((null l) t)
			 ((characterp l)
			  (member l available-chars))
			 ((numberp l)
			  (is-hexable (write-to-string l)))
			 ((stringp l)
			  (if (eql 1 (length l))
			      (member (character l) available-chars)
			      (is-hexable (coerce l 'list))))
			 ((arrayp l)
			  (is-hexable (coerce l 'list)))
			 (t nil)))))
	   (replace-hex-value (n)
	     (cond ((and (stringp n) (equal 1 (length n)))
		    (replace-hex-value (character n)))
		   ((characterp n)
		    (cond ((char-equal n #\A) 10)
			  ((char-equal n #\B) 11)
			  ((char-equal n #\C) 12)
			  ((char-equal n #\D) 13)
			  ((char-equal n #\E) 14)
			  ((char-equal n #\F) 15)
			  (t (if (and (<= 0 (parse-integer (string n)))
				      (<= (parse-integer (string n)) 9))
				 (parse-integer (string n))
				 0))))
		   ((numberp n)
		    (if (and (<= 0 n) (<= n 9))
			n
			0))
		   (t 0)))
	   (calc (n base)
	     (if (null n)
		 0
		 (+ (* base (replace-hex-value (car n)))
		    (calc (cdr n) (* base 16))))))
    (when (is-hexable x)
      (cond ((or (stringp x) (arrayp x))
	     (calc (reverse (coerce x 'list)) 1))
	    ((listp x)
	     (calc (reverse x) 1))
	    ((characterp x)
	     (replace-hex-value x))
	    (t
	     (hex2decimal (write-to-string x)))))))

簡単な実行結果は以下。渡された値は16進数とみなして計算する。

? (hex2decimal 99)
153
? (hex2decimal "fe")
254
? (hex2decimal '("f" "e"))
254
? (hex2decimal #("f" "e"))
254
? (hex2decimal "fs")
NIL
?