我是一名C++程序员,正在尝试自学Haskell,并且它证明了把握使用函数作为一种循环的基础知识的挑战.我有一个很大的数字,50!,我需要添加其数字的总和.这是一个相对简单的C++循环,但我想学习如何在Haskell中完成它.
我已经阅读了一些入门指南,能够获得50分!同
sum50fac.hs ::
fac 0 = 1
fac n = n * fac (n-1)
x = fac 50
main = print x
Run Code Online (Sandbox Code Playgroud)
不幸的是,在这一点上,我并不完全确定如何处理这个问题.是否有可能编写一个函数将(mod)x 10添加到一个值,然后在x/10上再次调用相同的函数,直到x/10小于10?如果那不可能,我应该如何处理这个问题?
谢谢!
Yas*_*aev 11
sumd 0 = 0
sumd x = (x `mod` 10) + sumd (x `div` 10)
Run Code Online (Sandbox Code Playgroud)
然后运行它:
ghci> sumd 2345
14
Run Code Online (Sandbox Code Playgroud)
更新1:
这个不生成thunk并使用累加器:
sumd2 0 acc = acc
sumd2 x acc = sumd2 (x `div` 10) (acc + (x `mod` 10))
Run Code Online (Sandbox Code Playgroud)
测试:
ghci> sumd2 2345 0
14
Run Code Online (Sandbox Code Playgroud)
更新2:
部分应用版本采用无点样式:
sumd2w = (flip sumd2) 0
Run Code Online (Sandbox Code Playgroud)
测试:
ghci> sumd2w 2345
14
Run Code Online (Sandbox Code Playgroud)
我flip
在这里使用是因为函数由于某种原因(可能是由于GHC设计)不能用累加器作为第一个参数.
new*_*cct 11
为什么不呢
sumd = sum . map Char.digitToInt . show
Run Code Online (Sandbox Code Playgroud)
这只是@ ony的一个变种,但是我怎么写它:
import Data.List (unfoldr)
digits :: (Integral a) => a -> [a]
digits = unfoldr step . abs
where step n = if n==0 then Nothing else let (q,r)=n`divMod`10 in Just (r,q)
Run Code Online (Sandbox Code Playgroud)
这将产生从低到高的数字,虽然读数不自然,但通常是涉及数字数字的数学问题.(项目欧拉有人吗?)另请注意,0
生成[]
和负数被接受,但产生绝对值的数字.(我不想要部分功能!)
另一方面,如果我需要一个数字的数字,因为它们是通常写的,那么我会使用@ newacct的方法,因为问题是基本的正字法,而不是数学:
import Data.Char (digitToInt)
writtenDigits :: (Integral a) => a -> [a]
writtenDigits = map (fromIntegral.digitToInt) . show . abs
Run Code Online (Sandbox Code Playgroud)
比较输出:
> digits 123
[3,2,1]
> writtenDigits 123
[1,2,3]
> digits 12300
[0,0,3,2,1]
> writtenDigits 12300
[1,2,3,0,0]
> digits 0
[]
> writtenDigits 0
[0]
Run Code Online (Sandbox Code Playgroud)
在做Euler项目时,我实际上发现有些问题需要一个,有些则需要另一个问题.
.
和"无点"风格为了让那些不熟悉Haskell .
运算符和"无点"风格的人明白这些,可以将它们重写为:
import Data.Char (digitToInt)
import Data.List (unfoldr)
digits :: (Integral a) => a -> [a]
digits i = unfoldr step (abs i)
where step n = if n==0 then Nothing else let (q,r)=n`divMod`10 in Just (r,q)
writtenDigits :: (Integral a) => a -> [a]
writtenDigits i = map (fromIntegral.digitToInt) (show (abs i))
Run Code Online (Sandbox Code Playgroud)
这些与上面完全相同.您应该知道这些是相同的:
f . g
(\a -> f (g a))
Run Code Online (Sandbox Code Playgroud)
而"无点"意味着它们是相同的:
foo a = bar a
foo = bar
Run Code Online (Sandbox Code Playgroud)
结合这些想法,这些是相同的:
foo a = bar (baz a)
foo a = (bar . baz) a
foo = bar . baz
Run Code Online (Sandbox Code Playgroud)
laster是惯用的Haskell,因为一旦你习惯了它,你可以看到它非常简洁.
总结一个数字的所有数字:
digitSum = sum . map (read . return) . show
Run Code Online (Sandbox Code Playgroud)
show将数字转换为字符串.map迭代字符串的单个元素(即数字),将它们转换为字符串(例如字符'1'变为字符串"1")并读取它们将它们变回整数.总和最后计算总和.
归档时间: |
|
查看次数: |
8644 次 |
最近记录: |