mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	 3e92b635fb
			
		
	
	
		3e92b635fb
		
	
	
	
	
		
			
			When you change this to true, you may need to add more tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53141 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			103 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
	
		
			2.1 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| # frozen_string_literal: false
 | |
| module AllPairs
 | |
|   module_function
 | |
| 
 | |
|   def make_prime(v)
 | |
|     return 2 if v < 2
 | |
|     ary = [true] * (v*2)
 | |
|     2.upto(Math.sqrt(ary.length).ceil) {|i|
 | |
|       return i if ary[i] && v <= i
 | |
|       (i*2).step(ary.length, i) {|j|
 | |
|         ary[j] = false
 | |
|       }
 | |
|     }
 | |
|     v.upto(ary.length-1) {|i|
 | |
|       return i if ary[i]
 | |
|     }
 | |
|     raise "[bug] prime not found greater than #{v}"
 | |
|   end
 | |
| 
 | |
|   def make_basic_block(prime)
 | |
|     prime.times {|i|
 | |
|       prime.times {|j|
 | |
|         row = [i]
 | |
|         0.upto(prime-1) {|m|
 | |
|           row << (i*m + j) % prime
 | |
|         }
 | |
|         yield row
 | |
|       }
 | |
|     }
 | |
|   end
 | |
| 
 | |
|   def combine_block(tbl1, tbl2)
 | |
|     result = []
 | |
|     tbl2.each {|row|
 | |
|       result << row * tbl1.first.length
 | |
|     }
 | |
|     tbl1.each_with_index {|row, k|
 | |
|       next if k == 0
 | |
|       result << row.map {|i| [i] * tbl2.first.length }.flatten
 | |
|     }
 | |
|     result
 | |
|   end
 | |
| 
 | |
|   def make_large_block(v, prime)
 | |
|     if prime <= v+1
 | |
|       make_basic_block(v) {|row|
 | |
|         yield row
 | |
|       }
 | |
|     else
 | |
|       tbl = []
 | |
|       make_basic_block(v) {|row|
 | |
|         tbl << row
 | |
|       }
 | |
|       tbls = [tbl]
 | |
|       while tbl.first.length ** 2 < prime
 | |
|         tbl = combine_block(tbl, tbl)
 | |
|         tbls << tbl
 | |
|       end
 | |
|       tbl1 = tbls.find {|t| prime <= t.first.length * tbl.first.length }
 | |
|       tbl = combine_block(tbl, tbl1)
 | |
|       tbl.each {|row|
 | |
|         yield row
 | |
|       }
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def each_index(*vs)
 | |
|     n = vs.length
 | |
|     max_v = vs.max
 | |
|     h = {}
 | |
|     make_large_block(max_v, n) {|row|
 | |
|       row = vs.zip(row).map {|v, i| i % v }
 | |
|       next if h[row]
 | |
|       h[row] = true
 | |
|       yield row
 | |
|     }
 | |
|   end
 | |
| 
 | |
|   # generate all pairs test.
 | |
|   def each(*args)
 | |
|     args.map! {|a| a.to_a }
 | |
|     each_index(*args.map {|a| a.length}) {|is|
 | |
|       yield is.zip(args).map {|i, a| a[i] }
 | |
|     }
 | |
|   end
 | |
| 
 | |
|   # generate all combination in cartesian product.  (not all-pairs test)
 | |
|   def exhaustive_each(*args)
 | |
|     args = args.map {|a| a.to_a }
 | |
|     i = 0
 | |
|     while true
 | |
|       n = i
 | |
|       as = []
 | |
|       args.reverse_each {|a|
 | |
|         n, m = n.divmod(a.length)
 | |
|         as.unshift a[m]
 | |
|       }
 | |
|       break if 0 < n
 | |
|       yield as
 | |
|       i += 1
 | |
|     end
 | |
|   end
 | |
| end
 |