{- Convert zero-padded big-endian decimal to zero-padded big-endian hexadecimal. Copyright 2015 Ken Takusagawa This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -} {-# LANGUAGE ScopedTypeVariables, LambdaCase #-} module Main(main) where { import Data.List; import Data.Tuple(swap); import Data.Char(intToDigit); main :: IO(); -- convert the first number in each line main = getContents >>= mapM_ putStrLn . map (to_hex . head . words) . lines; radix_convert :: Integer -> Integer -> [Integer]; radix_convert base = unfoldr $ \n -> if n==0 then Nothing else Just $ swap $ divMod n base; {- we see an N digit decimal number. Some hexadecimal number h=fff..ff converts to a N digit decimal number. The N digit decimal number x=1000..0 is less than or equal to h=fff..ff. The N digit decimal number y=9999..9 is greater than or equal to h. Idea 1: convert 9999..9 and knock off the leading digit, so fff..ff is somewhere in there. A little better is convert the N+1 digit 10^N and knock off the leading digit. -} equivalent_hexadecimal_length :: Integer -> Integer; equivalent_hexadecimal_length dec_length = pred $ genericLength $ radix_convert 16 (10^dec_length); to_hex_int :: String -> [Integer]; to_hex_int s = let { answer :: [Integer]; answer = radix_convert 16 $ read s; expected_length :: Integer; expected_length = equivalent_hexadecimal_length $ genericLength s; } in case compare (genericLength answer) expected_length of { LT -> genericTake expected_length $ answer ++ repeat 0; EQ -> answer; GT -> error "decimal number too large for padding"; }; to_hex_string :: [Integer] -> String; to_hex_string = map (intToDigit . fromInteger) . reverse; to_hex :: String -> String; to_hex = to_hex_string . to_hex_int; } --end