Skip to main content
Code Review

Return to Question

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

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:

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l greater than k such that a[k] < a[l].
  3. Swap the value of a[k] with that of a[l].
  4. Reverse the sequence from a[k + 1] up to and including the final element a[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:

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l greater than k such that a[k] < a[l].
  3. Swap the value of a[k] with that of a[l].
  4. Reverse the sequence from a[k + 1] up to and including the final element a[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:

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l greater than k such that a[k] < a[l].
  3. Swap the value of a[k] with that of a[l].
  4. Reverse the sequence from a[k + 1] up to and including the final element a[n].
Tweeted twitter.com/StackCodeReview/status/786152191258161153
deleted 1 character in body
Source Link
Flambino
  • 33.3k
  • 2
  • 46
  • 90

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:

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l greater than k such that a[k] < a[l].
  3. Swap the value of a[k] with that of a[l].
  4. Reverse the sequence from a[k + 1] up to and including the final element a[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:

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l greater than k such that a[k] < a[l].
  3. Swap the value of a[k] with that of a[l].
  4. Reverse the sequence from a[k + 1] up to and including the final element a[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:

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l greater than k such that a[k] < a[l].
  3. Swap the value of a[k] with that of a[l].
  4. Reverse the sequence from a[k + 1] up to and including the final element a[n].
Source Link
Flambino
  • 33.3k
  • 2
  • 46
  • 90

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:

  1. Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
  2. Find the largest index l greater than k such that a[k] < a[l].
  3. Swap the value of a[k] with that of a[l].
  4. Reverse the sequence from a[k + 1] up to and including the final element a[n].
lang-rb

AltStyle によって変換されたページ (->オリジナル) /