Execute SNUSP: Difference between revisions

Content added Content deleted
(→‎{{header|F_Sharp|F#}}: Moving content to sub-page)
Line 11: Line 11:
See [[RCSNUSP/D]].
See [[RCSNUSP/D]].
=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
See [[RCSNUSP/F Sharp]].
This is the "modular" version. Perhaps I'll get around to bloated later. Allows infinite size data space to the left and right of the original data pointer. I originally mistook the meaning of ',' and had the user input an arbitrary number which I would place on the tape, but after looking at the sample multiplication program, realized that I was supposed to input the ascii value of the single key entered. Still, it seems like a good command to allow for reading an arbitrary value so I arbitrarily allocated '~' as the command for that purpose.
<lang fsharp>open System
open System.Collections.Generic

type IP (p:(int*int), d:(int*int), dim1, dim2) =
let mutable _p = p
let mutable _d = d
let mutable _fValid = true
member this.dim1 = dim1
member this.dim2 = dim2
member this.x = fst this.pos
member this.y = snd this.pos
member this.dx = fst this.dir
member this.dy = snd this.dir
member this.pos with get() = _p
and set newp = _p <- newp
member this.dir with get() = _d
and set newd = _d <- newd
member this.Clone() = new IP((this.x, this.y), (this.dx, this.dy), dim1, dim2)
member this.Invalidate() = _fValid <- false
member this.SetTo(ip : IP) = this.pos <- ip.pos; this.dir <- ip.dir
member this.Advance() =
this.pos <- ((fst this.pos) + (fst this.dir), (snd this.pos) + (snd this.dir))
member this.Valid() =
_fValid && this.x >= 0 && this.x < dim2 && this.y >= 0 && this.y < dim2
member this.Reflect(c) =
match c with
| '/' -> this.dir <- (-this.dy, -this.dx)
| '\\' -> this.dir <- (this.dy, this.dx)
| _ -> ignore()
let RCSNUSP (pgmStr : string) =
let StringToPgm (str : string) =
let stringsPre =
str.Trim([|'\n'; '\r'|]).Split([|'\n'|])
|> Seq.map (fun s -> s.Trim([|'\n'; '\r'|]))
let maxLen =
stringsPre
|> Seq.map (fun s -> s.Length)
|> Seq.max
let strings =
stringsPre
|> Seq.map (fun s -> s.PadRight(maxLen))
strings
|> Seq.map (fun s -> s.Trim([|'\n'; '\r'|]).ToCharArray())
|> array2D

let pgm = StringToPgm pgmStr
let ptr = ref 0 // Pointer into input
let stk = new Stack<IP>() // Instruction stack
let input = ref (Array.create 100 0)

let LocateStart pgm =
let fFound = ref false
let s1 =
seq {
for i = 0 to ((Array2D.length1 pgm)-1) do
for j = 0 to ((Array2D.length2 pgm)-1) do
yield (pgm.[i,j], (j, i)) }
|> Seq.skipWhile (fun (c, _) -> fFound := !fFound || (c = '$'); not !fFound)
|> Seq.truncate 1
|> Seq.toArray

if not !fFound then
(0,0)
else
s1
|> Seq.head
|> snd
let ip = new IP(LocateStart pgm, (1, 0), Array2D.length1 pgm, Array2D.length2 pgm) // Instruction Pointer

let InputNumber() =
let mutable fValid = false
let mutable num = 0
printfn "Enter a valid number"
fValid <- Int32.TryParse(Console.ReadLine(), &num);
while not fValid do
printfn "Invalid input. Please enter a valid number"
fValid <- Int32.TryParse(Console.ReadLine(), &num);
num

let InputAscii() =
printfn "Enter an ascii character"
let chOut = (Console.ReadKey().KeyChar)
printfn ""
int chOut

let MovePtr fRight =
if fRight then
ptr := !ptr + 1
if !ptr >= (!input).Length then
Array.Resize(input, (!input).Length + 20)
else
ptr := !ptr - 1
if !ptr < 0 then
let newInput = Array.create ((!input).Length + 20) 0
Array.ConstrainedCopy(!input, 0, newInput, 20, (!input).Length)
ptr := 19
let interpretCmd() =
//if @"><+-.,;/\?!@#".Contains(pgm.[ip.y, ip.x].ToString()) then
// printfn "TapePos: %d; TapeVal: %d; Pos (%d, %d) : %c" !ptr (!input).[!ptr] ip.x ip.y pgm.[ip.y, ip.x]
// Console.ReadKey() |> ignore
match pgm.[ip.y, ip.x] with
| '>' -> MovePtr true; ip.Advance()
| '<' -> MovePtr false; ip.Advance()
| '+' -> (!input).[!ptr] <- (!input).[!ptr] + 1; ip.Advance()
| '-' -> (!input).[!ptr] <- (!input).[!ptr] - 1; ip.Advance()
| '.' -> printf "%c" (char (!input).[!ptr]); ip.Advance()
| ',' -> (!input).[!ptr] <- InputAscii(); ip.Advance()
| '~' -> (!input).[!ptr] <- InputNumber(); ip.Advance()
| '/' | '\\' -> ip.Reflect(pgm.[ip.y, ip.x]); ip.Advance()
| '?' -> ip.Advance(); if (!input).[!ptr] = 0 then ip.Advance()
| '!' -> ip.Advance(); ip.Advance()
| '@' -> stk.Push(ip.Clone()); ip.Advance()
| '#' -> if stk.Count = 0 then
ip.Invalidate()
else
ip.SetTo(stk.Pop())
ip.Advance()
ip.Advance()
| _ -> ip.Advance()

while ip.Valid() do
interpretCmd() |> ignore
(!input).[!ptr]</lang>
Example inputs:
<lang fsharp>let p1 = @"
read two characters ,>,==\ * /=================== ATOI ----------\
convert to integers /=/@</@=/ * // /===== ITOA ++++++++++\ /----------/
multiply @ \=!\=========/ // /++++++++++/ \----------\
convert back !/@!\============/ \++++++++++\ /----------/
and print the result \/ \.# * /++++++++++/ \--------#
/====================/ * \++++++++#
|
| /-<+>\ #/?=<<<<\!>>>>\ />>+<+<-\
| #\?===/! BMOV1 =====\ \->>>>+/ // /======== BSPL2 !\======?/#
| /->+<\ /===|=========== FMOV4 =/ // /<<+>+>-\
| #\?===/! FMOV1 =|===|==============\ /====/ /====== FSPL2 !\======?/#
| /==|===|==============|==|=======/
| * * *|* | * | * * * * * * *|* | * * * /+<-\
| * />@/<@/>>@/>>===\ /====>>\@<\@<\ * /==== ADD2 !\>=?/<#
\===== MUL2 =?/>@\==<#<<<==\ \!\<<<<@\>>>>-?/\ * // /-\
* \\ \/@========|======</ * // /== ZERO !\?/#
* * * \\* * * * | * * * * | * * * * *// //
\\ | \==========/ //
\======!\=======================/
"
// Should print out multiplication of two input ascii values
RCSNUSP p1 |> ignore
printfn ""
printfn "Next three should all yield 48"
printfn "value = %d" (RCSNUSP @"
/\/\/\
$===++++++\
/++++++/
\++++++\
/++++++/
\/\/\/#
")
printfn "value = %d" (RCSNUSP @"
#/\/\
$===!\++++\
/++++/
/=\++++\
\!\/\/\/
")
printfn "value = %d" (RCSNUSP @"6=@@@+@+++++#")
</lang>


=={{header|Haskell}}==
=={{header|Haskell}}==