Shammer's Philosophy

My private adversaria

16進数を10進数に戻す関数・改

16進数を10進数に戻す関数 - Shammerismで、16進数の文字列表記を10進の数字にするものを作成したが、少し手を加えて数のリストとcharacterのリストにも対応させることにする。

リスト内の要素が全て同一タイプかを判定する関数

たとえば、(0 1 2 3) や (#\a #\a #\a) のようなものを判定したい。

(defun typelistp (l type)
  (if (null l)
      t
    (and (typep (car l) type) (typelistp (cdr l) type))))

これはこんな風に使える。

? (typelistp '(0 1 2 3) 'number)
T
? (typelistp '(0 1 2 "aaa") 'number)
NIL
? (typelistp '(#\a #\a #\a) 'character)
T
? (typelistp '(#\a #\a "a") 'character)
NIL
? 

hex2dec拡張

16進数を10進数に戻す関数 - Shammerismのバージョンではstringpのみの判定だったが、上記を使って以下のように変更。

(defun hex2dec (x)
  (labels ((typelistp (l type)
		      (if (null l)
			  t
			(and (typep (car l) type) (typelistp (cdr l) type)))))
    (let ((result 0) (base 1))
      (cond ((stringp x)
	     (dolist (c (reverse (coerce x 'list)))
	       (cond ((char-equal c #\A)
		      (setf result (+ result (* base 10))))
		     ((char-equal c #\B)
		      (setf result (+ result (* base 11))))
		     ((char-equal c #\C)
		      (setf result (+ result (* base 12))))
		     ((char-equal c #\D)
		      (setf result (+ result (* base 13))))
		     ((char-equal c #\E)
		      (setf result (+ result (* base 14))))
		     ((char-equal c #\F)
		      (setf result (+ result (* base 15))))
		     (t
		      (setf result (+ result (* base (parse-integer (string c)))))))
	       (setf base (* base 16))))
	    ((typelistp x 'number)
	     (dolist (c (reverse x))
	       (setf result (+ result (* base c)))
	       (setf base (* base 16))))
	    ((typelistp x 'character)
	     (setf result (hex2dec (coerce x 'string))))
	    (t
	     (setf result x)))
      result)))

char-equal を使えば、大文字小文字関係なく比較してくれるのでこれを使うことにした。実行結果は以下。

? (hex2dec '(1 2 3 4))
4660
? (format nil "~d" #x1234)
"4660"
? (hex2dec '(#\a #\b))
171
? (format nil "~d" #xab)
"171"
?