master
  1<<-DOC
  2Note: Try to solve this task in O(list size) time using O(1) additional space, since this is what you'll be asked during an interview.
  3
  4Given a singly linked list of integers l and a non-negative integer n,
  5move the last n list nodes to the beginning of the linked list.
  6
  7Example
  8
  9For l = [1, 2, 3, 4, 5] and n = 3, the output should be
 10rearrangeLastN(l, n) = [3, 4, 5, 1, 2];
 11For l = [1, 2, 3, 4, 5, 6, 7] and n = 1, the output should be
 12rearrangeLastN(l, n) = [7, 1, 2, 3, 4, 5, 6].
 13Input/Output
 14
 15[time limit] 4000ms (rb)
 16[input] linkedlist.integer l
 17
 18A singly linked list of integers.
 19
 20Guaranteed constraints:
 210  list size  105,
 22-1000  element value  1000.
 23
 24[input] integer n
 25
 26A non-negative integer.
 27
 28Guaranteed constraints:
 290  n  list size.
 30
 31[output] linkedlist.integer
 32
 33Return l with the n last elements moved to the beginning.
 34DOC
 35
 36describe "#rearrange_last_n" do
 37  def length_of(list)
 38    i = 1
 39    i += 1 while list = list.next
 40    i
 41  end
 42
 43  def rearrange_last_n(list, n)
 44    return list if n.zero?
 45    length = length_of(list)
 46    return list if n == length
 47
 48    position = length - n
 49    head = mid = tail = list
 50
 51    tail = tail.next until tail.next.nil?
 52    (position - 1).times { mid = mid.next }
 53    nh = mid.next
 54    mid.next = nil
 55    tail.next = head
 56
 57    nh
 58  end
 59
 60  [
 61    { l: [1, 2, 3, 4, 5], n: 3, x: [3, 4, 5, 1, 2] },
 62    { l: [1, 2, 3, 4, 5, 6, 7], n: 1, x: [7, 1, 2, 3, 4, 5, 6] },
 63    { l: [1000, -1000], n: 0, x: [1000, -1000] },
 64    { l: [], n: 0, x: [] },
 65    { l: [123, 456, 789, 0], n: 4, x: [123, 456, 789, 0] },
 66  ].each do |x|
 67    it do
 68      result = rearrange_last_n(ListNode.to_list(x[:l]), x[:n])
 69      expect(result.to_a).to eql(x[:x])
 70    end
 71  end
 72
 73  class ListNode
 74    attr_accessor :value, :next
 75
 76    def initialize(value, next_node: nil)
 77      @value = value
 78      @next = next_node
 79    end
 80
 81    def to_a
 82      result = []
 83      current = self
 84      until current.nil?
 85        result.push(current.value)
 86        current = current.next
 87      end
 88      result
 89    end
 90
 91    def self.to_list(items)
 92      x = nil
 93      items.inject(nil) do |memo, item|
 94        node = new(item)
 95        if memo.nil?
 96          x = node
 97        else
 98          memo.next = node
 99        end
100        node
101      end
102      x
103    end
104  end
105end