Shuffling in Whitespace

Until now, programmers interested in using randomized algorithms in Whitespace have been required to supply some random stuff as input to their program. To solve this, I propose adding a new instruction to the Whitespace language that will shuffle the stack. This feature can then be used to implement various randomized algorithms, including a random number generator.

Command Reference and Sample Program

As a stack operation, this instruction is prefixed by the [Space] IMP. The command code is selected to allow for future expansion of Whitespace's stack operations and in homage to a musical group that my wife assures me is not disco.

CommandParametersMeaning
[Tab][Tab][Space]-Randomly permute the order of all values on the stack.

You can download a sample program which prints out the digits 0-9 in a random order.

Implementation

You may download my enhanced version of Whitespace here.

For your convenience, the changes to the reference implementation of Whitespace follow.


--- WSpace/Input.hs	2004-05-04 10:10:15.000000000 -0700
+++ WSpaceS/Input.hs	2011-03-10 11:26:53.000000000 -0800
@@ -13,7 +13,10 @@
 We have:
 
 * Stack instructions (Preceded by A)
-     Push (Integer)    A
+     Push n        A
+     Copy nth      BA
+     Shuffle       BBA
+     Slide n       BC
      Dup           CA
      Swap          CB
      Discard       CC
@@ -67,6 +70,7 @@
 parse (A:C:A:xs) = Dup:(parse xs)
 parse (A:B:A:xs) = let (num,rest) = parseNumber xs in
 		   (Ref num):(parse rest)
+parse (A:B:B:A:xs) = Shuffle:(parse xs)
 parse (A:B:C:xs) = let (num,rest) = parseNumber xs in
 		   (Slide num):(parse rest)
 parse (A:C:B:xs) = Swap:(parse xs)

--- WSpace/VM.hs	2004-05-04 10:10:41.000000000 -0700
+++ WSpaceS/VM.hs	2011-03-10 12:37:56.000000000 -0800
@@ -1,6 +1,8 @@
 module VM where
 
+import Array
 import IO
+import System.Random
 
 {- Stack machine for running whitespace programs -}
 
@@ -8,6 +10,7 @@
        Push Integer
      | Dup
      | Ref Int
+     | Shuffle
      | Slide Int
      | Swap
      | Discard
@@ -61,6 +64,9 @@
     = vm (VM prog (Stack (n:n:stack)) cs heap pc)
 doInstr (VM prog (Stack (stack)) cs heap pc) (Ref i)
     = vm (VM prog (Stack ((stack!!i):stack)) cs heap pc)
+doInstr (VM prog (Stack stack) cs heap pc) Shuffle
+    = do shuffled <- shuffle stack
+	 vm (VM prog (Stack shuffled) cs heap pc)
 doInstr (VM prog (Stack (n:stack)) cs heap pc) (Slide i)
     = vm (VM prog (Stack (n:(drop i stack))) cs heap pc)
 doInstr (VM prog (Stack (n:m:stack)) cs heap pc) Swap
@@ -143,3 +149,18 @@
 store x n [] = do hp <- store x (n-1) [] 
 		  return (0:hp)
 
+-- Shuffling the stack
+
+shuffle :: [Integer] -> IO [Integer]
+shuffle nums = do shuffled <- shuffle' arr 1
+		  return $ elems shuffled
+  where arr = array (1, length nums) $ zip [1..] nums
+
+shuffle' :: Array Int Integer -> Int -> IO (Array Int Integer)
+shuffle' arr start = do
+   newIx <- randomRIO (start, end)
+   let (v1, v2) = (arr ! start, arr ! newIx)
+   -- putStrLn $ "Swapping " ++ (show (start, newIx))
+   let swapped = arr // [(start, v2), (newIx, v1)]
+   if start < (end - 1) then shuffle' swapped (start+1) else return arr
+  where end = snd $ bounds arr

--- WSpace/main.hs	2003-03-31 07:33:44.000000000 -0800
+++ WSpaceS/main.hs	2011-03-10 12:07:15.000000000 -0800
@@ -37,7 +37,7 @@
 
 usage :: IO ()
 usage = do
-	putStrLn "wspace 0.2 (c) 2003 Edwin Brady"
+	putStrLn "wspace 0.4 (c) 2003 Edwin Brady"
 	putStrLn "-------------------------------"
 	putStrLn "Usage: wspace [file]"