mirror of
https://github.com/osmarks/random-stuff
synced 2025-11-03 23:33:01 +00:00
add more things???
This commit is contained in:
100
Stackulator.fs
Executable file
100
Stackulator.fs
Executable file
@@ -0,0 +1,100 @@
|
||||
open System
|
||||
open System.Numerics
|
||||
|
||||
type Stack = StackContents of Complex list
|
||||
|
||||
let splitPart (what:char) index (stringIn:string) = stringIn.Split(what).[index]
|
||||
let spliti = splitPart 'i'
|
||||
let firstInSpliti = spliti 0
|
||||
let secondInSpliti = spliti 1
|
||||
let isDoubleAsString text = System.Double.TryParse text |> fst
|
||||
let doubleFromString text = System.Double.TryParse text |> snd
|
||||
let isImaginaryAsString (text:string) =
|
||||
match text.Contains("i") with
|
||||
| false -> false
|
||||
| true ->
|
||||
let normalPart = firstInSpliti text
|
||||
isDoubleAsString normalPart
|
||||
let imaginaryFromString text =
|
||||
let imaginaryPart = doubleFromString (firstInSpliti text)
|
||||
Complex(0.0, imaginaryPart)
|
||||
|
||||
let showStack (StackContents contents) =
|
||||
printfn "%A" contents // Print unpacked StackContents with formatting string
|
||||
StackContents (contents) // Repack the StackContents
|
||||
|
||||
let push value (StackContents contents) =
|
||||
StackContents (value::contents)
|
||||
|
||||
let pop (StackContents contents) =
|
||||
match contents with
|
||||
| top::rest -> // Separate top from rest
|
||||
(top, StackContents rest) // Stack contents must be the StackContents type.
|
||||
| [] -> // Check for stack underflow
|
||||
failwith "Stack underflow"
|
||||
|
||||
let binary func stack =
|
||||
let x, newStack = pop stack
|
||||
let y, newestStack = pop newStack
|
||||
let z = func y x // This is deliberately swapped, because we are working on a stack
|
||||
push z newestStack
|
||||
|
||||
let unary func stack =
|
||||
let x, newStack = pop stack
|
||||
push (func x) stack
|
||||
|
||||
let dup stack =
|
||||
let x, _ = pop stack // Drop the new stack, we want to duplicate "x"
|
||||
push x stack
|
||||
|
||||
let swap stack =
|
||||
let x, newStack = pop stack
|
||||
let y, newerStack = pop newStack
|
||||
push y (push x newerStack)
|
||||
|
||||
let drop stack =
|
||||
let _, newStack = pop stack // Pop one off the top and ignore it
|
||||
newStack
|
||||
|
||||
let numberInput value stack = push value stack
|
||||
|
||||
let add = binary (+)
|
||||
let multiply = binary (*)
|
||||
let subtract = binary (-)
|
||||
let divide = binary (/)
|
||||
let negate = unary (fun x -> -(x))
|
||||
let square = unary (fun x -> x * x)
|
||||
let cube = dup >> dup >> multiply >> multiply
|
||||
let exponent = binary ( ** )
|
||||
|
||||
let show stack =
|
||||
let value, _ = pop(stack)
|
||||
printfn "%A" value
|
||||
stack // We're going to keep the same stack as before.
|
||||
|
||||
let empty = StackContents []
|
||||
|
||||
let splitString (text:string) = text.Split ' '
|
||||
|
||||
let processTokenString stack token =
|
||||
match token with
|
||||
| "*" -> stack |> multiply
|
||||
| "+" -> stack |> add
|
||||
| "/" -> stack |> divide
|
||||
| "+-" -> stack |> negate
|
||||
| "sqr" -> stack |> square
|
||||
| "cub" -> stack |> cube
|
||||
| "**" | "^" -> stack |> exponent
|
||||
| _ when isDoubleAsString token ->
|
||||
let doubleInString = doubleFromString token
|
||||
numberInput (Complex(doubleInString, 0.0)) stack
|
||||
| _ when isImaginaryAsString token ->
|
||||
let imaginaryInString = imaginaryFromString token
|
||||
numberInput imaginaryInString stack
|
||||
| _ -> showStack stack // For easier debugging.
|
||||
|
||||
Console.Write("Please enter your expression here: ")
|
||||
let userExpression = Console.ReadLine()
|
||||
let splitExpression = splitString userExpression
|
||||
|
||||
let resultantStack = List.fold processTokenString (empty) (Array.toList splitExpression) |> showStack
|
||||
Reference in New Issue
Block a user