競速
決定來一次 C / C++ / Java / Ruby ACM#100 競速大亂鬥(Common Lisp 還不行 XD)。以下是各種語言的程式碼,以自然為主,不特地做 tweak。程式邏輯均相同,變數名稱儘量維持一致:
1: /* ACM#100 in C */
2:
3: #include <stdio.h>
4:
5: int main() {
6: int i, j, temp, k, max, kk, count;
7: while (scanf("%d%d", &i, &j) == 2) {
8: printf("%d %d ", i, j);
9: if (i > j) {
10: temp = j;
11: j = i;
12: i = temp;
13: }
14: max = 0;
15: for (k = i; k <= j; ++k) {
16: kk = k;
17: count = 1;
18: while (kk != 1) {
19: kk = kk % 2 ? kk * 3 + 1 : kk / 2;
20: ++count;
21: }
22: if (count > max) {
23: max = count;
24: }
25: }
26: printf("%d\n", max);
27: }
28: return 0;
29: }
1: // ACM#100 in C++
2:
3: #include <algorithm>
4: #include <iostream>
5: using namespace std;
6:
7: int main() {
8: int i, j;
9: while(cin >> i >> j){
10: cout << i << ' ' << j << ' ';
11: if (i > j) {
12: swap(i, j);
13: }
14: int max = 0;
15: for (int k = i; k <= j; ++k) {
16: int kk = k;
17: int count = 1;
18: while (kk != 1) {
19: kk = kk % 2 ? kk * 3 + 1 : kk / 2;
20: ++count;
21: }
22: if (count > max) {
23: max = count;
24: }
25: }
26: cout << max << endl;
27: }
28: }
1: // ACM#100 in Java
2:
3: import java.io.*;
4: import java.util.*;
5:
6: public class ACM100 {
7: public static void main(String[] args) throws Exception {
8: Scanner in = new Scanner(System.in);
9: int i, j;
10: while(in.hasNextInt()) {
11: i = in.nextInt();
12: j = in.nextInt();
13: System.out.print(i + " " + j + " ");
14: if (i > j) {
15: int temp = j;
16: j = i;
17: i = temp;
18: }
19: int max = 0;
20: for (int k = i; k <= j; ++k) {
21: int count = 1;
22: int kk = k;
23: while (kk != 1) {
24: kk = kk % 2 == 0 ? kk / 2 : 3 * kk + 1;
25: ++count;
26: }
27: if (max < count) {
28: max = count;
29: }
30: }
31: System.out.println(max);
32: }
33: }
34: }
1: # ACM#100 in Ruby
2:
3: while s = gets
4: i, j = s.split(/\s+/).collect {|t| t.to_i}
5: i, j = j, i if i > j
6: print "#{i} #{j} "
7: max = 0
8: (i..j).each do |k|
9: count = 1
10: until k == 1
11: k = k % 2 == 0 ? k / 2 : 3 * k + 1
12: count += 1
13: end
14: max = count if max < count
15: end
16: puts max
17: end
然後是協助我加上行號的 Ruby script lineno:
1: #!/usr/local/bin/ruby -w
2:
3: a = readlines
4: for i in 0...a.length
5: printf("%#{(Math.log10(a.length) + 1).to_i}d: %s", i + 1, a[i])
6: end
以及擔任本次大亂鬥評審的 Ruby script timer:
1: #!/usr/local/bin/ruby -w
2:
3: s = ARGV[0]
4: s = s[1...-1] if s[0] == '"'
5: t1 = Time.now
6: system(s)
7: t2 = Time.now
8: printf("elapsed time: %.6f second(s).\n", t2.to_f - t1.to_f)
C/C++ 編譯時不開最佳化。測試時,皆將「內含一行 "1 100000" 的檔案」重新導向(redirect)到程式的 stdin。以下是結果:
| 語言 | C | C++ | Java | Ruby |
| 秒數 | 0.209 | 0.205 | 0.642 | 27.635 |
| 比值 | 1.020 | 1 | 3.132 | 134.805 |
其中「比值」是對「最少秒數」(C++)的比值。
雖然這次競速中,C 小輸 C++,但兩者實際上相差無幾,誰贏只是機率問題。這很顯然,因為這次競速用的程式碼,幾乎落在 C++ 的 "better C" paradigm 裡面(即 Scott Meyers 所謂的 C part of C++)。而且此次競速的 I/O 並不大量,若給多筆測資,C++ iostream 應該就得敗給 C stdio。Java VM 雖然帶有 JIT 技術,但終究多了一道間接層,比 C/C++ 慢了三倍。Ruby 就不用說了,要拚速度絕不是對手。On the other hand,Ruby 的程式碼看起來真的比較清爽一些,尤其和 Java 相比 :P。


一次看那麼多程式碼
重要的是,大概都能看種,真是一件令人高興的事
ruby慢到讓我覺得神奇啊...這其中必然有原因,不僅僅只是script language而己
<< 回到主頁