Naomi's notebook

Naomi's notebook

AtCoder Beginners Selection in Haskell 〜B問題

atcoder.jp

HaskellでACしていきます

メモ

エラー:pattern match failure in do expression はだいたい入力を前の問題から変え忘れたことによりパターンマッチしていないというエラー

PracticeA - Welcome to AtCoder

-- import module
import Control.Applicative  

main = do
    a <- readLn --型推論
    [b,c] <- map read . words <$> getLine
    d <- getLine
    putStrLn $ show (a + b + c) ++ " " ++ d

ABC086A - Product

-- import module
import Control.Applicative  

isOddEven::Int->String
isOddEven x | mod x 2==0 = "Even"
    | otherwise = "Odd"

main = do
    [a,b] <- map read . words <$> getLine
    putStrLn $ isOddEven (a*b)

ABC081A - Placing Marbles

-- import module
import Control.Applicative  

sumofplaces::Int->Int
sumofplaces 0 = 0
sumofplaces a = mod a 10 + sumofplaces (quot a 10)

main = do
    a <- readLn
    print $  sumofplaces a

ABC081B - Shift only

import Control.Applicative  

twodiv::Int->Int
twodiv x | mod x 2 ==1 = 0
    | otherwise = 1+twodiv( quot x 2 )


main = do
    n <- getLine
    a <- (map read . words) <$> getLine
    print $  minimum (map twodiv a)
    

ABC087B - Coins

めちゃくちゃ愚直ですが
リスト内包表記でループが実現できてるの面白い

import Control.Monad
import Control.Applicative 
-- Control.Monad は replicateM を使うのに必要(改行区切り入力の取得)

ifxyen::Int->(Int,Int,Int)->Int
ifxyen x (a,b,c) | a*500+b*100+c*50 ==x =1
    | otherwise = 0

main = do
    [a,b,c,x] <- replicateM 4 readLn
    print $ sum ( map (ifxyen x) [(x,y,z) | x<-[0..a],y<-[0..b],z<-[0..c]])

Some Sums

import Control.Applicative  

sumofplaces::Int->Int
sumofplaces 0 = 0
sumofplaces a = mod a 10 + sumofplaces (quot a 10)
ifAtoB::Int->Int->Int->Int
ifAtoB _ _ 0 = 0
ifAtoB a b x |( a<=(sumofplaces x) ) && ( b>=(sumofplaces x) ) = x 
    | otherwise = 0

main = do
    [n,a,b] <- (map read . words) <$> getLine
    print $  sum ( map (ifAtoB a b) [1..n])

最初リストで101..にしてsumをとって1..Nのそのような数の個数を求めようとしてたけど、一重ループだしわざわざリスト内包表記にしなくても-1してけばループできる(それはそう)
と思ったらなぜかこれはTLE。なぜなのかわからないので誰か教えてください
(追記)
コメントで教えていただきました!関数適用はどんな中置演算子よりも高い優先順位をもっているので、ifAtoB a b x-1 が(ifAtoB a b x)-1と認識され、xが減らないままifAtoBが呼び出されて無限再帰していたためTLEなようです。(AtCoderの仕様を勘違いしていたのですが答えが出てなくてもTLEになるのか、それはそう?)
ifAtoB a b (x-1)にしたらAC。

import Control.Applicative  
 
sumofplaces::Int->Int
sumofplaces 0 = 0
sumofplaces a = mod a 10 + sumofplaces (quot a 10)
ifAtoB::Int->Int->Int->Int
ifAtoB a b 0 = 0
ifAtoB a b x |( a<=(sumofplaces x) ) && ( b>=(sumofplaces x) ) = x + (ifAtoB a b x-1)
    | otherwise = (ifAtoB a b x-1)
 
main = do
    [n,a,b] <- (map read . words) <$> getLine
    print $  ifAtoB a b n

ABC088B - Card Game for Two

(sumoddite xs (n+1))のn+1にかっこをつけないと、そこが分離してしまうようだ…(演算順序)

import Control.Applicative  
-- listをquicksortする関数がある
import Data.List

sumoddite::[Int]->Int->Int
sumoddite [] _ = 0
sumoddite (p:xs) n | (mod n 2)==1 = p + (sumoddite xs (n+1))
    | otherwise = 0 + (sumoddite xs (n+1))

main = do
    n <- getLine
    a <- (map read . words) <$> getLine
    let sa = sortBy (\x y -> compare y x) a
    print $ 2*(sumoddite sa 1)-sum sa

ABC085B - Kagami Mochi

import Control.Applicative 
import Control.Monad
import Data.List

notsamelen::[Int]->Int->Int
notsamelen [] _ = 0
notsamelen (p:xs) n | p==n = 0 + (notsamelen xs p)
    | otherwise = 1 + (notsamelen xs p)

main = do
    n <- readLn
    d <- replicateM n readLn
    let sd = sort d
    print $ notsamelen sd 0