我正在尝试在Haskell中实现硬币找零问题。问题如下:
给定一组硬币和无限个这些硬币,找到使一个特定值n所需的最小硬币数。
我在Haskell中编写了以下程序:
我用C++编写了以下程序:
我使用
Haskell:
给定一组硬币和无限个这些硬币,找到使一个特定值n所需的最小硬币数。
我在Haskell中编写了以下程序:
import Data.Vector ((!), generate)
import Control.Applicative
import Control.Monad
coins = [1, 5, 10, 25, 100] :: [Int]
coinchangev :: Int -> [Int] -> Int
coinchangev n cs = v ! n
where v = generate (n+1) f
f 0 = 0
f n = 1 + minimum [v ! x | x <- map (n-) cs, x >= 0]
main :: IO ()
main = do n <- read <$> getLine :: IO Int
putStrLn . show $ coinchangev n coins
我用C++编写了以下程序:
#include <iostream>
#include <vector>
using namespace std;
typedef vector<int> row;
const row coins {1, 5, 10, 25, 100};
#define INT_MAX 9999999;
int coinchange(const int n, const row& coins) {
row v(n+1, 0);
for (int i=1; i<n+1; i++) {
int min = INT_MAX;
for (int j=0; j<coins.size(); j++) {
int x = i - coins[j];
if (x >= 0 && v[x] < min) {
min = v[x];
}
}
v[i] = 1 + min;
}
return v.back();
}
int main() {
int n; cin >> n;
cout << coinchange(n, coins) << endl;
return 0;
}
我使用
ghc -O3
(版本为7.8.4)编译了Haskell版本,使用g++ --std=c++1y -O3
(版本为4.8.4)编译了C++版本。对于输入10000000
,我的Haskell程序比我的C++程序需要更长的时间来完成。以下是使用time测量的计时结果:Haskell:
6.40user 0.85system 0:07.26elapsed 99%CPU (0avgtext+0avgdata 2664316maxresident)k
152inputs+0outputs (1major+647822minor)pagefaults 0swaps
C++:0.08user 0.00system 0:00.08elapsed 97%CPU (0avgtext+0avgdata 39964maxresident)k
0inputs+0outputs (0major+936minor)pagefaults 0swaps
我的问题是为什么我看到这样大的差异以及我可以采取哪些步骤(如果有的话)来提高Haskell代码的性能。我原本期望性能基本相同(至少在相同顺序内)。我的目标是在两种语言中保持解决方案简单(并希望是惯用的)。
-O3
是GHC选项? GHC的优化级别最高只有2。 - Carl[x | x <- map ((v!) . (n-)) cs, x >= 0]
替代[v ! x | x <- map (n-) cs, x >= 0]
将执行时间降低到2.18user 0.29system 0:02.48elapsed 99%CPU (0avgtext+0avgdata 983660maxresident)k 0inputs+0outputs (0major+226603minor)pagefaults 0swaps
。 - Ajit Singh