2014-05-19 184 views
-5

想法是儘可能使優雅代碼。部分主題:循環。 任務:返回數字從1到(n-1)的平方和 示例:6 - > 55(即1^2 + 2^2 + 3^2 + 4^2 + 5^2)代碼尋找遊戲02.05

我選擇了Java作爲語言寫了這樣的代碼:

public class Program { 
    public static int Puzzle(int n) { 
     int r=0; 
     for(--n;n>=0;r+=n*n--); 
     return r; 
    } 
} 

但是編譯器說,我的代碼是不是優雅不夠。你能幫我嗎? 鏈接:CodeHunt

+0

這屬於代碼高爾夫球:http://codegolf.stackexchange.com/ –

+3

可以粘貼你的編譯器給你說這是不是優雅的實際消息? –

+0

它並沒有對它說一個字,但它測量了「技能」塊的結果。對於3個區塊來說,代碼是優雅的,但無論我做什麼 - 我總是隻有2個區塊 –

回答

1

一些非常不雅方面:

  • 在線遞增/遞減:他們使代碼非常混亂,因爲大多數人都當變量實際上將遞減中沒有專家,又會爲實例發生在m = (n--)*(--n);(答案是m = n*(n-2); n -= 2;)。對於一些小的簡單表達式,內聯遞減使代碼更易讀。但幾乎在所有情況下,都沒有性能提升,因爲編譯器足夠聰明,可以將可讀代碼轉換爲內聯自增或自減的代碼。
  • 無循環:大多數人只是感到困惑,認爲下一條指令是身體的一部分,等等。大多數IDE甚至建議總是使用大括號並在身體中寫一些東西。
  • 對參數的操作:這是令人困惑的,並且使得代碼可擴展性較差。假設你想用下面的部分擴展你的代碼,你執行複製,因爲參數沒有它們的原始值,粘貼的代碼將工作不同。 IDE主要建議至少製作一份副本。幾乎每個編譯器都可以優化這個,如果事實證明參數不再被使用。
  • 遞減for for循環:雖然這有時會使代碼性能略有提高,但大多數程序員習慣於增加循環。
  • 語義變量名稱(編譯器無法檢測到的東西):建議您正確命名變量,使用sum而不是r。 java編譯器將名稱視爲標識符。所以在運行時沒有什麼區別,但是當你在幾個月後重新訪問你的代碼時,它對於其他人和你自己來說更具可讀性。

這些都是編寫算法的非常糟糕的方法。大多數書都強烈建議,除非你真的需要編寫一個代碼,它能夠從CPU中獲得絕對最大的代碼,那麼你最好寫出漂亮,結構合理和可讀的代碼。此外,如果是這種情況,那麼比Java更有效的語言。


作爲一個更好的版本,我建議如下代碼:

public class Program { 

    public static int Puzzle(int n) { 
     int sum = 0; 
     for(int i = 1; i < n; i++) { 
      sum += i*i; 
     } 
     return sum; 
    } 

} 

而且你不需要for -loop計算這個(爲指出here):

public class Program { 

    public static int Puzzle(int n) { 
     return n*(n-1)*(2*n-1)/6; 
    } 

} 
+0

不過,它表示它不夠好。我認爲它想要一些小而明顯的東西像 return Array.Sum(0,n) 但是我不知道是否存在這樣的操作 –

+0

正如@morrizon所說的,根本不需要for循環,可以簡單地使用sum展開:https://www.wolframalpha.com/input/?i=sum%20of%20i^2%20with%20i%20from%201%20to%20n –

1

優雅可能是簡單性和準確性的組合。你的方法最大的問題是它並不簡單,它可能會產生正確的結果,但它不必要的複雜,並且有不尋常的迭代,並且你正在爲其副作用運行for-loop。

爲什麼不用更直接的方法呢?

public static Puzzle(int n) { 
    int sum = 0; 
    for(int i = 1; i <= n; i++) { 
     sum += Math.pow(i, 2); 
    } 
    return sum; 
} 
+0

我將替換'Math.pow(n ,2)'帶'n * n',因爲'n'是一個整數,對於小功率,展開的版本更具可讀性。此外,由於'n'是一個整數,所以它會更有效率(否則'2'必須首先解釋,等等)。 –

+0

此外,你應該總結'我*我'而不是'n * n'。 –