Talk:DownRight
Jump to navigation
Jump to search
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!
# partialDownRight # -to feed program, use the following format: [below a 3x2 program example] # rd d d # d r rdd # (that is, use "d" and "r" characters for down and right arrows, separate each string # within a row with a single space, use a new-line to end the row (except the last row)) # -this interpreter does not deal properly with faulty programs # -usage: dori.py prog.dr # use any string (such as "debug") as a second argument to active debug mode # written by Keymaker 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 # this routine does not really check for any errors or invalid syntax... 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 # ------------------------------------------------------------------- # here should be a routine to check that width and height are coprime # ------------------------------------------------------------------- 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 ""
--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 ./program < inputfile
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)