wvogel日記

自分用の技術備忘録が多めです.

3問

今日はcodeforcesの問題を夕方と帰宅後、合わせて3問解きました。


そのうちの一問、こちら


捻ったようなアルゴリズムも不要で、
ちゃんと書けばちゃんと動いてくれる問題。
問題の背景を考えるとちょっと面白かったです。


10進数→2進数、
2進数→10進数の関数など、探せばありそうですが、
簡単なので書いた方が早い。


それより、ASCIIコードの取得方法をどうしようかと思いました。
H -> 72
! -> 33
のような変換は、タプルのリスト作ったりするより効率の良い方法がありそう。


実際、Data.Charの中をHoogleで探したらあった。

ord :: Char -> Int
chr :: Int -> Char

型情報の通りの挙動をしてくれます。
意外と便利そう。
問題のソースコードと共にここにメモしておきます。

import Data.Char (ord)    --ord Char->Int
import Control.Monad

intercal :: [Char] -> Int -> [Int]
intercal [] _ = []
intercal (x:xs) n = let k =  transform x
                    in value k : intercal xs k
  where
    transform = toDec.length8. toBi.ord
    value k = (n - k) `mod` 256

--二進数の文字列長を8に調整
length8 :: String -> String
length8 xs = xs ++ replicate (8-length xs) '0'

--10進数から2進数へ(逆順)
toBi :: Int -> String
toBi 0 = "0"
toBi n = show (mod n 2) ++ toBi (div n 2)

--2進数から10進数へ
toDec :: String -> Int
toDec [] = 0
toDec ('0':cs) = toDec cs
toDec ('1':cs) = 2^(length cs) + toDec cs

main = do xs <- getLine
          forM_ (intercal xs 0) print