challenge 文字列のセンタリング

文字列を指定のカラム幅にセンタリング配置する関数を示してください。文字列の長さが指定した幅より長い場合には文字列の両端をできるだけ均等に切り落して指定幅に収めてください。1文字は1カラムに収まるものと仮定してかまいません。

Posted feedbacks - Haskell

1
2
3
4
5
6
7
8
9
center :: Int -> [Char] -> [Char]
center n str | slen < n  = center'
             | slen > n  = clop
             | otherwise = str
  where
    slen = length str
    center' = lmargin ++ str ++ rmargin
    (lmargin, rmargin) = splitAt ((n-slen) `div` 2) $ replicate (n-slen) ' '
    clop = take n $ drop ((slen-n) `div` 2) str

Haskellらしく無限リストと高階関数で。

1. 文字列の右に無限個の空白を連結
2. 左側を揃える
3. 幅の分だけ切り取る
1
2
3
4
5
center width str = take width . adjust lmargin $ str ++ repeat ' '
    where 
    lmargin = (width - length str) `div` 2
    adjust n | n > 0      = (replicate n ' ' ++)
             | otherwise  = drop (-n)

覚えたてのControl.Monad.Fixを使って。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import Control.Monad.Fix

center :: Int -> String -> String
center n = fix (\f x -> g f x)
  where g f x | length x1 == n = x1
              | length x2 == n = x2
              | length x2 > n = f x2
              | otherwise = f $ head $ zipWith3 (\x y z -> x ++ y ++ z) [" "] [x] [" "]
          where x1 = tail x
                x2 = init x1

明示的算術演算なし、lengthで文字列の長さも測っていない、「そこまでしたからってどうよ」版 ^^;
あ。それから、このセンタリングでは空白は前より入り、切り落としは後ろよりになります。

center 2 "a" → "_a"
center 3 "a" → "_a_"
center 3 "ab" → "_ab"
center 4 "ab" → "_ab_"
center 3 "abcde" → "bcd"
center 4 "abcde" → "bcde"
center 3 "abcdef" → "bcd"
center 4 "abcdef" → "bcde"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
center n s = uncurry (c n []) $ halve s
  where c 0 a p q = take n (a ++ q)
        c i a p q = d (pred i) (head p:a) (tail p) q
        d 0 a p q = take n (a ++ q)
        d i a p q = c (pred i) a p q

halve s = e (repeat ' ') (s++repeat ' ') s
  where e a b [] = (a,b)
        e a b c  = o (head b:a) (tail b) (tail c)
        o a b [] = (a,b)
        o a b c  = e a b (tail c)

Index

Feed

Other

Link

Pathtraq

loading...