Talk:DownRight

A partial interpreter in Python
An interesting language here, very elegant. I made an interpreter in Python but it's partial because it doesn't handle the arrows as unicode but instead uses letters 'd' and 'r', and the program input isn't checked for errors, and it's plainly required in different format from the one the language specification uses. But otherwise it should work!

import sys if len(sys.argv) < 2: print "Error, need a DownRight program to run." sys.exit try: f = open(sys.argv[1]) except IOError: print "Error in reading the program." sys.exit d = f.read.split("\n") f.close debug = 0 if len(sys.argv) > 2: debug = 1 prog = [] que = "" width = -1 height = -1 px = 0 py = 0 height = len(d) for x in d:    a = x.split(" ") if len(a) > 0: width = len(a) for y in a:            prog.append(y) if debug: print "program, width, height:", prog, width, height que = prog[0] # place the top-left string into the queue if debug: print "initial queue:", que print "" while 1: # first, pop the queue c = "" if len(que) > 0: c = que[0] que = que[1:] # "" means the queue was empty: halt if c == "": if debug: print "empty queue, program halted" break # "d" or "r" mean the instruction pointer will be moved if c == "d": if debug: print "down arrow read from queue" py = (py + 1) % height else: if debug: print "right arrow read from queue" px = (px + 1) % width if debug: print "instruction pointer gone to", px, py    # now, the string from the new location of the instruction pointer will be placed in the queue if debug: print "queue before addition:", que print "string under instruction pointer:", prog[(width * py) + px] print "queue: (below)" que = que + prog[(width * py) + px] print que if debug: print ""
 * 1) partialDownRight
 * 2) -to feed program, use the following format: [below a 3x2 program example]
 * 3)  rd d d
 * 4)  d r rdd
 * 5)  (that is, use "d" and "r" characters for down and right arrows, separate each string
 * 6)  within a row with a single space, use a new-line to end the row (except the last row))
 * 7) -this interpreter does not deal properly with faulty programs
 * 8) -usage: dori.py prog.dr
 * 9)  use any string (such as "debug") as a second argument to active debug mode
 * 10) written by Keymaker
 * 1) this routine does not really check for any errors or invalid syntax...
 * 1) here should be a routine to check that width and height are coprime
 * 1) here should be a routine to check that width and height are coprime

--Keymaker 18:43, 12 May 2011 (UTC)

Implementation in haskell
This should work, the code is likely suboptimal, as I'm not very used to Haskell yet. Tested on GHC 6.12.1 and Parsec 3.0.1.

To use, compile with ghc and then run as

This program implements the extension where the sides do not need to be co-prime.

-- Copyright (c) 2011, Vorpal -- Released in public domain in countries where that is applicable.

import Text.ParserCombinators.Parsec import qualified Data.Sequence as Seq import Data.Array import System.IO

data DownRightReturn = ParseErr ParseError | Error String | FinalPos (Int, Int)

-- Parsec stuff ws = many (char ' ') ws1 = many1 (char ' ') eol = (many1 (char '\n')) >> ws cell = many1 (noneOf " \n") line = sepEndBy1 cell ws1 downrightFile = (sepEndBy1 line eol) <|> (eof >> return [])

parseDownRight :: String -> Either ParseError String parseDownRight input = parse downrightFile "(unknown)" input

-- Post-procesing parsed stuff filterDownRight :: String -> String filterDownRight = map (map (filter (`elem` "↓→")))

checkLen :: a -> Bool checkLen [] = True checkLen (x:xs) = let l = length x in       all (\y -> length y == l) xs

programToArray :: String -> Array (Int, Int) String programToArray program = let (x:_) = program h = length program - 1 w = length x - 1 in   listArray ((0,0),(h,w)) (concat program)

-- Actual execution executeDownRight :: Array (Int, Int) String -> Seq.Seq Char -> (Int, Int) -> (Int,Int) -> (Int,Int) executeDownRight program queue pos max = case Seq.viewl queue of        Seq.EmptyL -> pos (Seq.:<) instr newqueue -> let newpos = calcMove instr pos max str = program ! newpos in           executeDownRight program ((Seq.><) newqueue (Seq.fromList str)) newpos max

calcMove :: Char -> (Int, Int) -> (Int, Int) -> (Int, Int) calcMove '→' (x,y) (mx,my) = (x, (y+1) `rem` my) calcMove '↓' (x,y) (mx,my) = ((x+1) `rem` mx, y)

-- Code wrapping executeDownRight runDownRight :: Array (Int, Int) String -> (Int, Int) runDownRight program = let (_,(mx,my)) = bounds program str = program ! (0,0) in       executeDownRight program (Seq.fromList str) (0,0) (mx+1,my+1)

downRight :: String -> DownRightReturn downRight input = case parseDownRight input of        Left err -> ParseErr err Right [] -> Error "Can't handle null program yet" Right (x:xs) -> case checkLen (x:xs) of                False -> Error "All lines must be of same length" True -> FinalPos (runDownRight $ programToArray $ filterDownRight (x:xs))

-- Stuff for running as free standing program instead of from ghci downRightInteract :: String -> String downRightInteract input = case downRight input of        ParseErr err -> "Parse error: " ++ show err ++ "\n" Error err -> "Error: " ++ err ++ "\n" FinalPos pos -> "Halted at " ++ show pos ++ "\n"

main = interact downRightInteract -- User:Vorpal 2011-05-14T12:53:05 (UTC)