基数変換
逆転したビット列です。
2進数にしてreverseして10進数に戻しています。
import Data.Char import Numeric main = do print $ rbits 4 print $ rbits 5 rbits :: Int -> [Int] rbits n = map (\m -> readBin $ reverse $ padding0 n (toBin m)) $ take (2 ^ n) [0..] toBin :: Int -> String toBin n = showIntAtBase 2 intToDigit n "" padding0 :: Int -> String -> String padding0 n xs = replicate (n - length xs) '0' ++ xs readBin :: String -> Int readBin = fst.head.(readInt 2 (`elem` "10") digitToInt)
用意されている基数変換の関数を使ってみました。まずは2進数への変換。なのですが2進数へ変換する関数がなかったのでまずは16進数へ変換する関数から出発。
Prelude> Numeric.showHex 100 "(16)" "64(16)"
showHexがどうなっているかを見てみるとこうなっていました。
showHex = showIntAtBase 16 intToDigit
これを基に2進数への変換関数を作成。
Prelude> (Numeric.showIntAtBase 2 Data.Char.intToDigit) 100 "(2)" "1100100(2)"
今度は2進数から10進数に変換する関数です。こちらも2進数から変換するものがなかったので16進数からスタート。
Prelude> Numeric.readHex "FF" [(255,"")]
タプルのリストになっているので欲しいところだけ残します。
Prelude> (fst.head.Numeric.readHex) "FF" 255
readHexがどうなっているかを見てみるとこうなっていました。
readHex = readInt 16 isHexDigit digitToInt
ということで書き換え。
Prelude> (fst.head.(Numeric.readInt 16 Data.Char.isHexDigit Data.Char.digitToInt)) "FF" 255
これを基に2進数版の変換関数を作成。
Prelude> (fst.head.(Numeric.readInt 2 (`elem` "01") Data.Char.digitToInt)) "1111" 15
以下は同じような考え方で作ったPerl版。
use strict; use warnings; print join(',', rbits(4)), "\n"; print join(',', rbits(5)), "\n"; sub rbits { my $keta = shift; return map {oct "0b" . reverse sprintf "%0*b", $keta, $_} (0 .. 2 ** $keta - 1); }