『ビンゴカード作成問題』で書いたソースの改善方法について
漠然とした質問で申しわけないのですが
お力を貸していただけるとうれしいです
『Ruby初心者必見!?「ビンゴカード作成問題」のリファクタリング風景をお見せします #codeiq』
http://blog.jnito.com/entry/2015/03/06/090106
にあった『ビンゴカード作成問題』をHaskellで挑戦してみました
=================
■ルール■
①各列の値は以下の条件を満たすこと
B:1~15のどれか
I:16~30のどれか
N:31~45のどれか
G:46~60のどれか
O:61~75のどれか
②毎回異なるカードを生成すること
③どの数値も重複しないこと
④各列はパイプ(|)で区切ること
⑤数字や"BINGO"の文字は右寄せで出力すること
⑥真ん中(FREEになる場所)はスペースを出力すること
=================
{-# OPTOINS -Wall -Werror #-}
{-# LANGUAGE OverloadedStrings, ViewPatterns #-}
import qualified Data.List as L
import qualified Data.Text as T
import qualified System.Random as R
type RangeUnit = (Int, Int)
header = "BINGO"
bingoSize = T.length header
numrange = 15
rangeUnit = take bingoSize $ zip [1,numrange+1..] [numrange, numrange*2..]
body = do
nums <- mapM (createRondomRange bingoSize) rangeUnit
return $ formatCell 2 2 nums
viewBingo = do
b <- body
return $ map formatline $ map appendSeparatedWord $ headerList : b
where
headerList = map (\x -> justifyRightSpace $ T.pack [x]) $ T.unpack header
appendSeparatedWord = L.intersperse $ T.pack " | "
formatline = foldl T.append T.empty
createRondomRange :: Int -> RangeUnit -> IO [Int]
createRondomRange range (start, end) = do
gen <- R.newStdGen
return $ take range . L.nub $ R.randomRs (start, end) gen
formatCell :: Int -> Int -> [[Int]] -> [[T.Text]]
formatCell rowIndex colIndex vals =
L.transpose $ mmap (justifyRightSpace . centerReplaced) vals
where
centerReplaced x = if centerVal == x then " " else T.pack $ show x
centerVal = vals !! rowIndex !! colIndex
justifyRightSpace = T.justifyRight 2 ' '
mmap f = map (map f)
main = do
b <- viewBingo
mapM_ print b
■質問内容
・Haskellらしく書くにはこうしたほうがいい
・この便利関数を使えばこんな回りくどいことしなくていい
・そもそも書く上での考え方が悪(ry
などなど、ソースを改善するお力を貸していただきたいです
また①の数値の範囲について
import qualified Data.List.Split as S
ranges = S.splitEvery 15 [1..75]
で作成したrangesの格リストの値をシャッフルすることで
作りたかったのですが方法がわかりませんでした。
リストの要素をランダムに入れ替える関数はあるのでしょうか