競速
決定來一次 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而己
<< 回到主頁