2011-12-22 62 views
2

我不知道Ruby,但我想了解歐拉#17問題的代碼。我理解這個問題,並且理解代碼的前幾行。並且,我搜索了關於個人方法,如putsinjects。我不明白代碼在|sum,n|之後要做什麼。如何將Ruby代碼轉換爲僞代碼?

有人可以將它翻譯成某種僞代碼嗎?

這是the code

digit = [ 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 8, 7, 9, 8, 8 ] 
decade = [4, 3, 6, 6, 5, 5, 5, 7, 6, 6] 

puts (1..1000).inject(0) { |sum, n| 
    sum, n = sum + 11, n % 1000 if n > 999 
    sum, n = sum + digit[n/100] + (n % 100 > 0 ? 10 : 7), n % 100 if n > 99 
    sum, n = sum + decade[n/10], n % 10 if n > 19 
    sum += digit[n] if n > 0 
    sum 
} 
+0

如果你瞭解'puts'和'inject',其餘的是僞代碼。 – 2011-12-22 20:14:01

+0

查看Ruby Array類和Enumerate模塊。那你很好。 – three 2011-12-22 20:15:45

+0

如果我遇到有人使用「','」操作符將行連接到這樣的條件,我會在代碼審查中對它們進行編程。雖然它是一個可用的加入操作的操作符,但它幾乎不常見或習慣用法,並且不會加速代碼或使其更具可讀性。避開這種做法,遵循Ruby的啓發式禪宗代碼。 – 2011-12-22 20:48:50

回答

0

我假設你已經熟悉了模數(n % 100)和三元運算符(condition ? result_if_true : result_if_false

僅有的兩個新的概念在這裏是:

  • 後綴條件

因此,代碼

sum += digit[n] if n > 0 

相當於

if n > 0 
    sum += digit[n] 
end 
  • 質量分配

代碼

sum, n = sum + decade[n/10], n % 10 if n > 19 

被等價格到

if n > 19 
    sum = sum + decade[n/10] 
    n = n % 10 
end 

現在的代碼應該是明顯的。

+0

謝謝你的回覆。我瞭解後綴條件,但我不明白你引用的大規模分配示例。根據我的理解,puts(1..1000)就像循環遍歷1到1000,並且對於每個數字n,根據條件檢查和評估所有三個語句。 現在我不確定是在總和評估後它被加在一起嗎? 循環內部是否會遇到所有三個sum語句? – user1110749 2011-12-22 20:24:53

+0

有人可以拋出一些更多的光線對個別 這些語句例如 總和之一,N = SUM + 11,N%1000當n> 999 難道指定如 的東西,如果N> 999 {N = N %1000 sum = sum + n} 正如我們對'='操作符的LHS求和n,它指定了什麼 – user1110749 2011-12-22 20:33:43

+0

是的,'inject'對一個集合進行操作(在這種情況下,數字從1到1000) 。它將給定的函數應用於每個元素並累計返回的結果。 – 2011-12-22 20:37:18

3

首先,注意,在這一程序中的錯誤:digit[15]應該是7,不是8

我不知道,如果將其轉換成僞代碼將使其更清楚,但這裏是由線路的線路解釋:

sum, n = sum + 11, n % 1000 if n > 999 

如果n是至少1000,添加的詞的one thousand非空格字符的數目到正在運行的總sum,然後用n由1000除以例如其餘取代n,如果n分別爲1538,n % 1000將爲538,從而刪除第一位數字。

sum, n = sum + digit[n/100] + (n % 100 > 0 ? 10 : 7), n % 100 if n > 99 

如果n爲至少100,添加第1位的名稱的長度,加上7(字hundred的長度)。如果n不是100的倍數,則還需要添加單詞and,總共10個字符。然後像以前一樣刪除n的第一個數字。

sum, n = sum + decade[n/10], n % 10 if n > 19 

現在添加以表達第一個數字(twenty 2,thirty 3,等等)所需的字符數,條件是數字是至少爲2的「十幾歲」分別在處理最後一行。最後,用最後一位數字代替n

sum += digit[n] if n > 0 

在這一點上,n是一個單一的數字或「青少年」,並在其名稱中的字符的digit陣列中的所有預先計算的數量,所以我們添加價值,我們就大功告成了。


有些可能是晦澀的語法特徵在這裏被使用:

  • 多重分配

    在Ruby中,你可以寫之類的語句

    a, b = 3, 5 
    

    賦值給更多比一個變量同時。在這種情況下沒有真正的理由這樣做,除了縮短代碼(雖然可以說不太可讀)。

  • 後綴條件

    條件句的屍體僅1表達式可以寫成在後綴形式。例如:

    puts "hi" if n > 0 
    

    是完全等效於:

    if n > 0 
        puts "hi" 
    end 
    

    再次,這僅用於使代碼短。

  • 三元操作符

    另一種方式來寫一個條件表達式:

    n > 0 ? n : 1 
    

    轉化爲

    if n > 0 
        n 
    else 
        1 
    end 
    

通過 「脫糖」 所有的特殊語法解釋以上(並修復錯誤a程序變成:

digit = [ 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8 ] 
decade = [4, 3, 6, 6, 5, 5, 5, 7, 6, 6] 

puts (1..1000).inject(0) { |sum, n| 
    if n > 999 
    sum += 11 
    n = n % 1000 
    end 

    if n > 99 
    sum += digit[n/100] + 7 
    if n % 100 > 0 
     sum += 3 
    end 
    n = n % 100 
    end 

    if n > 19 
    sum += decade[n/10] 
    n = n % 10 
    end 

    if n > 0 
    sum += digit[n] 
    end 

    sum 
} 
+0

因此,當涉及到第二個if語句時,n的新值用於評估條件。它是否正確。另外我想知道改變n的值並不影響循環,因爲當我想到循環時我想(n = 0; n <= 1000; n ++),但看起來像是因爲在上面的例子中循環並不依賴在n上,它不受影響。 – user1110749 2011-12-22 21:16:28

+0

這裏有一個要點,注入去掉了,並且使用了for-in循環來避免使用塊。 https://gist.github.com/29ee078033a901ae023e – d11wtq 2011-12-22 21:17:19

+0

@ user1110749這不是一個簡單的循環,而是一個'inject'語句。在每次迭代中'n'被分配一個從1到1000的連續值,而塊的返回值被分配給'sum'以用於下一次迭代。所以'sum'是一個「運行總數」,而'n'是從1到1000的數字。不管是否在塊內部修改了'n'都沒關係。 – 2011-12-22 21:25:18