Created
November 11, 2012 07:43
-
-
Save hitsumabushi/4054092 to your computer and use it in GitHub Desktop.
すごいH本読書会 in 大阪 #1 問題
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- ガードを使わないことにしてみる。 | |
-- map, filter,fold も使わない. | |
-- いくつかの関数の実装 | |
-- null, sum, product, elem | |
null' :: [a] -> Bool | |
null' [] = True | |
null' _ = False | |
-- sum と product 書くのめんどくさいので。 | |
-- foldも使わないと言ったけど、実装しないとは言ってないっ! | |
-- 型もfold{l|r}と違うし。 | |
reduce :: (a -> a -> a) -> a -> [a] -> a | |
reduce _ x [] = x | |
reduce f x (y:ys) = reduce f (f x y) ys | |
sum' :: (Num a) => [a] -> a | |
sum' = reduce (+) 0 | |
product' :: (Num a) => [a] -> a | |
product' = reduce (*) 1 | |
elem' :: (Eq a) => a -> [a] -> Bool | |
elem' a = any ( == a) | |
-- Python の slice の実装 | |
slice :: Int -> Int -> [b] -> [b] | |
slice n m xs = take (m - n) $ drop n xs | |
-- fibo : Fibonacci 数列 の n 番目を返す関数 | |
-- まず、 fibon を定義する | |
fibon :: (Integral a) => a -> a -> a -> a | |
fibon a _ 0 = a | |
fibon _ b 1 = b | |
fibon a b n = fibon b (a + b) (n - 1) | |
fibo = fibon 0 1 | |
-- sliceFizzBuzz : FizzBuzz の n ~ m 番目 | |
-- まず、FizzBuzz の無限リストを返す関数 fizzBuzz を作る | |
divisable :: (Integral a) => (a,a) -> (b,b) -> b | |
divisable (m,n) (s,t) = if m `mod` n == 0 then s else t | |
fizzBuzz :: [String] | |
fizzBuzz = [ x ++ y | n <- [1..], let x = divisable (n,3) ("Fizz",""), let y = divisable (n,5) ("Buzz","")] | |
sliceFizzBuzz n m = slice n m fizzBuzz | |
-- 問題: | |
-- 3けたの整数のうち、次の条件を満たすものを「良い整数」とよぶことにします。 | |
-- 条件: 3けたの整数を2つの整数に分けてその和を考えると、常にもとの整数の約数になっている。 | |
-- 例1 : 330は3と30に分けても、33と0に分けても和が330の約数になっています。このため、330は「良い整数」となります。 | |
-- 例2 : 702は7と02に分けた場合は約数になりますが、70と2に分けてしまうと約数になりません。よって、702は「良い整数」ではありません。 | |
-- 一の位が0でない「良い整数」を4個求めなさい。 | |
-- 解答: | |
spanList :: [a] -> [([a],[a])] | |
spanList xs = takeWhile (not . null . snd) [splitAt n xs | n <- [1..]] | |
-- Integral に対してgoodかどうかを判定 | |
isGoodNum :: (Read a,Show a, Integral a) => a -> Bool | |
isGoodNum n = | |
let xs = spanList $ show n | |
nums = [ (read $ (fst x)) + (read $ (snd x))| x <- xs ] | |
in and [ n `mod` sum == 0 | sum <- nums ] | |
goodAnswer = [ n | n <- [100..999], n `mod` 10 /= 0, isGoodNum n] | |
-- 終わり. | |
-- 以下、一般化して解いて、その部分列を取ろうと思ったけど、停止しない… | |
-- どうしてすぐ終わらないのかわからない。教えていただけるとありがたい。 | |
goodNumsWithDigitCondition :: (Read a,Show a,Integral a) => [a] | |
goodNumsWithDigitCondition = [ n | n <- [1..], n `mod` 10 /= 0, isGoodNum n] | |
-- そこから 3桁の数の部分リストを取る | |
answerNums :: (Read a,Show a,Integral a) => (a,a) -> [a] | |
answerNums (n,m) = dropWhile (< n) $ takeWhile (< m) goodNumsWithDigitCondition | |
answer = answerNums (100,1000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment