2012-05-23 12 views
11

पहले परियोजना यूलर सवाल कर रही है: 1 और 1000 के बीच 3 और 5 के गुणकों संक्षेप में, मैं इस (बहुत सरल)रूबी ब्लॉक में सशर्त के साथ इंजेक्ट?

sum = 0 
1.upto(999) { |i| sum += i if 0 == i%3 || 0 == i%5 } 
sum 

के साथ आया था, लेकिन मैंने सोचा था कि यह काम करेगा, लेकिन ऐसा नहीं होता, कर सकते हैं कोई मुझे दिखाता है कि मैं क्या गलत कर रहा हूं, या यह क्यों काम नहीं करता है?

1.upto(999).inject(0) { |sum, i| sum + i if 0 == i%3 || 0 == i%5 } 

धन्यवाद!

उत्तर

22

inject ब्लॉक के परिणाम को अगले पुनरावृत्ति के रूप में अगले पुनरावृत्ति के माध्यम से पास करता है। आपका ब्लॉक nil लौटाएगा जब आपका if कथन गलत है, जिसे sum के रूप में वापस भेज दिया जाता है।

सही जवाब पाने के लिए, ब्लॉक वर्तमान राशि लौटानी चाहिए जब यह बात गलत है:

1.upto(999).inject(0) { |sum, i| (0 == i%3 || 0 == i%5) ? sum + i : sum } 
2
1.upto(999).inject(0) { |sum, i| sum += i if 0 == i%3 || 0 == i%5; sum } 

भी काम करेंगे (ध्यान दें +=)।

+0

alt उत्तर के लिए धन्यवाद। यह मेरे शुरुआती सेटअप के करीब है और इसलिए मैं इसे इस तरह से कर सकता हूं (मेरे लिए अधिक पठनीय), मैंने त्रुटि के स्पष्टीकरण के कारण पहला जवाब स्वीकार किया - 'आह!' मुझे पल – Tonys

3

पूरक उत्तर: यदि आप यूलर समस्याओं से निपटने वाले हैं तो आपको अपने पुन: प्रयोज्य कोड का विस्तार करना शुरू करना चाहिए। इस मामले में, पहले विस्तार Enumerable#sum होगा:

module Enumerable 
    def sum 
    inject(0, :+) 
    end 
end 

और अब आप एक समाधान है कि summatory की हालत को अलग करती है लिख सकते हैं (आप इसे जोर से पढ़ सकते हैं और यह समझ में आता है, कि कार्यात्मक/कथात्मक की खासियत है शैली):

1.upto(999).select { |x| x % 3 == 0 || x % 5 == 0 }.sum 

तुम भी यह एक कदम आगे धक्का और Fixnum#divisible_by? बना सकते हैं ताकि आप लिख सकते हैं:

1.upto(999).select { |x| x.divisible_by?(3) || x.divisible_by?(5) }.sum 

अधिक: यहाँ यह है कोई समस्या नहीं, लेकिन बाद में सख्त कार्यान्वयन (सरणी का उपयोग करने वाले) पर बहुत अधिक स्मृति की आवश्यकता होगी। laziness साथ तो प्रयास करें:

require 'lazy' 
1.upto(999).lazy.select { |x| x % 3 == 0 || x % 5 == 0 }.sum 
+0

मदद मिली यह बहुत अच्छी जानकारी है। मैं इसे कुछ प्रश्नों के रूप में पालन करने जा रहा हूं और मैं सलाह की उपयोगिता देखता हूं। धन्यवाद! – Tonys

2

या, & proc जो स्वयं के पते का उपयोग करें।

(1..999).select{|x| x%3==0||x%5==0}.inject &:+ 
1

(1..999).to_a.keep_if{|d| d%3 == 0 || d%5 == 0}.reduce(:+) पूर्णता के लिए।

संबंधित मुद्दे