Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
94
Task/Truth-table/Nim/truth-table.nim
Normal file
94
Task/Truth-table/Nim/truth-table.nim
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import sequtils, strutils, sugar
|
||||
|
||||
# List of possible variables names.
|
||||
const VarChars = {'A'..'E', 'G'..'S', 'U'..'Z'}
|
||||
|
||||
type
|
||||
|
||||
Expression = object
|
||||
names: seq[char] # List of variables names.
|
||||
values: seq[bool] # Associated values.
|
||||
formula: string # Formula as a string.
|
||||
|
||||
|
||||
proc initExpression(str: string): Expression =
|
||||
## Build an expression from a string.
|
||||
for ch in str:
|
||||
if ch in VarChars and ch notin result.names:
|
||||
result.names.add ch
|
||||
result.values.setLen(result.names.len)
|
||||
result.formula = str
|
||||
|
||||
|
||||
template apply(stack: seq[bool]; op: (bool, bool) -> bool): bool =
|
||||
## Apply an operator on the last two operands of an evaluation stack.
|
||||
## Needed to make sure that pops are done (avoiding short-circuit optimization).
|
||||
let op2 = stack.pop()
|
||||
let op1 = stack.pop()
|
||||
op(op1, op2)
|
||||
|
||||
|
||||
proc evaluate(expr: Expression): bool =
|
||||
## Evaluate the current expression.
|
||||
|
||||
var stack: seq[bool] # Evaluation stack.
|
||||
|
||||
for e in expr.formula:
|
||||
stack.add case e
|
||||
of 'T': true
|
||||
of 'F': false
|
||||
of '!': not stack.pop()
|
||||
of '&': stack.apply(`and`)
|
||||
of '|': stack.apply(`or`)
|
||||
of '^': stack.apply(`xor`)
|
||||
else:
|
||||
if e in VarChars: expr.values[expr.names.find(e)]
|
||||
else:
|
||||
raise newException(
|
||||
ValueError, "Non-conformant character in expression: '$#'.".format(e))
|
||||
|
||||
if stack.len != 1:
|
||||
raise newException(ValueError, "Ill-formed expression.")
|
||||
result = stack[0]
|
||||
|
||||
|
||||
proc setVariables(expr: var Expression; pos: Natural) =
|
||||
## Recursively set the variables.
|
||||
## When all the variables are set, launch the evaluation of the expression
|
||||
## and print the result.
|
||||
|
||||
assert pos <= expr.values.len
|
||||
|
||||
if pos == expr.values.len:
|
||||
# Evaluate and display.
|
||||
let vs = expr.values.mapIt(if it: 'T' else: 'F').join(" ")
|
||||
let es = if expr.evaluate(): 'T' else: 'F'
|
||||
echo vs, " ", es
|
||||
|
||||
else:
|
||||
# Set values.
|
||||
expr.values[pos] = false
|
||||
expr.setVariables(pos + 1)
|
||||
expr.values[pos] = true
|
||||
expr.setVariables(pos + 1)
|
||||
|
||||
|
||||
echo "Accepts single-character variables (except for 'T' and 'F',"
|
||||
echo "which specify explicit true or false values), postfix, with"
|
||||
echo "&|!^ for and, or, not, xor, respectively; optionally"
|
||||
echo "seperated by spaces or tabs. Just enter nothing to quit."
|
||||
|
||||
while true:
|
||||
# Read formula and create expression.
|
||||
stdout.write "\nBoolean expression: "
|
||||
let line = stdin.readLine.toUpperAscii.multiReplace((" ", ""), ("\t", ""))
|
||||
if line.len == 0: break
|
||||
var expr = initExpression(line)
|
||||
if expr.names.len == 0: break
|
||||
|
||||
# Display the result.
|
||||
let vs = expr.names.join(" ")
|
||||
echo '\n', vs, " ", expr.formula
|
||||
let h = vs.len + expr.formula.len + 2
|
||||
echo repeat('=', h)
|
||||
expr.setVariables(0)
|
||||
Loading…
Add table
Add a link
Reference in a new issue