Codeforces 37A - A. Towers
import Data.List calc :: [Int] -> (Int, Int) calc xs = (maximum [count x xs | x <- xs], length $ nub xs) where count a xs = sum [1 | x <- xs, x == a] main = do s <- getLine t <- getLine let (x, y) = calc $ map read $ words t putStrLn (show x ++ " " ++ show y)
個数を求めるのに、1 からなるリストを sum するのはどうも好きになれない。他に良い方法はないだろうか。
Codeforces 122B - B. Lucky Substring
calc :: String -> Int calc s | n4+n7 == 0 = -1 | otherwise = if n4 >= n7 then 4 else 7 where n4 = sum [1 | c <- s, c == '4'] n7 = sum [1 | c <- s, c == '7'] main = do s <- getLine print $ calc s
Codeforces 122A - A. Lucky Division
isLucky :: Int -> Bool isLucky n = show n == filter (\c -> c == '4' || c == '7') (show n) calc :: Int -> String calc n = if null [i | i <- [1..n], isLucky i, n `mod` i == 0] then "NO" else "YES" main = do s <- getLine putStrLn $ calc $ read s
第4回 スタートHaskell2に参加してきました
第4回 スタートHaskell2 - [PARTAKE] に参加してきました。
- 第8章「入出力」@igrep さん
- IO action
- putStrLn は文字列を引数にとり、()(空のタプル。unit型ともいう)を結果とする I/O アクションを返す
- do記法。IO actionをつなぎ合わせる。
- >>= 関数の構文糖らしい main = getLine >>= print
- when b f = bがTrueの時だけfを実行
- forever
- 第9章「もっと入力、もっと出力」 @mizu_tama さん
- ファイル操作。自由度の高い方から openFile, withFile, (readFile, writeFile, appendFile)
- System.Randomモジュール
- getStdGen
- newStdGen
- bytestring, Stringより効率よく文字列を扱う
- LT 「Haskell Golfへのおさそい」@notogawa さん
- golfしか出来なくなる危険性…。
- Haskell Golf 入門 - ぼくのぬまち 出張版
練習問題
練習問題は、エコーと九九の表だけやりました。
練習問題: エコー
ユーザーの入力をそのまま表示するプログラムを作ろう。
ただし “quit” と入力されたときは “Do you really want to quit? (yes/no)” と表示して、次の入力が “yes” だったらプログラムを終了する。
文字出力の際、バッファリングの関係ですぐに表示されないことがある。そのときは hFlushを使うとよい。
import Control.Monad import System.IO (hFlush, stdout) main = do x <- getLine if x == "quit" then do putStrLn "Do you really want to quit? (yes/no)" hFlush stdout y <- getLine when (y /= "yes") $ do main else do putStrLn x hFlush stdout main
練習問題: 九九の表
こんな感じの九九の表を表示してみよう。
1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81
Text.Printfモジュールを使うと、いわゆるprintf関数がつかえるようです。printfは IO として扱われると、文字列を出力し、Stringとして扱われるとStringを返すようです。素晴らしいですね! 参考: Text.Printf.printf を使ってみる - sirocco の書いてもすぐに忘れるメモ
import Text.Printf qq :: [[Int]] qq = [map (*i) [1..9] | i <- [1..9]] format :: Int -> String format n = printf "%3d" n formatList :: [Int] -> String formatList xs = unwords $ map format xs main :: IO () main = mapM_ putStrLn $ map formatList qq
Codeforces 146B - B. Lucky Mask
整数 a, b が与えられたとき、c のマスクが b と等しく、かつ c > a であるような c を求めよという問題。
「c のマスクが b と等しい」とは、整数 c から 4 と 7 以外の数字を取り除いた数が b と等しいという意味。
制約:
1 <= a, b <= 10^5
全探索。
mask :: Int -> Int mask n | null s = 0 | otherwise = read s where s = filter (\c -> c == '4' || c == '7') $ show n calc :: Int -> Int -> Int calc a b = head [i | i <- [a+1..], b == mask i] main = do s <- getLine let [a, b] = map read $ words s :: [Int] print $ calc a b
はじめにmask関数を書いたとき、if式を用いていたけど、ガードに書き直した。ガードの方が読みやすく分かりやすい。
mask :: Int -> Int mask n = if null s then 0 else read s where s = filter (\c -> c == '4' || c == '7') $ show n
Codeforces 221A - A. Little Elephant and Function
221A - A. Little Elephant and Function
calc :: Int -> [Int] calc 1 = [1] calc 2 = [2, 1] calc n = [n, 1] ++ [2..n-1] main = do s <- getLine putStrLn $ unwords $ map show $ calc $ read s
Codeforces 26A - A. Almost Prime
素因数分解したときに、素因数の種類が 2 つかどうか求める問題。
import Data.List factorize :: Int -> [Int] factorize 1 = [1] factorize n = fac 2 n where fac p n | n == 1 = [] | n `mod` p == 0 = p : fac p (n `div` p) | otherwise = fac (p+1) n isAlmostPrime :: Int -> Bool isAlmostPrime n = 2 == (length $ nub $ factorize n) calc :: Int -> Int calc n = sum [1 | i <- [1..n], isAlmostPrime i] main = do s <- getLine print $ calc $ read s
リストの中にpredを満たすものがいくつあるか個数を返す関数が標準ライブラリにありそうだと思って調べたけれど見つかりませんでした。