# $Id: lists.pliant,v 1.0 2002/02/08 10:09:00 dada Exp $
# http://dada.perl.it/shootout/

module "/pliant/language/context.pli"

gvar Int SIZE := 10000

function reverse l -> r
  arg List:Int l
  arg List:Int r
  var Pointer:Int v
  v :> l last
  for (var Int i) l:size-1 0 step -1
    r += v
    v :> l previous v
  return r

function test_lists -> r
  arg Int r
  var List:Int Li1
  var List:Int Li2
  var List:Int Li3
  var Pointer:Int v
  var Int len1
  var Int len2
  var Bool lists_equal := true
  var Pointer:Int v1
  var Pointer:Int v2
  
  # create a list of integers (Li1) from 1 to SIZE
  for (var Int i) 1 SIZE
    Li1 += i
 
  # copy the list to Li2 (not by individual items)
  Li2 := Li1

  # remove each individual item from left side of Li2 and
  # append to right side of Li3 (preserving order)
  while Li2:size > 0
    v :> Li2 first
    Li3 += v
    Li2 -= v

  # Li2 must now be empty
  # remove each individual item from right side of Li3 and
  # append to right side of Li2 (reversing list)
  while Li3:size > 0
    v :> Li3 last
    Li2 += v
    Li3 -= v

  # Li3 must now be empty
  # reverse Li1 in place
  Li1 := reverse Li1
  
  # check that first item is now SIZE
  v :> Li1 first
  if v <> SIZE
    return 0 

  # compare Li1 and Li2 for equality
  len1 := Li1:size
  len2 := Li2:size
  lists_equal := (len1=len2)
  v1 :> Li1 first
  v2 :> Li2 first
  for (var Int i) 0 len1-1      
    if v1 <> v2
      lists_equal := false
      i := len1-1
    v1 :> Li1 next v1
    v2 :> Li2 next v2
  if lists_equal = false
    return 0
  return len1

gvar Int r
gvar Str s_n := cast ((pliant_script_args translate Address 1) map CStr) Str
if (s_n parse (gvar Int n))
  while n > 0
    r := test_lists
    n := n - 1
  console r eol
else
  console "usage: lists.pliant <number>" eol