permutation 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +6 -0
- data/GPL +0 -0
- data/README.en +0 -0
- data/Rakefile +7 -0
- data/VERSION +1 -1
- data/install.rb +0 -0
- data/lib/permutation.rb +315 -317
- data/lib/permutation/version.rb +1 -1
- data/test/test.rb +0 -0
- metadata +51 -44
data/CHANGES
CHANGED
data/GPL
CHANGED
File without changes
|
data/README.en
CHANGED
File without changes
|
data/Rakefile
CHANGED
@@ -23,6 +23,11 @@ task :test do
|
|
23
23
|
ruby %{-Ilib test/test.rb}
|
24
24
|
end
|
25
25
|
|
26
|
+
desc "Testing library (with coverage)"
|
27
|
+
task :coverage do
|
28
|
+
sh %{rcov -Ilib test/test.rb}
|
29
|
+
end
|
30
|
+
|
26
31
|
spec = Gem::Specification.new do |s|
|
27
32
|
s.name = 'permutation'
|
28
33
|
s.version = PKG_VERSION
|
@@ -66,5 +71,7 @@ EOT
|
|
66
71
|
end
|
67
72
|
end
|
68
73
|
|
74
|
+
CLEAN.include 'doc'
|
75
|
+
|
69
76
|
task :release => [ :clean, :version, :package ]
|
70
77
|
# vim: set et sw=2 ts=2:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.6
|
data/install.rb
CHANGED
File without changes
|
data/lib/permutation.rb
CHANGED
@@ -47,7 +47,7 @@
|
|
47
47
|
# # => [:r, :g, :b]
|
48
48
|
# perm.map { |p| p.project(colors) }
|
49
49
|
# # => [[:r, :g, :b], [:r, :b, :g], [:g, :r, :b], [:g, :b, :r], [:b, :r, :g],
|
50
|
-
# #
|
50
|
+
# # [:b, :g, :r]]
|
51
51
|
# string = "abc"# => "abc"
|
52
52
|
# perm.map { |p| p.project(string) }
|
53
53
|
# # => ["abc", "acb", "bac", "bca", "cab", "cba"]
|
@@ -120,42 +120,42 @@
|
|
120
120
|
#
|
121
121
|
|
122
122
|
class Permutation
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
123
|
+
include Enumerable
|
124
|
+
include Comparable
|
125
|
+
|
126
|
+
# Creates a new Permutation instance of <code>size</code>
|
127
|
+
# (and ranked with <code>rank</code>).
|
128
|
+
def initialize(size, rank = 0)
|
129
|
+
@size, @rank = size, rank
|
130
|
+
@last = factorial(size) - 1
|
131
|
+
end
|
132
|
+
|
133
|
+
# Creates a new Permutation instance from the Array
|
134
|
+
# <code>indices</code>, that should consist of a permutation of Fixnums
|
135
|
+
# in the range of <code>0</code> and <code>indices.size - 1</code>. This is
|
136
|
+
# for example the result of a call to the Permutation#value method.
|
137
|
+
def self.from_value(indices)
|
138
|
+
obj = new(indices.size)
|
139
|
+
obj.instance_eval do
|
140
|
+
self.rank = rank_indices(indices)
|
131
141
|
end
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
# Creates a new Permutation instance from the Array of Arrays
|
146
|
-
# <code>cycles</code>. This is for example the result of a
|
147
|
-
# call to the Permutation#cycles method .
|
148
|
-
def self.from_cycles(cycles, max = 0)
|
149
|
-
indices = Array.new(max)
|
150
|
-
cycles.each do |cycle|
|
151
|
-
cycle.empty? and next
|
152
|
-
for i in 0...cycle.size
|
153
|
-
indices[ cycle[i - 1] ] = cycle[i]
|
154
|
-
end
|
155
|
-
end
|
156
|
-
indices.each_with_index { |r, i| r or indices[i] = i }
|
157
|
-
from_value(indices)
|
142
|
+
obj
|
143
|
+
end
|
144
|
+
|
145
|
+
# Creates a new Permutation instance from the Array of Arrays
|
146
|
+
# <code>cycles</code>. This is for example the result of a
|
147
|
+
# call to the Permutation#cycles method .
|
148
|
+
def self.from_cycles(cycles, max = 0)
|
149
|
+
indices = Array.new(max)
|
150
|
+
cycles.each do |cycle|
|
151
|
+
cycle.empty? and next
|
152
|
+
for i in 0...cycle.size
|
153
|
+
indices[ cycle[i - 1] ] = cycle[i]
|
154
|
+
end
|
158
155
|
end
|
156
|
+
indices.each_with_index { |r, i| r or indices[i] = i }
|
157
|
+
from_value(indices)
|
158
|
+
end
|
159
159
|
|
160
160
|
# A permutation instance of size collection.size is created with
|
161
161
|
# collection as the default Permutation#project data object. A
|
@@ -167,301 +167,299 @@ class Permutation
|
|
167
167
|
perm
|
168
168
|
end
|
169
169
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
klon.rank = r
|
282
|
-
yield klon
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
# Does something similar to Permutation#each. It doesn't create new
|
287
|
-
# instances (less overhead) for every iteration step, but yields to a
|
288
|
-
# modified self instead. This is useful if one only wants to call a
|
289
|
-
# method on the yielded value and work with the result of this call. It's
|
290
|
-
# not a good idea to put the yielded values in a data structure because the
|
291
|
-
# will all reference the same (this!) instance. If you want to do this
|
292
|
-
# use Permutation#each.
|
293
|
-
def each!
|
294
|
-
old_rank = rank
|
295
|
-
0.upto(last) do |r|
|
296
|
-
self.rank = r
|
297
|
-
yield self
|
298
|
-
end
|
299
|
-
self.rank = old_rank
|
300
|
-
end
|
301
|
-
|
302
|
-
# Compares to Permutation instances according to their Permutation#size
|
303
|
-
# and the Permutation#rank.
|
304
|
-
#
|
305
|
-
# The mixed in methods from the Comparable module rely on this method.
|
306
|
-
def <=>(other)
|
307
|
-
size <=> other.size.zero? || rank <=> other.rank
|
308
|
-
end
|
309
|
-
|
310
|
-
# Returns true if this Permutation instance and the other have the same
|
311
|
-
# value, that is both Permutation instances have the same Permutation#size
|
312
|
-
# and the same Permutation#rank.
|
313
|
-
def eql?(other)
|
314
|
-
self.class == other.class && size == other.size && rank == other.rank
|
170
|
+
# Returns the size of this permutation, a Fixnum.
|
171
|
+
attr_reader :size
|
172
|
+
|
173
|
+
# Returns the size of this permutation, a Fixnum in the range
|
174
|
+
# of 0 and Permutation#last.
|
175
|
+
attr_reader :rank
|
176
|
+
|
177
|
+
# Returns the rank of the last ranked Permutation of size
|
178
|
+
# Permutation#size .
|
179
|
+
attr_reader :last
|
180
|
+
|
181
|
+
# Assigns <code>m</code> to the rank attribute of this Permutation
|
182
|
+
# instance. That implies that the indices produced by a call to the
|
183
|
+
# Permutation#value method of this instance is the permutation ranked with
|
184
|
+
# this new <code>rank</code>.
|
185
|
+
def rank=(m)
|
186
|
+
@rank = m % factorial(size)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Returns the indices in the range of 0 to Permutation#size - 1
|
190
|
+
# of this permutation that is ranked with Permutation#rank.
|
191
|
+
#
|
192
|
+
# <b>Example:</b>
|
193
|
+
# perm = Permutation.new(6, 312)
|
194
|
+
# # => #<Permutation:0x6ae34 @last=719, @rank=312, @size=6>
|
195
|
+
# perm.value
|
196
|
+
# # => [2, 4, 0, 1, 3, 5]
|
197
|
+
def value
|
198
|
+
unrank_indices(@rank)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns the projection of this instance's Permutation#value
|
202
|
+
# into the <code>data</code> object that should respond to
|
203
|
+
# the #[] method. If this Permutation inbstance was created
|
204
|
+
# with Permutation.for the collection used to create
|
205
|
+
# it is used as a data object.
|
206
|
+
#
|
207
|
+
# <b>Example:</b>
|
208
|
+
# perm = Permutation.new(6, 312)
|
209
|
+
# # => #<Permutation:0x6ae34 @last=719, @rank=312, @size=6>
|
210
|
+
# perm.project("abcdef")
|
211
|
+
# # => "ceabdf"
|
212
|
+
def project(data = @collection)
|
213
|
+
data or raise ArgumentError, "a collection is required to project"
|
214
|
+
raise ArgumentError, "data size is != #{size}!" if data.size != size
|
215
|
+
projection = data.clone
|
216
|
+
value.each_with_index { |i, j| projection[j] = data[i] }
|
217
|
+
projection
|
218
|
+
end
|
219
|
+
|
220
|
+
# Switches this instances to the next ranked Permutation.
|
221
|
+
# If this was the Permutation#last permutation it wraps around
|
222
|
+
# the first (<code>rank == 0</code>) permutation.
|
223
|
+
def next!
|
224
|
+
@rank += 1
|
225
|
+
@rank = 0 if @rank > last
|
226
|
+
self
|
227
|
+
end
|
228
|
+
|
229
|
+
alias succ! next!
|
230
|
+
|
231
|
+
# Returns the next ranked Permutation instance.
|
232
|
+
# If this instance is the Permutation#last permutation it returns the first
|
233
|
+
# (<code>rank == 0</code>) permutation.
|
234
|
+
def next
|
235
|
+
clone.next!
|
236
|
+
end
|
237
|
+
|
238
|
+
alias succ next
|
239
|
+
|
240
|
+
# Switches this instances to the previously ranked Permutation.
|
241
|
+
# If this was the first permutation it returns the last (<code>rank ==
|
242
|
+
# Permutation#last</code>) permutation.
|
243
|
+
def pred!
|
244
|
+
@rank -= 1
|
245
|
+
@rank = last if @rank < 0
|
246
|
+
self
|
247
|
+
end
|
248
|
+
|
249
|
+
# Returns the previously ranked Permutation. If this was the first
|
250
|
+
# permutation it returns the last (<code>rank == Permutation#last</code>)
|
251
|
+
# permutation.
|
252
|
+
def pred
|
253
|
+
clone.pred!
|
254
|
+
end
|
255
|
+
|
256
|
+
# Switches this Permutation instance to random permutation
|
257
|
+
# of size Permutation#size.
|
258
|
+
def random!
|
259
|
+
new_rank = rand(last + 1).to_i
|
260
|
+
self.rank = new_rank
|
261
|
+
self
|
262
|
+
end
|
263
|
+
|
264
|
+
# Returns a random Permutation instance # of size Permutation#size.
|
265
|
+
def random
|
266
|
+
clone.random!
|
267
|
+
end
|
268
|
+
|
269
|
+
# Iterates over all permutations of size Permutation#size starting with the
|
270
|
+
# first (<code>rank == 0</code>) ranked permutation and ending with the
|
271
|
+
# last (<code>rank == Permutation#last</code>) ranked permutation while
|
272
|
+
# yielding to a freshly created Permutation instance for every iteration
|
273
|
+
# step.
|
274
|
+
#
|
275
|
+
# The mixed in methods from the Enumerable module rely on this method.
|
276
|
+
def each # :yields: perm
|
277
|
+
0.upto(last) do |r|
|
278
|
+
klon = clone
|
279
|
+
klon.rank = r
|
280
|
+
yield klon
|
315
281
|
end
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
282
|
+
end
|
283
|
+
|
284
|
+
# Does something similar to Permutation#each. It doesn't create new
|
285
|
+
# instances (less overhead) for every iteration step, but yields to a
|
286
|
+
# modified self instead. This is useful if one only wants to call a
|
287
|
+
# method on the yielded value and work with the result of this call. It's
|
288
|
+
# not a good idea to put the yielded values in a data structure because the
|
289
|
+
# will all reference the same (this!) instance. If you want to do this
|
290
|
+
# use Permutation#each.
|
291
|
+
def each!
|
292
|
+
old_rank = rank
|
293
|
+
0.upto(last) do |r|
|
294
|
+
self.rank = r
|
295
|
+
yield self
|
322
296
|
end
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
297
|
+
self.rank = old_rank
|
298
|
+
end
|
299
|
+
|
300
|
+
# Compares to Permutation instances according to their Permutation#size
|
301
|
+
# and the Permutation#rank.
|
302
|
+
#
|
303
|
+
# The mixed in methods from the Comparable module rely on this method.
|
304
|
+
def <=>(other)
|
305
|
+
size <=> other.size.zero? || rank <=> other.rank
|
306
|
+
end
|
307
|
+
|
308
|
+
# Returns true if this Permutation instance and the other have the same
|
309
|
+
# value, that is both Permutation instances have the same Permutation#size
|
310
|
+
# and the same Permutation#rank.
|
311
|
+
def eql?(other)
|
312
|
+
self.class == other.class && size == other.size && rank == other.rank
|
313
|
+
end
|
314
|
+
|
315
|
+
alias == eql?
|
316
|
+
|
317
|
+
# Computes a unique hash value for this Permutation instance.
|
318
|
+
def hash
|
319
|
+
size.hash ^ rank.hash
|
320
|
+
end
|
321
|
+
|
322
|
+
# Switchtes this Permutation instance to the inverted permutation.
|
323
|
+
# (See Permutation#compose for an example.)
|
324
|
+
def invert!
|
325
|
+
indices = unrank_indices(rank)
|
326
|
+
inverted = Array.new(size)
|
327
|
+
for i in 0...size
|
328
|
+
inverted[indices[i]] = i
|
334
329
|
end
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
330
|
+
self.rank = rank_indices(inverted)
|
331
|
+
self
|
332
|
+
end
|
333
|
+
|
334
|
+
# Returns the inverted Permutation of this Permutation instance.
|
335
|
+
# (See Permutation#compose for an example.)
|
336
|
+
def invert
|
337
|
+
clone.invert!
|
338
|
+
end
|
339
|
+
|
340
|
+
alias -@ invert
|
341
|
+
|
342
|
+
# Compose this Permutation instance and the other to
|
343
|
+
# a new Permutation. Note that a permutation
|
344
|
+
# composed with it's inverted permutation yields
|
345
|
+
# the identity permutation, the permutation with rank 0.
|
346
|
+
#
|
347
|
+
# <b>Example:</b>
|
348
|
+
# p1 = Permutation.new(5, 42)
|
349
|
+
# # => #<Permutation:0x75370 @last=119, @rank=42, @size=5>
|
350
|
+
# p2 = p1.invert
|
351
|
+
# # => #<Permutation:0x653d0 @last=119, @rank=51, @size=5>
|
352
|
+
# p1.compose(p2)
|
353
|
+
# => #<Permutation:0x639a4 @last=119, @rank=0, @size=5>
|
354
|
+
# Or a little nicer to look at:
|
355
|
+
# p1 * -p1
|
356
|
+
# # => #<Permutation:0x62004 @last=119, @rank=0, @size=5>
|
357
|
+
def compose(other)
|
358
|
+
size == other.size or raise ArgumentError,
|
359
|
+
"permutations of unequal sizes cannot be composed!"
|
360
|
+
indices = self.value
|
361
|
+
composed = other.value.map { |i| indices[i] }
|
362
|
+
klon = clone
|
363
|
+
klon.rank = rank_indices(composed)
|
364
|
+
klon
|
365
|
+
end
|
366
|
+
|
367
|
+
alias * compose
|
368
|
+
|
369
|
+
# Returns the cycles representation of this Permutation instance.
|
370
|
+
# The return value of this method can be used to create a
|
371
|
+
# new Permutation instance with the Permutation.from_cycles method.
|
372
|
+
#
|
373
|
+
# <b>Example:</b>
|
374
|
+
# perm = Permutation.new(7, 23)
|
375
|
+
# # => #<Permutation:0x58541c @last=5039, @rank=23, @size=7>
|
376
|
+
# perm.cycles
|
377
|
+
# # => [[3, 6], [4, 5]]
|
378
|
+
def cycles
|
379
|
+
perm = value
|
380
|
+
result = [[]]
|
381
|
+
seen = {}
|
382
|
+
current = nil
|
383
|
+
until seen == perm.size
|
384
|
+
current or current = perm.find { |x| !seen[x] }
|
385
|
+
break unless current
|
386
|
+
if seen[current]
|
384
387
|
current = nil
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
else
|
392
|
-
seen[current] = true
|
393
|
-
result[-1] << current
|
394
|
-
current = perm[current]
|
395
|
-
end
|
396
|
-
end
|
397
|
-
result.pop
|
398
|
-
result.select { |c| c.size > 1 }.map do |c|
|
399
|
-
min_index = c.index(c.min)
|
400
|
-
c[min_index..-1] + c[0...min_index]
|
401
|
-
end
|
388
|
+
result << []
|
389
|
+
else
|
390
|
+
seen[current] = true
|
391
|
+
result[-1] << current
|
392
|
+
current = perm[current]
|
393
|
+
end
|
402
394
|
end
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
#
|
408
|
-
# A permutation is odd if it can be represented by an odd number of
|
409
|
-
# transpositions (cycles of length 2), or even if it can be represented of
|
410
|
-
# an even number of transpositions.
|
411
|
-
def signum
|
412
|
-
s = 1
|
413
|
-
cycles.each do |c|
|
414
|
-
c.size % 2 == 0 and s *= -1
|
415
|
-
end
|
416
|
-
s
|
395
|
+
result.pop
|
396
|
+
result.select { |c| c.size > 1 }.map do |c|
|
397
|
+
min_index = c.index(c.min)
|
398
|
+
c[min_index..-1] + c[0...min_index]
|
417
399
|
end
|
400
|
+
end
|
401
|
+
|
402
|
+
# Returns the signum of this Permutation instance.
|
403
|
+
# It's -1 if this permutation is odd and 1 if it's
|
404
|
+
# an even permutation.
|
405
|
+
#
|
406
|
+
# A permutation is odd if it can be represented by an odd number of
|
407
|
+
# transpositions (cycles of length 2), or even if it can be represented of
|
408
|
+
# an even number of transpositions.
|
409
|
+
def signum
|
410
|
+
s = 1
|
411
|
+
cycles.each do |c|
|
412
|
+
c.size % 2 == 0 and s *= -1
|
413
|
+
end
|
414
|
+
s
|
415
|
+
end
|
418
416
|
|
419
|
-
|
417
|
+
alias sgn signum
|
420
418
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
419
|
+
# Returns true if this permutation is even, false otherwise.
|
420
|
+
def even?
|
421
|
+
signum == 1
|
422
|
+
end
|
425
423
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
424
|
+
# Returns true if this permutation is odd, false otherwise.
|
425
|
+
def odd?
|
426
|
+
signum == -1
|
427
|
+
end
|
430
428
|
|
431
|
-
|
429
|
+
private
|
432
430
|
|
433
|
-
|
431
|
+
@@fcache = [ 1 ]
|
434
432
|
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
433
|
+
def factorial(n)
|
434
|
+
@@fcache.size.upto(n) { |i| @@fcache[i] = i * @@fcache[i - 1] }
|
435
|
+
@@fcache[n]
|
436
|
+
end
|
439
437
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
end
|
448
|
-
result
|
438
|
+
def rank_indices(p)
|
439
|
+
result = 0
|
440
|
+
for i in 0...size
|
441
|
+
result += p[i] * factorial(size - i - 1)
|
442
|
+
for j in (i + 1)...size
|
443
|
+
p[j] -= 1 if p[j] > p[i]
|
444
|
+
end
|
449
445
|
end
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
446
|
+
result
|
447
|
+
end
|
448
|
+
|
449
|
+
def unrank_indices(m)
|
450
|
+
result = Array.new(size, 0)
|
451
|
+
for i in 0...size
|
452
|
+
f = factorial(i)
|
453
|
+
x = m % (f * (i + 1))
|
454
|
+
m -= x
|
455
|
+
x /= f
|
456
|
+
result[size - i - 1] = x
|
457
|
+
x -= 1
|
458
|
+
for j in (size - i)...size
|
459
|
+
result[j] += 1 if result[j] > x
|
460
|
+
end
|
465
461
|
end
|
462
|
+
result
|
463
|
+
end
|
466
464
|
end
|
467
|
-
|
465
|
+
# vim: set et sw=4 ts=4:
|
data/lib/permutation/version.rb
CHANGED
data/test/test.rb
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,62 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.2
|
3
|
-
specification_version: 1
|
4
2
|
name: permutation
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2007-04-17 00:00:00 +02:00
|
8
|
-
summary: Permutation library in pure Ruby
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: flori@ping.de
|
12
|
-
homepage: http://permutation.rubyforge.org
|
13
|
-
rubyforge_project: permutation
|
14
|
-
description: Library to perform different operations with permutations of sequences (strings, arrays, etc.)
|
15
|
-
autorequire:
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: true
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: 0.1.6
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
7
|
- Florian Frank
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-12-01 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Library to perform different operations with permutations of sequences (strings, arrays, etc.)
|
17
|
+
email: flori@ping.de
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- lib/permutation/version.rb
|
24
|
+
- lib/permutation.rb
|
31
25
|
files:
|
32
|
-
- VERSION
|
33
|
-
- GPL
|
34
|
-
- README.en
|
35
26
|
- install.rb
|
36
|
-
- Rakefile
|
37
|
-
- examples
|
38
27
|
- lib
|
39
|
-
- test
|
40
|
-
- CHANGES
|
41
|
-
- examples/tsp.rb
|
42
|
-
- lib/permutation.rb
|
43
28
|
- lib/permutation
|
44
29
|
- lib/permutation/version.rb
|
30
|
+
- lib/permutation.rb
|
31
|
+
- CHANGES
|
32
|
+
- README.en
|
33
|
+
- VERSION
|
34
|
+
- test
|
45
35
|
- test/test.rb
|
46
|
-
|
47
|
-
-
|
36
|
+
- Rakefile
|
37
|
+
- GPL
|
38
|
+
- examples
|
39
|
+
- examples/tsp.rb
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://permutation.rubyforge.org
|
42
|
+
post_install_message:
|
48
43
|
rdoc_options:
|
49
44
|
- --title
|
50
45
|
- Permutation
|
51
46
|
- --line-numbers
|
52
|
-
|
53
|
-
- lib
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
59
61
|
requirements: []
|
60
62
|
|
61
|
-
|
62
|
-
|
63
|
+
rubyforge_project: permutation
|
64
|
+
rubygems_version: 1.3.1
|
65
|
+
signing_key:
|
66
|
+
specification_version: 2
|
67
|
+
summary: Permutation library in pure Ruby
|
68
|
+
test_files:
|
69
|
+
- test/test.rb
|