cf. どう書く?.org – アルファベットの繰り上がり
succ でいいじゃん,と思ったらダメだった。
Prelude> succ 'A'
'B'
Prelude> succ 'Z'
'['
Ruby の String#succ はうまくやってくれるのに。
なら,26進数だと考えて素直に繰り上がりを処理すればいいか……と思ったけどこれもダメ。’A’ は 0 じゃない。要するに 0 が無いんだな。結局繰り上がりのところで汚いコードになってしまった。
module Main ( main ) where
import Data.Char ( ord, chr )
import Data.List ( mapAccumR, intersperse )
succS :: [Char] -> Int -> [Char]
succS s n = map intToAlpha $ g $ mapAccumR f n $ map alphaToInt s
where
alphaToInt c = (ord c ) - 64
intToAlpha i = chr (i + 64)
f acc x = let (d,m) = (acc+x) `divMod` 26
in if m == 0 then (d-1,26) else (d,m)
g (0,b) = b
g (a,b) = a:b
main :: IO ()
main = putStr $ concat $ intersperse "," $ take 100 $ iterate (flip succS 1) "A"
実行:
^o^ >runhaskell succS.hs
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,AB,AC,AD,AE,AF,AG,AH,AI,A
J,AK,AL,AM,AN,AO,AP,AQ,AR,AS,AT,AU,AV,AW,AX,AY,AZ,BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,
BK,BL,BM,BN,BO,BP,BQ,BR,BS,BT,BU,BV,BW,BX,BY,BZ,CA,CB,CC,CD,CE,CF,CG,CH,CI,CJ,CK
,CL,CM,CN,CO,CP,CQ,CR,CS,CT,CU,CV