Was looking at this questionthis question (which I initially misunderstood completely), to which Peter Taylor posted a good answera good answer outlining a much better algorithm.
For kicks, I implemented it in Ruby, but I feel like it can be done more cleanly:
def next_greater_permutation(integer)
digits = integer.to_s.chars.map(&:to_i) # get digits
k = digits.each_cons(2).to_a.rindex { |a, b| a < b } # find k
return integer if k.nil? # no k found, return the input unaltered
head, tail = digits[0..k], digits[k+1..-1] # split digits into two arrays
l = tail.rindex { |n| n > head.last } # find l (local to the tail)
head[k], tail[l] = tail[l], head[k] # swap the two values
(head + tail.reverse).join.to_i # glue back together, return
end
(The k and l names are in keeping with the names used in the algorithm; usually I'd use more verbose names.)
It's not super complex or anything, but I just feel like there's a bit too much going on. I'm used to array-manipulation in Ruby being a matter of finding the right methods and chaining them, rather than fiddling with indices. Just feels like I'm missing some obvious shortcut.
To wit, the algorithm (quoted from Wikipedia) is:
- Find the largest index
ksuch thata[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.- Find the largest index
lgreater thanksuch thata[k] < a[l].- Swap the value of
a[k]with that ofa[l].- Reverse the sequence from
a[k + 1]up to and including the final elementa[n].