René Nyffenegger's collection of things on the web
René Nyffenegger on Oracle - Most wanted - Feedback -
 

Permute [Vim Script]

The following function permutes the elements passed in (the only) parameter elems which is a List.
The permutations are returned as a List of Lists. See TestPermute.
fu! Permute(elems)

  return Permute_([], [], a:elems)

endfu

fu! Permute_(final_result, already_found, target)

  let l:final_result = copy(a:final_result)
  if len(a:target) == 1
    let l:already_found = copy(a:already_found)
    call add(l:already_found, a:target[0])
    call add(l:final_result, l:already_found)
    return l:final_result
  endif

  let l:pos    = 0

  while l:pos < len(a:target)
    let l:target = copy(a:target)

    let l:already_found = copy(a:already_found)
    call add(l:already_found, a:target[l:pos])
    call remove(l:target, l:pos)

    let l:final_result = Permute_(l:final_result, l:already_found, l:target)

    let l:pos = l:pos + 1
  endwhile

  return l:final_result

endfu

fu! TestPermute_(t, perm_no, elem_no, expected)
  if a:t[a:perm_no][a:elem_no] != a:expected
     echo "Error t[" . a:perm_no . "][" . a:elem_no . "] != " . a:expected
  endif
endfu

fu! TestPermute__(t, expected_len)

  for l:perm in a:t

    if len(l:perm) != a:expected_len 
       echo "expected_len: " . a:expected_len ", but is in fact: " . len(l:perm)
    endif
  endfor

endfu

fu! TestPermute()

  let t1 = Permute([10, 20])

  if len(t1) != 2 
     echo "Error, len(t1) != 2"
  endif

  call TestPermute__(t1, 2)

  call TestPermute_(t1, 0, 0, 10)
  call TestPermute_(t1, 0, 1, 20)
  call TestPermute_(t1, 1, 0, 20)
  call TestPermute_(t1, 1, 1, 10)

  """"""""

  let t2 = Permute(['x', 'y', 'z'])
  if len(t2) != 6 
     echo "Error, len(t2) != 6"
  endif
  call TestPermute__(t2, 3)

  call TestPermute_(t2, 0, 0, 'x')
  call TestPermute_(t2, 0, 1, 'y')
  call TestPermute_(t2, 0, 2, 'z')

  call TestPermute_(t2, 1, 0, 'x')
  call TestPermute_(t2, 1, 1, 'z')
  call TestPermute_(t2, 1, 2, 'y')

  call TestPermute_(t2, 2, 0, 'y')
  call TestPermute_(t2, 2, 1, 'x')
  call TestPermute_(t2, 2, 2, 'z')

  call TestPermute_(t2, 3, 0, 'y')
  call TestPermute_(t2, 3, 1, 'z')
  call TestPermute_(t2, 3, 2, 'x')

  call TestPermute_(t2, 4, 0, 'z')
  call TestPermute_(t2, 4, 1, 'x')
  call TestPermute_(t2, 4, 2, 'y')

  call TestPermute_(t2, 5, 0, 'z')
  call TestPermute_(t2, 5, 1, 'y')
  call TestPermute_(t2, 5, 2, 'x')

  """"""""

  let t3 = Permute(['a', 'b', 'c', 'd', 'e'])
  if len(t3) != 120
     echo "Error, len(t3) != 120"
  endif
  call TestPermute__(t3, 5)

  call TestPermute_(t3, 0, 0, 'a')
  call TestPermute_(t3, 0, 1, 'b')
  call TestPermute_(t3, 0, 2, 'c')
  call TestPermute_(t3, 0, 3, 'd')
  call TestPermute_(t3, 0, 4, 'e')

  call TestPermute_(t3,119, 0, 'e')
  call TestPermute_(t3,119, 1, 'd')
  call TestPermute_(t3,119, 2, 'c')
  call TestPermute_(t3,119, 3, 'b')
  call TestPermute_(t3,119, 4, 'a')

endfu
See also other Vim scripts.