Apply PIE to nghttpx
[platform/upstream/nghttp2.git] / third-party / mruby / mrbgems / mruby-array-ext / mrblib / array.rb
1 class Array
2   ##
3   # call-seq:
4   #    ary.uniq!                -> ary or nil
5   #    ary.uniq! { |item| ... } -> ary or nil
6   #
7   # Removes duplicate elements from +self+.
8   # Returns <code>nil</code> if no changes are made (that is, no
9   # duplicates are found).
10   #
11   #    a = [ "a", "a", "b", "b", "c" ]
12   #    a.uniq!   #=> ["a", "b", "c"]
13   #    b = [ "a", "b", "c" ]
14   #    b.uniq!   #=> nil
15   #    c = [["student","sam"], ["student","george"], ["teacher","matz"]]
16   #    c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
17   #
18   def uniq!(&block)
19     hash = {}
20     if block
21       self.each do |val|
22         key = block.call(val)
23         hash[key] = val unless hash.key?(key)
24       end
25       result = hash.values
26     else
27       hash = {}
28       self.each do |val|
29         hash[val] = val
30       end
31       result = hash.keys
32     end
33     if result.size == self.size
34       nil
35     else
36       self.replace(result)
37     end
38   end
39
40   ##
41   # call-seq:
42   #    ary.uniq                -> new_ary
43   #    ary.uniq { |item| ... } -> new_ary
44   #
45   # Returns a new array by removing duplicate values in +self+.
46   #
47   #    a = [ "a", "a", "b", "b", "c" ]
48   #    a.uniq   #=> ["a", "b", "c"]
49   #
50   #    b = [["student","sam"], ["student","george"], ["teacher","matz"]]
51   #    b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
52   #
53   def uniq(&block)
54     ary = self.dup
55     ary.uniq!(&block)
56     ary
57   end
58
59   ##
60   # call-seq:
61   #    ary - other_ary    -> new_ary
62   #
63   # Array Difference---Returns a new array that is a copy of
64   # the original array, removing any items that also appear in
65   # <i>other_ary</i>. (If you need set-like behavior, see the
66   # library class Set.)
67   #
68   #    [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]
69   #
70   def -(elem)
71     raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
72
73     hash = {}
74     array = []
75     idx = 0
76     len = elem.size
77     while idx < len
78       hash[elem[idx]] = true
79       idx += 1
80     end
81     idx = 0
82     len = size
83     while idx < len
84       v = self[idx]
85       array << v unless hash[v]
86       idx += 1
87     end
88     array
89   end
90
91   ##
92   # call-seq:
93   #    ary | other_ary     -> new_ary
94   #
95   # Set Union---Returns a new array by joining this array with
96   # <i>other_ary</i>, removing duplicates.
97   #
98   #    [ "a", "b", "c" ] | [ "c", "d", "a" ]
99   #           #=> [ "a", "b", "c", "d" ]
100   #
101   def |(elem)
102     raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
103
104     ary = self + elem
105     ary.uniq! or ary
106   end
107
108   ##
109   # call-seq:
110   #    ary.union(other_ary,...)  -> new_ary
111   #
112   # Set Union---Returns a new array by joining this array with
113   # <i>other_ary</i>, removing duplicates.
114   #
115   #    ["a", "b", "c"].union(["c", "d", "a"], ["a", "c", "e"])
116   #           #=> ["a", "b", "c", "d", "e"]
117   #
118   def union(*args)
119     ary = self.dup
120     args.each do |x|
121       ary.concat(x)
122       ary.uniq!
123     end
124     ary
125   end
126
127   ##
128   # call-seq:
129   #    ary & other_ary      -> new_ary
130   #
131   # Set Intersection---Returns a new array
132   # containing elements common to the two arrays, with no duplicates.
133   #
134   #    [ 1, 1, 3, 5 ] & [ 1, 2, 3 ]   #=> [ 1, 3 ]
135   #
136   def &(elem)
137     raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
138
139     hash = {}
140     array = []
141     idx = 0
142     len = elem.size
143     while idx < len
144       hash[elem[idx]] = true
145       idx += 1
146     end
147     idx = 0
148     len = size
149     while idx < len
150       v = self[idx]
151       if hash[v]
152         array << v
153         hash.delete v
154       end
155       idx += 1
156     end
157     array
158   end
159
160   ##
161   # call-seq:
162   #    ary.flatten -> new_ary
163   #    ary.flatten(level) -> new_ary
164   #
165   # Returns a new array that is a one-dimensional flattening of this
166   # array (recursively). That is, for every element that is an array,
167   # extract its elements into the new array.  If the optional
168   # <i>level</i> argument determines the level of recursion to flatten.
169   #
170   #    s = [ 1, 2, 3 ]           #=> [1, 2, 3]
171   #    t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
172   #    a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
173   #    a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
174   #    a = [ 1, 2, [3, [4, 5] ] ]
175   #    a.flatten(1)              #=> [1, 2, 3, [4, 5]]
176   #
177   def flatten(depth=nil)
178     res = dup
179     res.flatten! depth
180     res
181   end
182
183   ##
184   # call-seq:
185   #    ary.flatten!        -> ary or nil
186   #    ary.flatten!(level) -> array or nil
187   #
188   # Flattens +self+ in place.
189   # Returns <code>nil</code> if no modifications were made (i.e.,
190   # <i>ary</i> contains no subarrays.)  If the optional <i>level</i>
191   # argument determines the level of recursion to flatten.
192   #
193   #    a = [ 1, 2, [3, [4, 5] ] ]
194   #    a.flatten!   #=> [1, 2, 3, 4, 5]
195   #    a.flatten!   #=> nil
196   #    a            #=> [1, 2, 3, 4, 5]
197   #    a = [ 1, 2, [3, [4, 5] ] ]
198   #    a.flatten!(1) #=> [1, 2, 3, [4, 5]]
199   #
200   def flatten!(depth=nil)
201     modified = false
202     ar = []
203     idx = 0
204     len = size
205     while idx < len
206       e = self[idx]
207       if e.is_a?(Array) && (depth.nil? || depth > 0)
208         ar += e.flatten(depth.nil? ? nil : depth - 1)
209         modified = true
210       else
211         ar << e
212       end
213       idx += 1
214     end
215     if modified
216       self.replace(ar)
217     else
218       nil
219     end
220   end
221
222   ##
223   # call-seq:
224   #    ary.compact     -> new_ary
225   #
226   # Returns a copy of +self+ with all +nil+ elements removed.
227   #
228   #    [ "a", nil, "b", nil, "c", nil ].compact
229   #                      #=> [ "a", "b", "c" ]
230   #
231   def compact
232     result = self.dup
233     result.compact!
234     result
235   end
236
237   ##
238   # call-seq:
239   #    ary.compact!    -> ary  or  nil
240   #
241   # Removes +nil+ elements from the array.
242   # Returns +nil+ if no changes were made, otherwise returns
243   # <i>ary</i>.
244   #
245   #    [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
246   #    [ "a", "b", "c" ].compact!           #=> nil
247   #
248   def compact!
249     result = self.select { |e| !e.nil? }
250     if result.size == self.size
251       nil
252     else
253       self.replace(result)
254     end
255   end
256
257   # for efficiency
258   def reverse_each(&block)
259     return to_enum :reverse_each unless block
260
261     i = self.size - 1
262     while i>=0
263       block.call(self[i])
264       i -= 1
265     end
266     self
267   end
268
269   ##
270   #  call-seq:
271   #     ary.fetch(index)                    -> obj
272   #     ary.fetch(index, default)           -> obj
273   #     ary.fetch(index) { |index| block }  -> obj
274   #
275   #  Tries to return the element at position +index+, but throws an IndexError
276   #  exception if the referenced +index+ lies outside of the array bounds.  This
277   #  error can be prevented by supplying a second argument, which will act as a
278   #  +default+ value.
279   #
280   #  Alternatively, if a block is given it will only be executed when an
281   #  invalid +index+ is referenced.
282   #
283   #  Negative values of +index+ count from the end of the array.
284   #
285   #     a = [ 11, 22, 33, 44 ]
286   #     a.fetch(1)               #=> 22
287   #     a.fetch(-1)              #=> 44
288   #     a.fetch(4, 'cat')        #=> "cat"
289   #     a.fetch(100) { |i| puts "#{i} is out of bounds" }
290   #                              #=> "100 is out of bounds"
291   #
292
293   def fetch(n, ifnone=NONE, &block)
294     warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block
295
296     idx = n
297     if idx < 0
298       idx += size
299     end
300     if idx < 0 || size <= idx
301       return block.call(n) if block
302       if ifnone == NONE
303         raise IndexError, "index #{n} outside of array bounds: #{-size}...#{size}"
304       end
305       return ifnone
306     end
307     self[idx]
308   end
309
310   ##
311   #  call-seq:
312   #     ary.fill(obj)                                 -> ary
313   #     ary.fill(obj, start [, length])               -> ary
314   #     ary.fill(obj, range )                         -> ary
315   #     ary.fill { |index| block }                    -> ary
316   #     ary.fill(start [, length] ) { |index| block } -> ary
317   #     ary.fill(range) { |index| block }             -> ary
318   #
319   #  The first three forms set the selected elements of +self+ (which
320   #  may be the entire array) to +obj+.
321   #
322   #  A +start+ of +nil+ is equivalent to zero.
323   #
324   #  A +length+ of +nil+ is equivalent to the length of the array.
325   #
326   #  The last three forms fill the array with the value of the given block,
327   #  which is passed the absolute index of each element to be filled.
328   #
329   #  Negative values of +start+ count from the end of the array, where +-1+ is
330   #  the last element.
331   #
332   #     a = [ "a", "b", "c", "d" ]
333   #     a.fill("x")              #=> ["x", "x", "x", "x"]
334   #     a.fill("w", -1)          #=> ["x", "x", "x", "w"]
335   #     a.fill("z", 2, 2)        #=> ["x", "x", "z", "z"]
336   #     a.fill("y", 0..1)        #=> ["y", "y", "z", "z"]
337   #     a.fill { |i| i*i }       #=> [0, 1, 4, 9]
338   #     a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]
339   #     a.fill(1, 2) { |i| i+1 } #=> [0, 2, 3, 27]
340   #     a.fill(0..1) { |i| i+1 } #=> [1, 2, 3, 27]
341   #
342
343   def fill(arg0=nil, arg1=nil, arg2=nil, &block)
344     if arg0.nil? && arg1.nil? && arg2.nil? && !block
345       raise ArgumentError, "wrong number of arguments (0 for 1..3)"
346     end
347
348     beg = len = 0
349     ary = []
350     if block
351       if arg0.nil? && arg1.nil? && arg2.nil?
352         # ary.fill { |index| block }                    -> ary
353         beg = 0
354         len = self.size
355       elsif !arg0.nil? && arg0.kind_of?(Range)
356         # ary.fill(range) { |index| block }             -> ary
357         beg = arg0.begin
358         beg += self.size if beg < 0
359         len = arg0.end
360         len += self.size if len < 0
361         len += 1 unless arg0.exclude_end?
362       elsif !arg0.nil?
363         # ary.fill(start [, length] ) { |index| block } -> ary
364         beg = arg0
365         beg += self.size if beg < 0
366         if arg1.nil?
367           len = self.size
368         else
369           len = arg0 + arg1
370         end
371       end
372     else
373       if !arg0.nil? && arg1.nil? && arg2.nil?
374         # ary.fill(obj)                                 -> ary
375         beg = 0
376         len = self.size
377       elsif !arg0.nil? && !arg1.nil? && arg1.kind_of?(Range)
378         # ary.fill(obj, range )                         -> ary
379         beg = arg1.begin
380         beg += self.size if beg < 0
381         len = arg1.end
382         len += self.size if len < 0
383         len += 1 unless arg1.exclude_end?
384       elsif !arg0.nil? && !arg1.nil?
385         # ary.fill(obj, start [, length])               -> ary
386         beg = arg1
387         beg += self.size if beg < 0
388         if arg2.nil?
389           len = self.size
390         else
391           len = beg + arg2
392         end
393       end
394     end
395
396     i = beg
397     if block
398       while i < len
399         self[i] = block.call(i)
400         i += 1
401       end
402     else
403       while i < len
404         self[i] = arg0
405         i += 1
406       end
407     end
408     self
409   end
410
411   ##
412   #  call-seq:
413   #     ary.rotate(count=1)    -> new_ary
414   #
415   #  Returns a new array by rotating +self+ so that the element at +count+ is
416   #  the first element of the new array.
417   #
418   #  If +count+ is negative then it rotates in the opposite direction, starting
419   #  from the end of +self+ where +-1+ is the last element.
420   #
421   #     a = [ "a", "b", "c", "d" ]
422   #     a.rotate         #=> ["b", "c", "d", "a"]
423   #     a                #=> ["a", "b", "c", "d"]
424   #     a.rotate(2)      #=> ["c", "d", "a", "b"]
425   #     a.rotate(-3)     #=> ["b", "c", "d", "a"]
426
427   def rotate(count=1)
428     ary = []
429     len = self.length
430
431     if len > 0
432       idx = (count < 0) ? (len - (~count % len) - 1) : (count % len) # rotate count
433       len.times do
434         ary << self[idx]
435         idx += 1
436         idx = 0 if idx > len-1
437       end
438     end
439     ary
440   end
441
442   ##
443   #  call-seq:
444   #     ary.rotate!(count=1)   -> ary
445   #
446   #  Rotates +self+ in place so that the element at +count+ comes first, and
447   #  returns +self+.
448   #
449   #  If +count+ is negative then it rotates in the opposite direction, starting
450   #  from the end of the array where +-1+ is the last element.
451   #
452   #     a = [ "a", "b", "c", "d" ]
453   #     a.rotate!        #=> ["b", "c", "d", "a"]
454   #     a                #=> ["b", "c", "d", "a"]
455   #     a.rotate!(2)     #=> ["d", "a", "b", "c"]
456   #     a.rotate!(-3)    #=> ["a", "b", "c", "d"]
457
458   def rotate!(count=1)
459     self.replace(self.rotate(count))
460   end
461
462   ##
463   #  call-seq:
464   #     ary.delete_if { |item| block }  -> ary
465   #     ary.delete_if                   -> Enumerator
466   #
467   #  Deletes every element of +self+ for which block evaluates to +true+.
468   #
469   #  The array is changed instantly every time the block is called, not after
470   #  the iteration is over.
471   #
472   #  See also Array#reject!
473   #
474   #  If no block is given, an Enumerator is returned instead.
475   #
476   #     scores = [ 97, 42, 75 ]
477   #     scores.delete_if {|score| score < 80 }   #=> [97]
478
479   def delete_if(&block)
480     return to_enum :delete_if unless block
481
482     idx = 0
483     while idx < self.size do
484       if block.call(self[idx])
485         self.delete_at(idx)
486       else
487         idx += 1
488       end
489     end
490     self
491   end
492
493   ##
494   #  call-seq:
495   #     ary.reject! { |item| block }  -> ary or nil
496   #     ary.reject!                   -> Enumerator
497   #
498   #  Equivalent to Array#delete_if, deleting elements from +self+ for which the
499   #  block evaluates to +true+, but returns +nil+ if no changes were made.
500   #
501   #  The array is changed instantly every time the block is called, not after
502   #  the iteration is over.
503   #
504   #  See also Enumerable#reject and Array#delete_if.
505   #
506   #  If no block is given, an Enumerator is returned instead.
507
508   def reject!(&block)
509     return to_enum :reject! unless block
510
511     len = self.size
512     idx = 0
513     while idx < self.size do
514       if block.call(self[idx])
515         self.delete_at(idx)
516       else
517         idx += 1
518       end
519     end
520     if self.size == len
521       nil
522     else
523       self
524     end
525   end
526
527   ##
528   #  call-seq:
529   #     ary.insert(index, obj...)  -> ary
530   #
531   #  Inserts the given values before the element with the given +index+.
532   #
533   #  Negative indices count backwards from the end of the array, where +-1+ is
534   #  the last element.
535   #
536   #     a = %w{ a b c d }
537   #     a.insert(2, 99)         #=> ["a", "b", 99, "c", "d"]
538   #     a.insert(-2, 1, 2, 3)   #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
539
540   def insert(idx, *args)
541     idx += self.size + 1 if idx < 0
542     self[idx, 0] = args
543     self
544   end
545
546   ##
547   #  call-seq:
548   #     ary.bsearch {|x| block }  -> elem
549   #
550   #  By using binary search, finds a value from this array which meets
551   #  the given condition in O(log n) where n is the size of the array.
552   #
553   #  You can use this method in two use cases: a find-minimum mode and
554   #  a find-any mode.  In either case, the elements of the array must be
555   #  monotone (or sorted) with respect to the block.
556   #
557   #  In find-minimum mode (this is a good choice for typical use case),
558   #  the block must return true or false, and there must be an index i
559   #  (0 <= i <= ary.size) so that:
560   #
561   #  - the block returns false for any element whose index is less than
562   #    i, and
563   #  - the block returns true for any element whose index is greater
564   #    than or equal to i.
565   #
566   #  This method returns the i-th element.  If i is equal to ary.size,
567   #  it returns nil.
568   #
569   #     ary = [0, 4, 7, 10, 12]
570   #     ary.bsearch {|x| x >=   4 } #=> 4
571   #     ary.bsearch {|x| x >=   6 } #=> 7
572   #     ary.bsearch {|x| x >=  -1 } #=> 0
573   #     ary.bsearch {|x| x >= 100 } #=> nil
574   #
575   #  In find-any mode (this behaves like libc's bsearch(3)), the block
576   #  must return a number, and there must be two indices i and j
577   #  (0 <= i <= j <= ary.size) so that:
578   #
579   #  - the block returns a positive number for ary[k] if 0 <= k < i,
580   #  - the block returns zero for ary[k] if i <= k < j, and
581   #  - the block returns a negative number for ary[k] if
582   #    j <= k < ary.size.
583   #
584   #  Under this condition, this method returns any element whose index
585   #  is within i...j.  If i is equal to j (i.e., there is no element
586   #  that satisfies the block), this method returns nil.
587   #
588   #     ary = [0, 4, 7, 10, 12]
589   #     # try to find v such that 4 <= v < 8
590   #     ary.bsearch {|x| 1 - (x / 4).truncate } #=> 4 or 7
591   #     # try to find v such that 8 <= v < 10
592   #     ary.bsearch {|x| 4 - (x / 2).truncate } #=> nil
593   #
594   #  You must not mix the two modes at a time; the block must always
595   #  return either true/false, or always return a number.  It is
596   #  undefined which value is actually picked up at each iteration.
597
598   def bsearch(&block)
599     return to_enum :bsearch unless block
600
601     if idx = bsearch_index(&block)
602       self[idx]
603     else
604       nil
605     end
606   end
607
608   ##
609   #  call-seq:
610   #     ary.bsearch_index {|x| block }  -> int or nil
611   #
612   #  By using binary search, finds an index of a value from this array which
613   #  meets the given condition in O(log n) where n is the size of the array.
614   #
615   #  It supports two modes, depending on the nature of the block and they are
616   #  exactly the same as in the case of #bsearch method with the only difference
617   #  being that this method returns the index of the element instead of the
618   #  element itself. For more details consult the documentation for #bsearch.
619
620   def bsearch_index(&block)
621     return to_enum :bsearch_index unless block
622
623     low = 0
624     high = size
625     satisfied = false
626
627     while low < high
628       mid = ((low+high)/2).truncate
629       res = block.call self[mid]
630
631       case res
632       when 0 # find-any mode: Found!
633         return mid
634       when Numeric # find-any mode: Continue...
635         in_lower_half = res < 0
636       when true # find-min mode
637         in_lower_half = true
638         satisfied = true
639       when false, nil # find-min mode
640         in_lower_half = false
641       else
642         raise TypeError, 'invalid block result (must be numeric, true, false or nil)'
643       end
644
645       if in_lower_half
646         high = mid
647       else
648         low = mid + 1
649       end
650     end
651
652     satisfied ? low : nil
653   end
654
655   ##
656   #  call-seq:
657   #     ary.delete_if { |item| block }  -> ary
658   #     ary.delete_if                   -> Enumerator
659   #
660   #  Deletes every element of +self+ for which block evaluates to +true+.
661   #
662   #  The array is changed instantly every time the block is called, not after
663   #  the iteration is over.
664   #
665   #  See also Array#reject!
666   #
667   #  If no block is given, an Enumerator is returned instead.
668   #
669   #     scores = [ 97, 42, 75 ]
670   #     scores.delete_if {|score| score < 80 }   #=> [97]
671
672   def delete_if(&block)
673     return to_enum :delete_if unless block
674
675     idx = 0
676     while idx < self.size do
677       if block.call(self[idx])
678         self.delete_at(idx)
679       else
680         idx += 1
681       end
682     end
683     self
684   end
685
686   ##
687   #  call-seq:
688   #     ary.keep_if { |item| block } -> ary
689   #     ary.keep_if                  -> Enumerator
690   #
691   #  Deletes every element of +self+ for which the given block evaluates to
692   #  +false+.
693   #
694   #  See also Array#select!
695   #
696   #  If no block is given, an Enumerator is returned instead.
697   #
698   #     a = [1, 2, 3, 4, 5]
699   #     a.keep_if { |val| val > 3 } #=> [4, 5]
700
701   def keep_if(&block)
702     return to_enum :keep_if unless block
703
704     idx = 0
705     len = self.size
706     while idx < self.size do
707       if block.call(self[idx])
708         idx += 1
709       else
710         self.delete_at(idx)
711       end
712     end
713     self
714   end
715
716   ##
717   #  call-seq:
718   #     ary.select!  {|item| block } -> ary or nil
719   #     ary.select!                  -> Enumerator
720   #
721   #  Invokes the given block passing in successive elements from +self+,
722   #  deleting elements for which the block returns a +false+ value.
723   #
724   #  If changes were made, it will return +self+, otherwise it returns +nil+.
725   #
726   #  See also Array#keep_if
727   #
728   #  If no block is given, an Enumerator is returned instead.
729
730   def select!(&block)
731     return to_enum :select! unless block
732
733     result = []
734     idx = 0
735     len = size
736     while idx < len
737       elem = self[idx]
738       result << elem if block.call(elem)
739       idx += 1
740     end
741     return nil if len == result.size
742     self.replace(result)
743   end
744
745   ##
746   #  call-seq:
747   #     ary.index(val)            -> int or nil
748   #     ary.index {|item| block } ->  int or nil
749   #
750   #  Returns the _index_ of the first object in +ary+ such that the object is
751   #  <code>==</code> to +obj+.
752   #
753   #  If a block is given instead of an argument, returns the _index_ of the
754   #  first object for which the block returns +true+.  Returns +nil+ if no
755   #  match is found.
756   #
757   # ISO 15.2.12.5.14
758   def index(val=NONE, &block)
759     return to_enum(:find_index, val) if !block && val == NONE
760
761     if block
762       idx = 0
763       len = size
764       while idx < len
765         return idx if block.call self[idx]
766         idx += 1
767       end
768     else
769       return self.__ary_index(val)
770     end
771     nil
772   end
773
774   ##
775   # call-seq:
776   #   ary.dig(idx, ...)                 -> object
777   #
778   # Extracts the nested value specified by the sequence of <i>idx</i>
779   # objects by calling +dig+ at each step, returning +nil+ if any
780   # intermediate step is +nil+.
781   #
782   def dig(idx,*args)
783     n = self[idx]
784     if args.size > 0
785       n&.dig(*args)
786     else
787       n
788     end
789   end
790
791   ##
792   # call-seq:
793   #    ary.permutation { |p| block }          -> ary
794   #    ary.permutation                        -> Enumerator
795   #    ary.permutation(n) { |p| block }       -> ary
796   #    ary.permutation(n)                     -> Enumerator
797   #
798   # When invoked with a block, yield all permutations of length +n+ of the
799   # elements of the array, then return the array itself.
800   #
801   # If +n+ is not specified, yield all permutations of all elements.
802   #
803   # The implementation makes no guarantees about the order in which the
804   # permutations are yielded.
805   #
806   # If no block is given, an Enumerator is returned instead.
807   #
808   # Examples:
809   #
810   #  a = [1, 2, 3]
811   #  a.permutation.to_a    #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
812   #  a.permutation(1).to_a #=> [[1],[2],[3]]
813   #  a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
814   #  a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
815   #  a.permutation(0).to_a #=> [[]] # one permutation of length 0
816   #  a.permutation(4).to_a #=> []   # no permutations of length 4
817   def permutation(n=self.size, &block)
818     size = self.size
819     return to_enum(:permutation, n) unless block
820     return if n > size
821     if n == 0
822        yield []
823     else
824       i = 0
825       while i<size
826         result = [self[i]]
827         if n-1 > 0
828           ary = self[0...i] + self[i+1..-1]
829           ary.permutation(n-1) do |c|
830             yield result + c
831           end
832         else
833           yield result
834         end
835         i += 1
836       end
837     end
838   end
839
840   ##
841   # call-seq:
842   #    ary.combination(n) { |c| block }    -> ary
843   #    ary.combination(n)                  -> Enumerator
844   #
845   # When invoked with a block, yields all combinations of length +n+ of elements
846   # from the array and then returns the array itself.
847   #
848   # The implementation makes no guarantees about the order in which the
849   # combinations are yielded.
850   #
851   # If no block is given, an Enumerator is returned instead.
852   #
853   # Examples:
854   #
855   #    a = [1, 2, 3, 4]
856   #    a.combination(1).to_a  #=> [[1],[2],[3],[4]]
857   #    a.combination(2).to_a  #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
858   #    a.combination(3).to_a  #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
859   #    a.combination(4).to_a  #=> [[1,2,3,4]]
860   #    a.combination(0).to_a  #=> [[]] # one combination of length 0
861   #    a.combination(5).to_a  #=> []   # no combinations of length 5
862
863   def combination(n, &block)
864     size = self.size
865     return to_enum(:combination, n) unless block
866     return if n > size
867     if n == 0
868        yield []
869     elsif n == 1
870       i = 0
871       while i<size
872         yield [self[i]]
873         i += 1
874       end
875     else
876       i = 0
877       while i<size
878         result = [self[i]]
879         self[i+1..-1].combination(n-1) do |c|
880           yield result + c
881         end
882         i += 1
883       end
884     end
885   end
886
887   ##
888   # call-seq:
889   #    ary.transpose -> new_ary
890   #
891   # Assumes that self is an array of arrays and transposes the rows and columns.
892   #
893   # If the length of the subarrays don't match, an IndexError is raised.
894   #
895   # Examples:
896   #
897   #    a = [[1,2], [3,4], [5,6]]
898   #    a.transpose   #=> [[1, 3, 5], [2, 4, 6]]
899
900   def transpose
901     return [] if empty?
902
903     column_count = nil
904     self.each do |row|
905       raise TypeError unless row.is_a?(Array)
906       column_count ||= row.count
907       raise IndexError, 'element size differs' unless column_count == row.count
908     end
909
910     Array.new(column_count) do |column_index|
911       self.map { |row| row[column_index] }
912     end
913   end
914
915   ##
916   #  call-seq:
917   #    ary.to_h                ->   Hash
918   #    ary.to_h{|item| ... }   ->   Hash
919   #
920   # Returns the result of interpreting <i>aray</i> as an array of
921   # <tt>[key, value]</tt> pairs. If a block is given, it should
922   # return <tt>[key, value]</tt> pairs to construct a hash.
923   #
924   #     [[:foo, :bar], [1, 2]].to_h
925   #       # => {:foo => :bar, 1 => 2}
926   #     [1, 2].to_h{|x| [x, x*2]}
927   #       # => {1 => 2, 2 => 4}
928   #
929   def to_h(&blk)
930     h = {}
931     self.each do |v|
932       v = blk.call(v) if blk
933       raise TypeError, "wrong element type #{v.class}" unless Array === v
934       raise ArgumentError, "wrong array length (expected 2, was #{v.length})" unless v.length == 2
935       h[v[0]] = v[1]
936     end
937     h
938   end
939 end