Let एक सीमा हो full_range
और ranges
पर्वतमाला की एक सरणी, का प्रतिनिधित्व क्या प्रश्नकर्ता period
और incidents
क्रमश करार दिया हो। मैंने माना है कि सभी श्रेणियों में निहित तत्व किसी ऑब्जेक्ट्स हो सकते हैं, बशर्ते उन्हें तुलनात्मक वर्ग 'विधि <=>
से तुलना की जा सके और यह कि मॉड्यूल Comparableinclude
डी रहा है।
कोड
def uncovered_ranges(full_range, ranges)
ucrs = [full_range]
ranges.each do |r|
ucrs = ucrs.flat_map do |ucr|
if ucr.first >= r.last || ucr.last <= r.first
ucr
elsif r.first <= ucr.first && r.last >= ucr.last
nil
elsif r.first <= ucr.first && r.last < ucr.last
r.last..ucr.last
elsif r.first > ucr.first && r.last >= ucr.last
ucr.first..r.first
else
[ucr.first..r.first, r.last..ucr.last]
end
end.compact
end
ucrs
end
उदाहरण
full_range = 1..20
ranges = [3..4, 6..8, 10..12, 8..14, 16..17, 20..20]
uncovered_ranges(full_range, ranges)
#=> [1..3, 4..6, 14..16, 17..20]
require 'time'
full_range = Time.parse('8:00am')..Time.parse('8:00pm')
#=> 2016-12-22 08:00:00 -0800..2016-12-22 20:00:00 -0800
ranges = [
Time.parse('7:00am')..Time.parse('9:00am'),
Time.parse('1:00pm')..Time.parse('3:00pm'),
Time.parse('1:30pm')..Time.parse('3:30pm'),
Time.parse('7:00pm')..Time.parse('9:00pm'),
]
#=> [2016-12-22 07:00:00 -0800..2016-12-22 09:00:00 -0800,
# 2016-12-22 13:00:00 -0800..2016-12-22 15:00:00 -0800,
# 2016-12-22 13:30:00 -0800..2016-12-22 15:30:00 -0800,
# 2016-12-22 19:00:00 -0800..2016-12-22 21:00:00 -0800]
uncovered_ranges(full_range, ranges)
#=> [2016-12-22 09:00:00 -0800..2016-12-22 13:00:00 -0800,
# 2016-12-22 15:30:00 -0800..2016-12-22 19:00:00 -0800]
स्पष्टीकरण
शायद मुझे समझाने के लिए क्या हो रहा है के लिए सबसे आसान और सबसे के माध्यम से जिस तरह से कुछ puts
डालने के लिए हैबयान और ऊपर दिए गए पहले उदाहरण के लिए कोड चलाएं।
def uncovered_ranges(full_range, ranges)
ucrs = [full_range]
puts "ucrs initially=#{ucrs}"
ranges.each do |r|
puts "\ncovering range r=#{r}"
ucrs = ucrs.flat_map do |ucr|
puts " range uncovered so far ucr=#{ucr}"
if ucr.first >= r.last || ucr.last <= r.first
puts " in if #1, returning #{ucr}"
ucr
elsif r.first <= ucr.first && r.last >= ucr.last
puts " in if #2, returning nil"
nil
elsif r.first <= ucr.first && r.last < ucr.last
puts " in if #3, returning #{r.last..ucr.last}"
r.last..ucr.last
elsif r.first > ucr.first && r.last >= ucr.last
puts " in if #4, returning #{ucr.first..r.first}"
ucr.first..r.first
else
puts " in else, returning #{[ucr.first..r.first, r.last..ucr.last]}"
[ucr.first..r.first, r.last..ucr.last]
end
end.tap { |u| puts "ucrs after processing range #{r}=#{u}" }.
compact.
tap { |u| puts "ucrs after compact=#{u}" }
end
ucrs
end
uncovered_ranges 1..20, [3..4, 6..8, 10..12, 8..14, 16..17, 20..20]
निम्नलिखित प्रिंट करता है।
ucrs initially=[1..20]
covering range r=3..4
range uncovered so far ucr=1..20
in else, returning [1..3, 4..20]
ucrs after processing range 3..4=[1..3, 4..20]
ucrs after compact=[1..3, 4..20]
covering range r=6..8
range uncovered so far ucr=1..3
in if #1, returning 1..3
range uncovered so far ucr=4..20
in else, returning [4..6, 8..20]
ucrs after processing range 6..8=[1..3, 4..6, 8..20]
ucrs after compact=[1..3, 4..6, 8..20]
covering range r=10..12
range uncovered so far ucr=1..3
in if #1, returning 1..3
range uncovered so far ucr=4..6
in if #1, returning 4..6
range uncovered so far ucr=8..20
in else, returning [8..10, 12..20]
ucrs after processing range 10..12=[1..3, 4..6, 8..10, 12..20]
ucrs after compact=[1..3, 4..6, 8..10, 12..20]
covering range r=8..14
range uncovered so far ucr=1..3
in if #1, returning 1..3
range uncovered so far ucr=4..6
in if #1, returning 4..6
range uncovered so far ucr=8..10
in if #2, returning nil
range uncovered so far ucr=12..20
in if #3, returning 14..20
ucrs after processing range 8..14=[1..3, 4..6, nil, 14..20]
ucrs after compact=[1..3, 4..6, 14..20]
covering range r=16..17
range uncovered so far ucr=1..3
in if #1, returning 1..3
range uncovered so far ucr=4..6
in if #1, returning 4..6
range uncovered so far ucr=14..20
in else, returning [14..16, 17..20]
ucrs after processing range 16..17=[1..3, 4..6, 14..16, 17..20]
ucrs after compact=[1..3, 4..6, 14..16, 17..20]
covering range r=20..20
range uncovered so far ucr=1..3
in if #1, returning 1..3
range uncovered so far ucr=4..6
in if #1, returning 4..6
range uncovered so far ucr=14..16
in if #1, returning 14..16
range uncovered so far ucr=17..20
in if #1, returning 17..20
ucrs after processing range 20..20=[1..3, 4..6, 14..16, 17..20]
ucrs after compact=[1..3, 4..6, 14..16, 17..20]
#=> [1..3, 4..6, 14..16, 17..20]
यदि यह एक व्यावहारिक अनुप्रयोग है और आप PostgreSQL का उपयोग कर रहे हैं, तो आप [तारीख गणित कार्यक्षमता] (https://www.postgresql.org उपयोग करने पर विचार करना चाहिए /docs/9.1/static/functions-datetime.html) अपने एप्लिकेशन तर्क के अंदर संभालने के बजाय SQL क्वेरी के माध्यम से। – coreyward
यदि आप इसे पूरी तरह से एल्गोरिदमिक विकास दृष्टिकोण से देख रहे हैं, [इस प्रश्न/उत्तर को आपको कब्ज के लिए कुछ चारा देना चाहिए] (http://stackoverflow.com/questions/1193477/fast-algorithm-to-quickly-find -इस दूरी एक नंबर अंतर्गत आता है करने के लिए में एक सेट-ऑफ-द पर्वतमाला? RQ = 1)। – coreyward
@coreyward दुर्भाग्य से डेटा SQL डेटाबेस में संग्रहीत नहीं है। मैं वास्तव में स्पष्ट नहीं हूं कि लिंक पर आधारित एसक्यूएल संस्करण आसान होगा (अगर मैं पहले पीएसक्यूएल में आयात करना चाहता था)। – Stussa