Version 1 of lrotate

Updated 2016-03-17 11:51:45 by arjen

Rotate a list. (Creates and returns a new list.)

    proc lrotate {xs {n 1}} {
      if {!$n} {return $xs}
      if {$n<0} {return [lrotate $xs [expr {[llength $xs]+$n}]]}

      foreach x [lassign $xs y] {
        lappend ys $x
      }
      lappend ys $y
      lrotate $ys [incr n -1]
    }

By default, rotates a list left by one element (moving the head to the tail).

Examples:

    % lrotate {1 2 3 4 5}
    2 3 4 5 1

    % lrotate {1 2 3 4 5} -1
    5 1 2 3 4

    % lrotate {1 2 3 4 5} 2
    3 4 5 1 2

    % lrotate {1 2 3 4 5} 0
    1 2 3 4 5

I'm sure someone can come up with a better implementation...

AM I could not resist this challenge :). Here is mine (note that allows any number for the shift):

proc lrotate2 {xs {n 1}} {
    set length [llength $xs]

    if {$n == 0 || $length == 0 } {return $xs}

    set n [expr {$n % $length}]

    return [concat [lrange $xs $n end] [lrange $xs 0 [expr {$n-1}]]]
}