Was looking at this question this question (which I initially misunderstood completely), to which Peter Taylor posted a good answer a 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
k
such thata[k] < a[k + 1]
. If no such index exists, the permutation is the last permutation.- Find the largest index
l
greater thank
such 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]
.
Was looking at this question (which I initially misunderstood completely), to which Peter Taylor posted a 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
k
such thata[k] < a[k + 1]
. If no such index exists, the permutation is the last permutation.- Find the largest index
l
greater thank
such 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]
.
Was looking at this question (which I initially misunderstood completely), to which Peter Taylor posted a 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
k
such thata[k] < a[k + 1]
. If no such index exists, the permutation is the last permutation.- Find the largest index
l
greater thank
such 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]
.
Was looking at this question (which I initially misunderstood completely), to which Peter Taylor posted a 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 rightsright 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
k
such thata[k] < a[k + 1]
. If no such index exists, the permutation is the last permutation.- Find the largest index
l
greater thank
such 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]
.
Was looking at this question (which I initially misunderstood completely), to which Peter Taylor posted a 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 rights 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
k
such thata[k] < a[k + 1]
. If no such index exists, the permutation is the last permutation.- Find the largest index
l
greater thank
such 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]
.
Was looking at this question (which I initially misunderstood completely), to which Peter Taylor posted a 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
k
such thata[k] < a[k + 1]
. If no such index exists, the permutation is the last permutation.- Find the largest index
l
greater thank
such 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]
.
Next, greater permutation of digits of a number
Was looking at this question (which I initially misunderstood completely), to which Peter Taylor posted a 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 rights 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
k
such thata[k] < a[k + 1]
. If no such index exists, the permutation is the last permutation.- Find the largest index
l
greater thank
such 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]
.