# Resistance calculator

(Redirected from Resistance Calculator)
• Infix: ((((10 + 2) * 6 + 8) * 6 + 4) * 8 + 4) * 8 + 6
• RPN: 10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +
• Voltage = 18.0 V
Resistance calculator is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Introduction
• Calculate the resistance of a network of resistors.
• The resistors can be connected in series or parallel.
• Use infix or RPN to state the network.
• Calculate resistance, voltage, current and power for every resistor and operation.
Background
• Serial Resistors: the sum of the resistors gives the equivalent resistor
• Parallel Resistors: the inverse of the sum of the inverse of the resistors
• The voltage drops over the resistors
• Current = Resistance / Voltage
• Power = Current * Voltage
Input
Output
• 10.000 ohms in the upper left corner is the equivalent resistance.
• The first operation is 10 + 2 = 12 which can be found in the three middle rows.
```    Ohm     Volt   Ampere     Watt  Network tree
10.000   18.000    1.800   32.400  +
4.000    7.200    1.800   12.960  | *
8.000    7.200    0.900    6.480  | | +
4.000    3.600    0.900    3.240  | | | *
8.000    3.600    0.450    1.620  | | | | +
4.000    1.800    0.450    0.810  | | | | | *
12.000    1.800    0.150    0.270  | | | | | | +
4.000    0.600    0.150    0.090  | | | | | | | *
12.000    0.600    0.050    0.030  | | | | | | | | +
10.000    0.500    0.050    0.025  | | | | | | | | | r
2.000    0.100    0.050    0.005  | | | | | | | | | r
6.000    0.600    0.100    0.060  | | | | | | | | r
8.000    1.200    0.150    0.180  | | | | | | | r
6.000    1.800    0.300    0.540  | | | | | | r
4.000    1.800    0.450    0.810  | | | | | r
8.000    3.600    0.450    1.620  | | | | r
4.000    3.600    0.900    3.240  | | | r
8.000    7.200    0.900    6.480  | | r
6.000   10.800    1.800   19.440  | r
```

## 11l

Translation of: Python

### RPN

```T Resistor
Float resistance
voltage = 0.0
Resistor? a, b
Char symbol

F (resistance = 0.0, Resistor? a = N, b = N; symbol = Char(‘r’))
.resistance = resistance
.a = a
.b = b
.symbol = symbol

F.virtual.new res() -> Float
R .resistance
F.virtual.new setVoltage(Float voltage) -> N
.voltage = voltage
F current()
R .voltage / .res()
F effect()
R .current() * .voltage
F report(level = ‘’) -> N
print(‘#4.3 #4.3 #4.3 #4.3  #.#.’.format(.res(), .voltage, .current(), .effect(), level, .symbol))
I .a != N {.a.report(level‘| ’)}
I .b != N {.b.report(level‘| ’)}

T Serial(Resistor)
F (Resistor a, b)
.a = move(b)
.b = a
.symbol = Char(‘+’)

F.virtual.override res() -> Float
R .a.res() + .b.res()

F.virtual.override setVoltage(Float voltage) -> N
V ra = .a.res()
V rb = .b.res()
.a.setVoltage(ra / (ra + rb) * voltage)
.b.setVoltage(rb / (ra + rb) * voltage)
.voltage = voltage

T Parallel(Resistor)
F (Resistor a, b)
.a = move(b)
.b = a
.symbol = Char(‘*’)

F.virtual.override res() -> Float
R 1 / (1 / .a.res() + 1 / .b.res())

F.virtual.override setVoltage(Float voltage) -> N
.a.setVoltage(voltage)
.b.setVoltage(voltage)
.voltage = voltage

F build(s)
[Resistor] stack
L(word) s.split(‘ ’)
I word == ‘+’
Resistor p = stack.pop()
stack.append(Serial(p, stack.pop()))
E I word == ‘*’
Resistor p = stack.pop()
stack.append(Parallel(p, stack.pop()))
E
stack.append(Resistor(Float(word)))
R stack.pop()

Resistor node = build(‘10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +’)
print(‘     Ohm     Volt   Ampere     Watt  Network tree’)
node.setVoltage(18.0)
node.report()```

## CoffeeScript

### RPN

```nd = (num) -> num.toFixed(3).padStart 8

class Resistor
constructor : (@resistance,@a=null,@b=null,@symbol='r') ->
res : -> @resistance
setVoltage : (@voltage) ->
current : -> @voltage / @res()
effect : -> @current() * @voltage
report : (level) ->
print "#{nd @res()} #{nd @voltage} #{nd @current()} #{nd @effect()}  #{level}#{@symbol}"
if @a then @a.report level + "| "
if @b then @b.report level + "| "

class Serial extends Resistor
constructor : (a,b) -> super 0,a,b,'+'
res : -> @a.res() + @b.res()
setVoltage : (@voltage) ->
ra = @a.res()
rb = @b.res()
@a.setVoltage ra/(ra+rb) * @voltage
@b.setVoltage rb/(ra+rb) * @voltage

class Parallel extends Resistor
constructor : (a,b) -> super 0,a,b,'*'
res : -> 1 / (1 / @a.res() + 1 / @b.res())
setVoltage : (@voltage) ->
@a.setVoltage @voltage
@b.setVoltage @voltage

build = (s) ->
stack = []
for word in s.split ' '
if      word == '+' then stack.push new Serial stack.pop(), stack.pop()
else if word == '*' then stack.push new Parallel stack.pop(), stack.pop()
else                     stack.push new Resistor parseFloat word
stack.pop()

node = build "10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +"
node.setVoltage 18.0
print "     Ohm     Volt   Ampere     Watt  Network tree"
node.report ""
```

## Go

### Infix

Translation of: Nim
```package main

import "fmt"

type Resistor struct {
symbol              rune
resistance, voltage float64
a, b                *Resistor
}

func (r *Resistor) res() float64 {
switch r.symbol {
case '+':
return r.a.res() + r.b.res()
case '*':
return 1 / (1/r.a.res() + 1/r.b.res())
default:
return r.resistance
}
}

func (r *Resistor) setVoltage(voltage float64) {
switch r.symbol {
case '+':
ra := r.a.res()
rb := r.b.res()
r.a.setVoltage(ra / (ra + rb) * voltage)
r.b.setVoltage(rb / (ra + rb) * voltage)
case '*':
r.a.setVoltage(voltage)
r.b.setVoltage(voltage)
}
r.voltage = voltage
}

func (r *Resistor) current() float64 {
return r.voltage / r.res()
}

func (r *Resistor) effect() float64 {
return r.current() * r.voltage
}

func (r *Resistor) report(level string) {
fmt.Printf("%8.3f %8.3f %8.3f %8.3f  %s%c\n", r.res(), r.voltage, r.current(), r.effect(), level, r.symbol)
if r.a != nil {
r.a.report(level + "| ")
}
if r.b != nil {
r.b.report(level + "| ")
}
}

func (r *Resistor) add(other *Resistor) *Resistor {
return &Resistor{'+', 0, 0, r, other}
}

func (r *Resistor) mul(other *Resistor) *Resistor {
return &Resistor{'*', 0, 0, r, other}
}

func main() {
var r [10]*Resistor
resistances := []float64{6, 8, 4, 8, 4, 6, 8, 10, 6, 2}
for i := 0; i < 10; i++ {
r[i] = &Resistor{'r', resistances[i], 0, nil, nil}
}
node.setVoltage(18)
fmt.Println("     Ohm     Volt   Ampere     Watt  Network tree")
node.report("")
}
```

### RPN

```package main

import (
"fmt"
"strconv"
"strings"
)

type Stack []*Resistor

func (s *Stack) push(r *Resistor) {
*s = append(*s, r)
}

func (s *Stack) pop() *Resistor {
le := len(*s)
if le == 0 {
panic("Attempt to pop from an empty stack")
}
le--
r := (*s)[le]
*s = (*s)[:le]
return r
}

type Resistor struct {
symbol              rune
resistance, voltage float64
a, b                *Resistor
}

func (r *Resistor) res() float64 {
switch r.symbol {
case '+':
return r.a.res() + r.b.res()
case '*':
return 1 / (1/r.a.res() + 1/r.b.res())
default:
return r.resistance
}
}

func (r *Resistor) setVoltage(voltage float64) {
switch r.symbol {
case '+':
ra := r.a.res()
rb := r.b.res()
r.a.setVoltage(ra / (ra + rb) * voltage)
r.b.setVoltage(rb / (ra + rb) * voltage)
case '*':
r.a.setVoltage(voltage)
r.b.setVoltage(voltage)
}
r.voltage = voltage
}

func (r *Resistor) current() float64 {
return r.voltage / r.res()
}

func (r *Resistor) effect() float64 {
return r.current() * r.voltage
}

func (r *Resistor) report(level string) {
fmt.Printf("%8.3f %8.3f %8.3f %8.3f  %s%c\n", r.res(), r.voltage, r.current(), r.effect(), level, r.symbol)
if r.a != nil {
r.a.report(level + "| ")
}
if r.b != nil {
r.b.report(level + "| ")
}
}

func build(rpn string) *Resistor {
st := new(Stack)
for _, token := range strings.Fields(rpn) {
switch token {
case "+":
b, a := st.pop(), st.pop()
st.push(&Resistor{'+', 0, 0, a, b})
case "*":
b, a := st.pop(), st.pop()
st.push(&Resistor{'*', 0, 0, a, b})
default:
r, _ := strconv.ParseFloat(token, 64)
st.push(&Resistor{'r', r, 0, nil, nil})
}
}
return st.pop()
}

func main() {
node := build("10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +")
node.setVoltage(18)
fmt.Println("     Ohm     Volt   Ampere     Watt  Network tree")
node.report("")
}
```

## Julia

Translation of: Raku

#### Infix

```using Formatting
import Base.+, Base.*

mutable struct Resistor
operator::Char
voltage::Float64
resistance::Float64
a::Union{Resistor, Nothing}
b::Union{Resistor, Nothing}
end

function res(r::Resistor)
if r != nothing
if r.operator == '+'
return res(r.a) + res(r.b)
elseif r.operator == '*'
return 1 / ((1 / res(r.a)) + (1 / res(r.b)))
end
return r.resistance
end
end

function setvoltage(r, voltage)
if r != nothing
if r.operator == '+'
ra = res(r.a)
rb = res(r.b)
setvoltage(r.a, voltage * ra / (ra + rb))
setvoltage(r.b, voltage * rb / (ra + rb))
elseif r.operator == '*'
setvoltage(r.a, voltage)
setvoltage(r.b, voltage)
end
r.voltage = voltage
end
end

current(r) = r.voltage / res(r)

effect(r) = r.voltage * current(r)

function report(r, level=1)
afmt(arr::Vector) = join(map(nfmt, arr), "| ")
println(afmt([res(r), r.voltage, current(r), effect(r)]), "| "^level, r.operator)
if r.a != nothing
report(r.a, level + 1)
end
if r.b != nothing
report(r.b, level + 1)
end
end

Base.:+(a::Resistor, b::Resistor) = Resistor('+',  0.0, 0.0, a, b)
Base.:*(a::Resistor, b::Resistor) = Resistor('*',  0.0, 0.0, a, b)

(R1, R2, R3, R4, R5, R6, R7, R8, R9, R10) =
map(r -> Resistor('r', 0.0, r, nothing, nothing), [6, 8, 4, 8, 4, 6, 8, 10, 6, 2])

node = ((((R8 + R10) * R9 + R7) * R6 + R5) * R4 + R3) * R2 + R1
setvoltage(node, 18)

println("   Ohm        Volt          Ampere        Watt        Network tree")
report(node)
```
Output:
```   Ohm        Volt          Ampere        Watt        Network tree
10.000      | 18.000      | 1.800       | 32.400      | +
4.000       | 7.200       | 1.800       | 12.960      | | *
8.000       | 7.200       | 0.900       | 6.480       | | | +
4.000       | 3.600       | 0.900       | 3.240       | | | | *
8.000       | 3.600       | 0.450       | 1.620       | | | | | +
4.000       | 1.800       | 0.450       | 0.810       | | | | | | *
12.000      | 1.800       | 0.150       | 0.270       | | | | | | | +
4.000       | 0.600       | 0.150       | 0.090       | | | | | | | | *
12.000      | 0.600       | 0.050       | 0.030       | | | | | | | | | +
10.000      | 0.500       | 0.050       | 0.025       | | | | | | | | | | r
2.000       | 0.100       | 0.050       | 0.005       | | | | | | | | | | r
6.000       | 0.600       | 0.100       | 0.060       | | | | | | | | | r
8.000       | 1.200       | 0.150       | 0.180       | | | | | | | | r
6.000       | 1.800       | 0.300       | 0.540       | | | | | | | r
4.000       | 1.800       | 0.450       | 0.810       | | | | | | r
8.000       | 3.600       | 0.450       | 1.620       | | | | | r
4.000       | 3.600       | 0.900       | 3.240       | | | | r
8.000       | 7.200       | 0.900       | 6.480       | | | r
6.000       | 10.800      | 1.800       | 19.440      | | r
```

#### RPN

```function rpn(arr::Vector)
stack = Any[]
for op in arr
if isa(op, Function)
arg2 = pop!(stack)
arg1 = pop!(stack)
push!(stack, op(arg1, arg2))
else
push!(stack, op)
end
end
length(stack) != 1 && error("invalid RPN expression array: \$arr")
return stack[1]
end

node = rpn([R8, R10, +, R9, *, R7, +, R6, *, R5, +, R4, *, R3, +, R2, *, R1, +])
setvoltage(node, 18)
report(node)
```
Output:

Same as infix version.

## Nim

```import strutils, strformat

type
Node = ref object
kind: char  #  + = serial  * = parallel  r = resistor
resistance: float
voltage: float
a: Node
b: Node

proc res(node: Node): float =
if node.kind == '+': return node.a.res + node.b.res
if node.kind == '*': return 1 / (1 / node.a.res + 1 / node.b.res)
node.resistance

proc current(node: Node): float = node.voltage / node.res
proc effect (node: Node): float = node.current * node.voltage

proc report(node: Node, level: string = "") =
echo fmt"{node.res:8.3f} {node.voltage:8.3f} {node.current:8.3f} {node.effect:8.3f}  {level}{node.kind}"
if node.kind in "+*":
node.a.report level & "| "
node.b.report level & "| "

proc setVoltage(node: Node, voltage: float) =
node.voltage = voltage
if node.kind == '+':
let ra = node.a.res
let rb = node.b.res
node.a.setVoltage ra / (ra+rb) * voltage
node.b.setVoltage rb / (ra+rb) * voltage
if node.kind == '*':
node.a.setVoltage voltage
node.b.setVoltage voltage

proc build(tokens: seq[string]): Node =
var stack: seq[Node]
for token in tokens:
stack.add if token == "+": Node(kind: '+', a: stack.pop, b: stack.pop)
elif token == "*": Node(kind: '*', a: stack.pop, b: stack.pop)
else: Node(kind: 'r', resistance: parseFloat(token))
stack.pop

proc calculate(voltage: float, tokens: seq[string]): Node =
echo ""
echo "     Ohm     Volt   Ampere     Watt  Network tree"
let node = build tokens
node.setVoltage voltage
node.report
node
```

### RPN

```proc rpn(voltage:float, s:string): Node = calculate(voltage, s.split ' ')
var node = rpn(18, "10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +")
assert 10 == node.res
assert 18 == node.voltage
assert 1.8 == node.current()
assert 32.4 == node.effect()
assert '+' == node.kind
```

### Infix

```proc parse(s: string): seq[string] =
var tmp = ""
for ch in s:
case ch
of ' ':
if tmp != "": result.add tmp
tmp = ""
continue
of '+', '*', '(', ')':
if tmp != "": result.add tmp
tmp = ""
else:
tmp &= ch
if tmp != "": result.add tmp

proc shuntRPN(s: string): seq[string] =
let ops = "+*"
var tokens = parse s
var stack: seq[string]
var op: string

for token in tokens:
case token
of "(":
of ")":
while stack.len > 0:
op = stack.pop()
if op == "(": break
else:
if token in ops:
while stack.len > 0:
op = stack[^1]
if op notin ops: break
if ops.find(token) >= ops.find(op): break

while stack.len > 0: result.add stack.pop()

proc infix(voltage:float, s:string): Node = calculate(voltage, shuntRPN s)
node = infix(18, "((((10+2)*6+8)*6+4)*8+4)*8+6")
assert 10 == node.res
assert 18 == node.voltage
assert 1.8 == node.current()
assert 32.4 == node.effect()
assert '+' == node.kind
```

## Perl

### Infix

Translation of: Raku
```use v5.36;

package Resistor;
require Exporter;
our @ISA    = qw(Exporter);
our @EXPORT = qw(set_voltage report);

use overload '+' => \&serial, '*' => \&parallel;

sub new (\$class, \$args) {
my \$self = {
symbol     => \$args->{symbol},
voltage    => \$args->{voltage},
resistance => \$args->{resistance},
a          => \$args->{a},
b          => \$args->{b},
};
return bless \$self, \$class;
}

sub res (\$self) {
if    (\$self->{symbol} eq '+') { return res(\$self->{a}) + res(\$self->{b}) }
elsif (\$self->{symbol} eq '*') { return 1 / (1/res(\$self->{a}) + 1/res(\$self->{b})) }
else                           { return \$self->{resistance} }
}

sub set_voltage (\$self,\$voltage) {
if (\$self->{symbol} eq '+') {
my \$ra = res(\$self->{a});
my \$rb = res(\$self->{b});
set_voltage(\$self->{a}, \$ra / (\$ra+\$rb) * \$voltage );
set_voltage(\$self->{b}, \$rb / (\$ra+\$rb) * \$voltage );
} elsif (\$self->{symbol} eq '*') {
set_voltage(\$self->{a}, \$voltage );
set_voltage(\$self->{b}, \$voltage );
}
\$self->{voltage} = \$voltage;
}

sub current (\$self) { return \$self->{voltage} / res(\$self)     }
sub effect  (\$self) { return \$self->{voltage} * current(\$self) }

sub serial   (\$a,\$b,\$) { Resistor->new( {symbol => '+', a => \$a, b => \$b} ) }
sub parallel (\$a,\$b,\$) { Resistor->new( {symbol => '*', a => \$a, b => \$b} ) }

sub report (\$self,\$level = 0) {
state @results;
push @results, '      Ohm     Volt   Ampere     Watt   Network tree' and \$level = 1 unless \$level;
my \$pad = ('| ') x \$level;
my \$f = sprintf '%9.3f' x 4, res(\$self), \$self->{voltage}, current(\$self), effect(\$self);
report(\$self->{a}, \$level+1) if defined \$self->{a};
report(\$self->{b}, \$level+1) if defined \$self->{b};
join "\n", @results;
}

}

package main;
Resistor->import;

my (\$R1, \$R2, \$R3, \$R4, \$R5, \$R6, \$R7, \$R8, \$R9, \$R10) =
map { Resistor->new( {symbol => 'r', resistance => \$_} ) } <6 8 4 8 4 6 8 10 6 2>;

my \$node = ((((\$R8 + \$R10) * \$R9 + \$R7) * \$R6 + \$R5)
* \$R4 + \$R3) * \$R2 + \$R1;

set_voltage(\$node,18);
say report(\$node);
```
Output:
```      Ohm     Volt   Ampere     Watt   Network tree
10.000   18.000    1.800   32.400 | +
4.000    7.200    1.800   12.960 | | *
8.000    7.200    0.900    6.480 | | | +
4.000    3.600    0.900    3.240 | | | | *
8.000    3.600    0.450    1.620 | | | | | +
4.000    1.800    0.450    0.810 | | | | | | *
12.000    1.800    0.150    0.270 | | | | | | | +
4.000    0.600    0.150    0.090 | | | | | | | | *
12.000    0.600    0.050    0.030 | | | | | | | | | +
10.000    0.500    0.050    0.025 | | | | | | | | | | r
2.000    0.100    0.050    0.005 | | | | | | | | | | r
6.000    0.600    0.100    0.060 | | | | | | | | | r
8.000    1.200    0.150    0.180 | | | | | | | | r
6.000    1.800    0.300    0.540 | | | | | | | r
4.000    1.800    0.450    0.810 | | | | | | r
8.000    3.600    0.450    1.620 | | | | | r
4.000    3.600    0.900    3.240 | | | | r
8.000    7.200    0.900    6.480 | | | r
6.000   10.800    1.800   19.440 | | r```

## Phix

```with javascript_semantics
constant RPN = true // or false for infix (same output)
-- node contents:
enum KIND, -- '+', '*', or 'r'
RESISTANCE, VOLTAGE,
A, B   -- nested nodes or NULL

function resistance(sequence node)
switch node[KIND] do
case '+': return resistance(node[A]) + resistance(node[B])
case '*': return 1 / (1/resistance(node[A]) + 1/resistance(node[B]))
case 'r': return node[RESISTANCE]
default: ?9/0 -- unknown node kind
end switch
end function

function setVoltage(sequence node, atom voltage)
integer kind = node[KIND]
atom r = node[RESISTANCE]
--       v = node[VOLTAGE] -- not needed!
object na = node[A],
nb = node[B]
switch kind do
case '+':
atom ra := resistance(na),
rb := resistance(nb)
na = setVoltage(na, ra / (ra + rb) * voltage)
nb = setVoltage(nb, rb / (ra + rb) * voltage)
case '*':
na = setVoltage(na,voltage)
nb = setVoltage(nb,voltage)
end switch
node = {kind,r,voltage,na,nb}
return node
end function

function current(sequence node)
return node[VOLTAGE] / resistance(node)
end function

function effect(sequence node)
return current(node) * node[VOLTAGE]
end function

procedure report(sequence node, string level="")
printf(1,"%8.3f %8.3f %8.3f %8.3f  %s%c\n", {resistance(node), node[VOLTAGE], current(node), effect(node), level, node[KIND]})
if node[A]!=NULL then
report(node[A],level & "| ")
end if
if node[B]!=NULL then
report(node[B],level & "| ")
end if
end procedure

function push_op(sequence stack, string tok)
switch tok do
case "+","*": sequence b = stack[\$],
a = stack[\$-1]
stack = stack[1..\$-1]
stack[\$] = {tok[1], 0, 0, a, b}
default:      integer {{r}} = scanf(tok,"%d")
stack = append(stack,{'r', r, 0, NULL, NULL})
end switch
return stack
end function

-- RPN
function rpn(string s)
sequence stack = {},
tokens = split(s)
for i=1 to length(tokens) do
stack = push_op(stack,tokens[i])
end for
return stack[\$]
end function

-- Infix, slightly trickier:
constant ops = {"+","*"}
function infix(string s)
string lastnum = ""
sequence tokens = {}
for i=1 to length(s) do
integer ch = s[i]
if ch>='0' and ch<='9' then
lastnum &= ch
else
if length(lastnum) then
tokens = append(tokens,lastnum)
lastnum = ""
end if
tokens = append(tokens,ch&"")
end if
end for
if length(lastnum) then
tokens = append(tokens,lastnum)
end if
sequence stack = {}, result = {}
for i=1 to length(tokens) do
string token = tokens[i], op
switch token do
case "(":   stack = append(stack,token)
case ")":   while true do
op = stack[\$]
stack = stack[1..\$-1]
if op == "(" then exit end if
result = push_op(result,op)
end while
else:
integer tp = find(token,ops)
if tp then
while length(stack) do
op = stack[\$]
integer sp = find(op,ops)
if not sp or tp>=sp then exit end if
stack = stack[1..\$-1]
result = push_op(result,op)
end while
stack = append(stack,token)
else
result = push_op(result,token)
end if
end switch
end for
for i=length(stack) to 1 by -1 do
result = push_op(result,stack[i])
end for
return result[1]
end function

sequence node = iff(RPN?rpn("10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +")
:infix("((((10+2)*6+8)*6+4)*8+4)*8+6"))
node = setVoltage(node,18)
printf(1,"     Ohm     Volt   Ampere     Watt  Network tree\n")
report(node,"")
```
Output:
```     Ohm     Volt   Ampere     Watt  Network tree
10.000   18.000    1.800   32.400  +
4.000    7.200    1.800   12.960  | *
8.000    7.200    0.900    6.480  | | +
4.000    3.600    0.900    3.240  | | | *
8.000    3.600    0.450    1.620  | | | | +
4.000    1.800    0.450    0.810  | | | | | *
12.000    1.800    0.150    0.270  | | | | | | +
4.000    0.600    0.150    0.090  | | | | | | | *
12.000    0.600    0.050    0.030  | | | | | | | | +
10.000    0.500    0.050    0.025  | | | | | | | | | r
2.000    0.100    0.050    0.005  | | | | | | | | | r
6.000    0.600    0.100    0.060  | | | | | | | | r
8.000    1.200    0.150    0.180  | | | | | | | r
6.000    1.800    0.300    0.540  | | | | | | r
4.000    1.800    0.450    0.810  | | | | | r
8.000    3.600    0.450    1.620  | | | | r
4.000    3.600    0.900    3.240  | | | r
8.000    7.200    0.900    6.480  | | r
6.000   10.800    1.800   19.440  | r
```

## Python

### RPN

```class Resistor :
def __init__(self, resistance, a=None, b=None, symbol='r'):
self.resistance = resistance
self.a = a
self.b = b
self.symbol = symbol
def res(self) : return self.resistance
def setVoltage(self, voltage): self.voltage = voltage
def current(self) : return self.voltage / self.res()
def effect(self) : return self.current() * self.voltage
def report(self,level=""):
print(f"{self.res():8.3f} {self.voltage:8.3f} {self.current():8.3f} {self.effect():8.3f}  {level}{self.symbol}")
if self.a: self.a.report(level + "| ")
if self.b: self.b.report(level + "| ")

class Serial(Resistor) :
def __init__(self, a, b) : super().__init__(0, b, a, '+')
def res(self) : return self.a.res() + self.b.res()
def setVoltage(self, voltage) :
ra = self.a.res()
rb = self.b.res()
self.a.setVoltage(ra/(ra+rb) * voltage)
self.b.setVoltage(rb/(ra+rb) * voltage)
self.voltage = voltage

class Parallel(Resistor) :
def __init__(self,a,b) : super().__init__(0, b, a, '*')
def res(self) : return 1 / (1 / self.a.res() + 1 / self.b.res())
def setVoltage(self, voltage) :
self.a.setVoltage(voltage)
self.b.setVoltage(voltage)
self.voltage = voltage

def build(s) :
stack = []
for word in s.split(' '):
if   word == "+": stack.append(Serial(stack.pop(), stack.pop()))
elif word == "*": stack.append(Parallel(stack.pop(), stack.pop()))
else:             stack.append(Resistor(float(word)))
return stack.pop()

node = build("10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +")
print("     Ohm     Volt   Ampere     Watt  Network tree")
node.setVoltage(18.0)
node.report()
```

### Infix

```class Resistor :
def __init__(self, resistance, a=None, b=None, symbol='r') :
self.resistance = resistance
self.a = a
self.b = b
self.symbol = symbol
def res(self) : return self.resistance
def setVoltage(self, voltage) : self.voltage = voltage
def current(self) : return self.voltage / self.res()
def effect(self) : return self.current() * self.voltage
def report(self,level="") :
print(f"{self.res():8.3f} {self.voltage:8.3f} {self.current():8.3f} {self.effect():8.3f}  {level}{self.symbol}")
if self.a: self.a.report(level + "| ")
if self.b: self.b.report(level + "| ")
def __mul__(self,other) : return Parallel(self,other)

class Serial(Resistor) :
def __init__(self, a, b) : super().__init__(0, a, b, '+')
def res(self) : return self.a.res() + self.b.res()
def setVoltage(self, voltage) :
ra = self.a.res()
rb = self.b.res()
self.a.setVoltage(ra/(ra+rb) * voltage)
self.b.setVoltage(rb/(ra+rb) * voltage)
self.voltage = voltage

class Parallel(Resistor) :
def __init__(self,a,b) : super().__init__(0, a, b, '*')
def res(self) : return 1 / (1 / self.a.res() + 1 / self.b.res())
def setVoltage(self, voltage):
self.a.setVoltage(voltage)
self.b.setVoltage(voltage)
self.voltage = voltage

[R1,R2,R3,R4,R5,R6,R7,R8,R9,R10] = [Resistor(res) for res in [6,8,4,8,4,6,8,10,6,2]]
node = ((((R8+R10) * R9 + R7) * R6 + R5) * R4 + R3) * R2 + R1
node.setVoltage(18)
print("     Ohm     Volt   Ampere     Watt  Network tree")
node.report()
```

## Raku

(formerly Perl 6)

### Infix

Translation of: Nim
```class Resistor {
has Str        \$.symbol;
has Numeric  ( \$.voltage, \$.resistance );
has Resistor ( \$.a, \$.b );

method res ( ) {
given \$.symbol {
when '+' { return \$.a.res + \$.b.res }
when '*' { return 1 / (1 / \$.a.res  +  1 / \$.b.res) }
default  { return \$.resistance }
}
}

method set-voltage ( Numeric \$voltage ) {
given \$.symbol {
when '+' {
my \$ra = \$.a.res;
my \$rb = \$.b.res;
\$.a.set-voltage( \$ra / (\$ra+\$rb) * \$voltage );
\$.b.set-voltage( \$rb / (\$ra+\$rb) * \$voltage );
}
when '*' {
\$.a.set-voltage( \$voltage );
\$.b.set-voltage( \$voltage );
}
}
\$!voltage = \$voltage;
}
method current ( ) { return \$.voltage / self.res     }
method effect  ( ) { return \$.voltage * self.current }

method report ( Int \$level = 1 ) {
my \$pad = '| ' x \$level;
my \$f = ( self.res, \$.voltage, self.current, self.effect ).fmt('%8.3f');
\$.a.report( \$level+1 ) if \$.a;
\$.b.report( \$level+1 ) if \$.b;
}
}
multi sub infix:<+> (Resistor \$a, Resistor \$b) { \$a.new( symbol => '+', :\$a, :\$b ) }
multi sub infix:<*> (Resistor \$a, Resistor \$b) { \$a.new( symbol => '*', :\$a, :\$b ) }

my Resistor (\$R1, \$R2, \$R3, \$R4, \$R5, \$R6, \$R7, \$R8, \$R9, \$R10) =
map { Resistor.new: symbol => 'r', resistance => \$_ },
6, 8, 4, 8, 4, 6, 8, 10, 6, 2;

my \$node = ((((\$R8 + \$R10) * \$R9 + \$R7) * \$R6 + \$R5)
* \$R4 + \$R3) * \$R2 + \$R1;
\$node.set-voltage(18);

say '     Ohm     Volt   Ampere     Watt  Network tree';
\$node.report;
```
Output:
```     Ohm     Volt   Ampere     Watt  Network tree
10.000   18.000    1.800   32.400 | +
4.000    7.200    1.800   12.960 | | *
8.000    7.200    0.900    6.480 | | | +
4.000    3.600    0.900    3.240 | | | | *
8.000    3.600    0.450    1.620 | | | | | +
4.000    1.800    0.450    0.810 | | | | | | *
12.000    1.800    0.150    0.270 | | | | | | | +
4.000    0.600    0.150    0.090 | | | | | | | | *
12.000    0.600    0.050    0.030 | | | | | | | | | +
10.000    0.500    0.050    0.025 | | | | | | | | | | r
2.000    0.100    0.050    0.005 | | | | | | | | | | r
6.000    0.600    0.100    0.060 | | | | | | | | | r
8.000    1.200    0.150    0.180 | | | | | | | | r
6.000    1.800    0.300    0.540 | | | | | | | r
4.000    1.800    0.450    0.810 | | | | | | r
8.000    3.600    0.450    1.620 | | | | | r
4.000    3.600    0.900    3.240 | | | | r
8.000    7.200    0.900    6.480 | | | r
6.000   10.800    1.800   19.440 | | r```

## Wren

### Infix

Translation of: Go
Library: Wren-fmt
```import "./fmt" for Fmt

class Resistor {
construct new(symbol, resistance, voltage, a, b) {
_symbol = symbol
_resistance = resistance
_voltage = voltage
_a = a
_b = b
}

symbol { _symbol }
resistance { _resistance }
voltage { _voltage}

res {
if (_symbol == "+") return _a.res + _b.res
if (_symbol == "*") return 1 / (1/_a.res + 1/_b.res)
return _resistance
}

current { _voltage / res }

effect { current * _voltage }

voltage=(v) {
if (_symbol == "+") {
var ra = _a.res
var rb = _b.res
_a.voltage = ra / (ra + rb) * v
_b.voltage = rb / (ra + rb) * v
} else if (_symbol == "*") {
_a.voltage = v
_b.voltage = v
}
_voltage = v
}

report(level) {
Fmt.lprint("\$8.3f \$8.3f \$8.3f \$8.3f  \$s\$s", [res, _voltage, current, effect, level, symbol])
if (_a != null) _a.report(level + "| ")
if (_b != null) _b.report(level + "| ")
}

+(other) { Resistor.new("+", 0, 0, this, other) }
*(other) { Resistor.new("*", 0, 0, this, other) }
}

var r = List.filled(10, null)
var resistances = [6, 8, 4, 8, 4, 6, 8, 10, 6, 2]
for (i in 0..9) r[i] = Resistor.new("r", resistances[i], 0, null, null)
var node = ((((r[7]+r[9])*r[8]+r[6])*r[5]+r[4])*r[3]+r[2])*r[1] + r[0]
node.voltage = 18
System.print("     Ohm     Volt   Ampere     Watt  Network tree")
node.report("")
```
Output:
```     Ohm     Volt   Ampere     Watt  Network tree
10.000   18.000    1.800   32.400   +
4.000    7.200    1.800   12.960  | *
8.000    7.200    0.900    6.480  | | +
4.000    3.600    0.900    3.240  | | | *
8.000    3.600    0.450    1.620  | | | | +
4.000    1.800    0.450    0.810  | | | | | *
12.000    1.800    0.150    0.270  | | | | | | +
4.000    0.600    0.150    0.090  | | | | | | | *
12.000    0.600    0.050    0.030  | | | | | | | | +
10.000    0.500    0.050    0.025  | | | | | | | | | r
2.000    0.100    0.050    0.005  | | | | | | | | | r
6.000    0.600    0.100    0.060  | | | | | | | | r
8.000    1.200    0.150    0.180  | | | | | | | r
6.000    1.800    0.300    0.540  | | | | | | r
4.000    1.800    0.450    0.810  | | | | | r
8.000    3.600    0.450    1.620  | | | | r
4.000    3.600    0.900    3.240  | | | r
8.000    7.200    0.900    6.480  | | r
6.000   10.800    1.800   19.440  | r

```

### RPN

Library: Wren-seq
```import "./fmt" for Fmt
import "./seq" for Stack

class Resistor {
construct new(symbol, resistance, voltage, a, b) {
_symbol = symbol
_resistance = resistance
_voltage = voltage
_a = a
_b = b
}

symbol { _symbol }
resistance { _resistance }
voltage { _voltage}

res {
if (_symbol == "+") return _a.res + _b.res
if (_symbol == "*") return 1 / (1/_a.res + 1/_b.res)
return _resistance
}

current { _voltage / res }

effect { current * _voltage }

voltage=(v) {
if (_symbol == "+") {
var ra = _a.res
var rb = _b.res
_a.voltage = ra / (ra + rb) * v
_b.voltage = rb / (ra + rb) * v
} else if (_symbol == "*") {
_a.voltage = v
_b.voltage = v
}
_voltage = v
}

report(level) {
Fmt.lprint("\$8.3f \$8.3f \$8.3f \$8.3f  \$s\$s", [res, _voltage, current, effect, level, symbol])
if (_a != null) _a.report(level + "| ")
if (_b != null) _b.report(level + "| ")
}

+(other) { Resistor.new("+", 0, 0, this, other) }
*(other) { Resistor.new("*", 0, 0, this, other) }
}

var build = Fn.new { |rpn|
var st = Stack.new()
for (token in rpn.split(" ")) {
if (token == "+") {
var b = st.pop()
var a = st.pop()
st.push(Resistor.new("+", 0, 0, a, b))
} else if (token == "*") {
var b = st.pop()
var a = st.pop()
st.push(Resistor.new("*", 0, 0, a, b))
} else {
var r = Num.fromString(token)
st.push(Resistor.new("r", r, 0, null, null))
}
}
return st.pop()
}

var node = build.call("10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +")
node.voltage = 18
System.print("     Ohm     Volt   Ampere     Watt  Network tree")
node.report("")
```
Output:
```Same as Infix version
```

## Zig

Translation of: Nim
Works with: Zig version 0.11dev

Zig requires more "code" than dynamic languages. The following three items account for a good portion of the "extra code".

• There are no hidden memory allocations. Manual memory management.
• Errors are values, and may not be ignored.
• Generic data structures and functions.

### Postfix (RPN)

```// postfix.zig
const std = @import("std");
const Allocator = std.mem.Allocator;
const Node = @import("common.zig").Node;
const PostfixToken = @import("common.zig").PostfixToken;
const calculate = @import("common.zig").calculate;

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer {
const ok = gpa.deinit();
std.debug.assert(ok == .ok);
}
const allocator = gpa.allocator();

const stdout = std.io.getStdOut().writer();

const node = try postfix(allocator, stdout, 18, "10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +");

std.debug.assert(10 == node.res());
std.debug.assert(18 == node.voltage);
std.debug.assert(1.8 == node.current());
std.debug.assert(std.math.fabs(32.4 - node.effect()) < 0.05);
std.debug.assert(.serial == node.node_type);

node.destroyDescendants(allocator);
allocator.destroy(node);
}

/// Also know as RPN (Reverse Polish Notation)
fn postfix(allocator: Allocator, writer: anytype, voltage: f32, s: []const u8) !*Node {
const tokens = try parse(allocator, s);
defer allocator.free(tokens);

return try calculate(allocator, writer, voltage, tokens);
}

const PostfixParseError = error{
UnexpectedCharacter,
};

/// Parse postfix expression 's' to give a slice of PostfixToken.
/// Caller owns slice memory on return.
/// There are no Zig language semantics to indicate ownership or transferal thereof.
fn parse(allocator: Allocator, s: []const u8) ![]PostfixToken {
var tokens = std.ArrayList(PostfixToken).init(allocator);
// defer tokens.deinit(); // not needed, toOwnedSlice() owns memory.

var slice_start: ?usize = null;

// convert the string to a list of Token
for (s, 0..) |ch, i| {
const token: PostfixToken = switch (ch) {
'+' => PostfixToken.serial,
'*' => PostfixToken.parallel,
'0'...'9' => {
// Add digits to 'resistor' value.
// 'slice_start' determines if any digit(s) have already been parsed.
if (slice_start) |_| _ = tokens.pop() else slice_start = i;
const slice_end = i + 1;
try tokens.append(PostfixToken{ .resistor = s[slice_start.?..slice_end] });
continue;
},
' ', '\t' => {
slice_start = null;
continue;
},
else => return PostfixParseError.UnexpectedCharacter,
};
try tokens.append(token);
// Last token was not a resistor. Reset 'start_slice'.
slice_start = null;
}
}
```

### Infix

```// infix.zig
const std = @import("std");
const Allocator = std.mem.Allocator;
const Stack = @import("common.zig").Stack;
const Node = @import("common.zig").Node;
const PostfixToken = @import("common.zig").PostfixToken;
const calculate = @import("common.zig").calculate;

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer {
const ok = gpa.deinit();
std.debug.assert(ok == .ok);
}
const allocator = gpa.allocator();

const stdout = std.io.getStdOut().writer();

const node = try infix(allocator, stdout, 18, "((((10+2)*6+8)*6+4)*8+4)*8+6");

std.debug.assert(10 == node.res());
std.debug.assert(18 == node.voltage);
std.debug.assert(1.8 == node.current());
std.debug.assert(std.math.fabs(32.4 - node.effect()) < 0.05);
std.debug.assert(.serial == node.node_type);

node.destroyDescendants(allocator);
allocator.destroy(node);
}

// Zig tagged union.
const InfixToken = union(enum) {
lparen,
rparen,
serial, // +
parallel, // *

// Slice of digits from parent string.
// Do not let the parent string go out of scope while this is in scope.
resistor: []const u8,
};

/// Convert infix expression 's' to postfix and call the postfix calculate()
fn infix(allocator: Allocator, writer: anytype, voltage: f32, s: []const u8) !*Node {
// parse infix expression
const infix_tokens: []InfixToken = try parse(allocator, s);
defer allocator.free(infix_tokens);

// convert infix to postfix
const postfix_tokens: []PostfixToken = try shuntPostfix(allocator, infix_tokens);
defer allocator.free(postfix_tokens);

// use postfix calculate()
return try calculate(allocator, writer, voltage, postfix_tokens);
}

const InfixParseError = error{
UnexpectedCharacter,
};

/// Parse infix expression 's' to give a slice of InfixToken.
/// Caller owns slice memory on return.
/// There are no Zig language semantics to indicate ownership or transferal thereof.
fn parse(allocator: Allocator, s: []const u8) ![]InfixToken {
var tokens = std.ArrayList(InfixToken).init(allocator);
// defer tokens.deinit(); // not needed, toOwnedSlice() owns memory.

var slice_start: ?usize = null;

for (s, 0..) |ch, i| {
const token: InfixToken = switch (ch) {
'(' => InfixToken.lparen,
')' => InfixToken.rparen,
'+' => InfixToken.serial,
'*' => InfixToken.parallel,
'0'...'9' => {
// Add digits to 'resistor' value.
// 'slice_start' determines if any digit(s) have already been parsed.
if (slice_start) |_| _ = tokens.pop() else slice_start = i;
const slice_end = i + 1;
try tokens.append(InfixToken{ .resistor = s[slice_start.?..slice_end] });
continue;
},
' ', '\t' => { // extraneous whitespace
slice_start = null;
continue;
},
else => return InfixParseError.UnexpectedCharacter, // unknown
};
try tokens.append(token);
// Last token was not a resistor. Reset 'start_slice'.
slice_start = null;
}
}

const ShuntPostfixError = error{
LParenNotAllowed,
RParenNotAllowed,
};

/// Input infix (infix tokens) in infix order.
/// Output postfix (postfix tokens) in postfix order.
///
fn shuntPostfix(allocator: Allocator, infix_tokens: []InfixToken) ![]PostfixToken {
var result = PostfixTokenArray.init(allocator); // destination storage
var stack = InfixTokenStack.init(allocator); // working storage
defer result.deinit();
defer stack.deinit();

for (infix_tokens) |token| {
switch (token) {
.lparen => try stack.push(token),
.rparen => while (!stack.isEmpty()) {
const op = stack.pop();
if (op == InfixToken.lparen) break;
try result.append(op);
},
.parallel, .serial => {
while (!stack.isEmpty()) {
const op = stack.peek();
if (op != InfixToken.serial and op != InfixToken.parallel) break;
_ = stack.pop();
try result.append(op);
}
try stack.push(token);
},
.resistor => try result.append(token),
}
}
while (!stack.isEmpty())
try result.append(stack.pop());

// array now contains operands and operators in postfix order (no parentheses)
return result.toOwnedSlice();
}

const InfixTokenStack = Stack(InfixToken);

/// Façade to an ArrayList that translates from InfixToken tagged unions to
/// PostfixToken tagged unions in its append() function.
const PostfixTokenArray = struct {
result: std.ArrayList(PostfixToken),

fn init(allocator: Allocator) PostfixTokenArray {
return PostfixTokenArray{
.result = std.ArrayList(PostfixToken).init(allocator),
};
}
fn deinit(self: *PostfixTokenArray) void {
self.result.deinit();
}
/// Convert InfixToken to PostfixToken.
fn append(self: *PostfixTokenArray, infix_token: InfixToken) !void {
const postfix_token: PostfixToken = switch (infix_token) {
.serial => PostfixToken.serial,
.parallel => PostfixToken.parallel,
.resistor => |slice| PostfixToken{ .resistor = slice },

// Postfix does not have parentheses.
.lparen => return ShuntPostfixError.LParenNotAllowed,
.rparen => return ShuntPostfixError.RParenNotAllowed,
};
try self.result.append(postfix_token);
}
fn toOwnedSlice(self: *PostfixTokenArray) !std.ArrayList(PostfixToken).Slice {
return try self.result.toOwnedSlice();
}
};
```

### Shared Infix/Postfix Code

```// common.zig
const std = @import("std");
const Allocator = std.mem.Allocator;

// Zig "enum"
const NodeType = enum {
serial,
parallel,
resistor,

fn repr(self: NodeType) u8 {
return switch (self) {
.serial => '+',
.parallel => '*',
.resistor => 'r',
};
}
};

// Zig "tagged union"
pub const PostfixToken = union(NodeType) {
serial, // '+'
parallel, // '*'

// Slice of digits from parent string.
// Do not let the parent string go out of scope while this is in scope.
resistor: []const u8, // 'r'
};

// Zig "struct"
pub const Node = struct {
node_type: NodeType,
resistance: ?f32 = null, // optional float, either value or null
voltage: ?f32 = null,
a: ?*Node = null, // optional pointer to Node, either value or null
b: ?*Node = null,

pub fn res(self: *Node) f32 {
return switch (self.node_type) {
.serial => self.a.?.res() + self.b.?.res(),
.parallel => 1 / (1 / self.a.?.res() + 1 / self.b.?.res()),
.resistor => if (self.resistance) |resistance| resistance else unreachable,
};
}

pub fn current(self: *Node) f32 {
if (self.voltage) |voltage| return voltage / self.res() else unreachable;
}

pub fn effect(self: *Node) f32 {
if (self.voltage) |voltage| return self.current() * voltage else unreachable;
}

pub fn setVoltage(self: *Node, voltage: f32) void {
self.voltage = voltage;
switch (self.node_type) {
.serial => {
const ra: f32 = self.a.?.res();
const rb: f32 = self.b.?.res();
self.a.?.setVoltage(ra / (ra + rb) * voltage);
self.b.?.setVoltage(rb / (ra + rb) * voltage);
},
.parallel => {
self.a.?.setVoltage(voltage);
self.b.?.setVoltage(voltage);
},
.resistor => {},
}
}

pub fn report(self: *Node, allocator: Allocator, writer: anytype, level: []const u8) !void {
if (self.voltage) |voltage| {
try writer.print("{d:8.3} {d:8.3} {d:8.3} {d:8.3}  {s}{c}\n", .{
self.res(),    voltage, self.current(),
self.effect(), level,   self.node_type.repr(),
});
} else unreachable;
// iterate though 'a' and 'b' optional nodes
for ([2]?*Node{ self.a, self.b }) |optional_node| {
if (optional_node) |node| {
const next_level = try std.fmt.allocPrint(allocator, "{s}| ", .{level});
defer allocator.free(next_level);
try node.report(allocator, writer, next_level);
}
}
}

/// Free memory allocated to Node descendants and Node itself.
pub fn destroyDescendants(self: *Node, allocator: Allocator) void {
if (self.a) |a| {
self.a = null;
a.destroyDescendants(allocator);
allocator.destroy(a);
}
if (self.b) |b| {
self.b = null;
b.destroyDescendants(allocator);
allocator.destroy(b);
}
}
};

fn build(allocator: Allocator, tokens: []PostfixToken) !*Node {
var stack = Stack(*Node).init(allocator);
defer stack.deinit();

for (tokens) |token| {
const node = try allocator.create(Node);

// 'token' is a tagged union.
// note the extraction of the '.resistor' variable via |r|
node.* = switch (token) {
.serial => Node{ .node_type = NodeType.serial, .b = stack.pop(), .a = stack.pop() },
.parallel => Node{ .node_type = NodeType.parallel, .b = stack.pop(), .a = stack.pop() },
.resistor => |r| Node{ .node_type = NodeType.resistor, .resistance = try std.fmt.parseFloat(f32, r) },
};
try stack.push(node);
}
std.debug.assert(stack.hasOne()); // stack length should be 1.

return stack.pop();
}

pub fn calculate(allocator: Allocator, writer: anytype, voltage: f32, tokens: []PostfixToken) !*Node {
try writer.print("     Ohm     Volt   Ampere     Watt  Network tree\n", .{});

var node = try build(allocator, tokens);
node.setVoltage(voltage);
try node.report(allocator, writer, "");
return node;
}

// Zig "Generic Data Structure"
// An ad hoc generic stack implementation.
// 'pub' is the Zig way of giving visibility outside module scope.
pub fn Stack(comptime T: type) type {
return struct {
const Self = @This();
stack: std.ArrayList(T),

pub fn init(allocator: Allocator) Self {
return Self{
.stack = std.ArrayList(T).init(allocator),
};
}
pub fn deinit(self: *Self) void {
self.stack.deinit();
}
pub fn push(self: *Self, node: T) !void {
return try self.stack.append(node);
}
pub fn pop(self: *Self) T {
return self.stack.pop();
}
pub fn peek(self: *const Self) T {
return self.stack.items[self.stack.items.len - 1];
}
pub fn isEmpty(self: *const Self) bool {
return self.stack.items.len == 0;
}
// no 'pub' - private to this module
fn hasOne(self: *Self) bool {
return self.stack.items.len == 1;
}
};
}
```

## zkl

```class Resistor{
fcn init(resistance_,symbol_="r", a_=Void, b_=Void){
var resistance,a,b,symbol, voltage=Void;
resistance,symbol,a,b = vm.arglist;
resistance=resistance.toFloat();  // deal with strings/ints
}
fcn res{
if     (symbol=="+") a.res() + b.res();
else if(symbol=="*") 1.0/(1.0/a.res() + 1.0/b.res());
else                 resistance
}
fcn setVoltage(voltage){
if(symbol=="+"){
ra,rb := a.res(), b.res();
a.setVoltage(ra/(ra + rb)*voltage);
b.setVoltage(rb/(ra + rb)*voltage);
}
else if(symbol=="*") T(a,b).apply2("setVoltage",voltage);
self.voltage = voltage.toFloat();
}
fcn current{ voltage/res()     }
fcn effect { current()*voltage }
fcn report(level=""){
println("%8.3f %8.3f %8.3f %8.3f  %s%s".fmt(res(),voltage,current(),effect(),level,symbol));
T(a,b).apply2("report",level + "| ");  // noop if Void
}
fcn __opMul(other){ Resistor(0,"*",self,other) }
}```

### Infix

```R1,R2,R3,R4,R5,R6,R7,R8,R9,R10 := T(6,8,4,8,4,6,8,10,6,2].apply(Resistor);
node:=((((R8 + R10)*R9 + R7)*R6 + R5)*R4 + R3)*R2 + R1;
node.setVoltage(18);
println("     Ohm     Volt   Ampere     Watt  Network tree");
node.report();```
Output:
```     Ohm     Volt   Ampere     Watt  Network tree
10.000   18.000    1.800   32.400  +
4.000    7.200    1.800   12.960  | *
8.000    7.200    0.900    6.480  | | +
4.000    3.600    0.900    3.240  | | | *
8.000    3.600    0.450    1.620  | | | | +
4.000    1.800    0.450    0.810  | | | | | *
12.000    1.800    0.150    0.270  | | | | | | +
4.000    0.600    0.150    0.090  | | | | | | | *
12.000    0.600    0.050    0.030  | | | | | | | | +
10.000    0.500    0.050    0.025  | | | | | | | | | r
2.000    0.100    0.050    0.005  | | | | | | | | | r
6.000    0.600    0.100    0.060  | | | | | | | | r
8.000    1.200    0.150    0.180  | | | | | | | r
6.000    1.800    0.300    0.540  | | | | | | r
4.000    1.800    0.450    0.810  | | | | | r
8.000    3.600    0.450    1.620  | | | | r
4.000    3.600    0.900    3.240  | | | r
8.000    7.200    0.900    6.480  | | r
6.000   10.800    1.800   19.440  | r
```

### RPN

```fcn build(rpnStr){
stack:=List();
foreach symbol in (rpnStr.split()){
if(symbol=="+"){
a,b:=stack.pop(),stack.pop();
stack.append(Resistor(0,"+",b,a))
}
else if(symbol=="*"){
a,b:=stack.pop(),stack.pop();
stack.append(Resistor(0,"*",b,a))
}
else stack.append(Resistor(symbol,"r"));
}
stack.pop()	// unevaluated top of circuit
}

node:=build("10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +");
node.setVoltage(18);
println("     Ohm     Volt   Ampere     Watt  Network tree");
node.report();```
Output:
```     Ohm     Volt   Ampere     Watt  Network tree
10.000   18.000    1.800   32.400  +
4.000    7.200    1.800   12.960  | *
8.000    7.200    0.900    6.480  | | +
4.000    3.600    0.900    3.240  | | | *
8.000    3.600    0.450    1.620  | | | | +
4.000    1.800    0.450    0.810  | | | | | *
12.000    1.800    0.150    0.270  | | | | | | +
4.000    0.600    0.150    0.090  | | | | | | | *
12.000    0.600    0.050    0.030  | | | | | | | | +
10.000    0.500    0.050    0.025  | | | | | | | | | r
2.000    0.100    0.050    0.005  | | | | | | | | | r
6.000    0.600    0.100    0.060  | | | | | | | | r
8.000    1.200    0.150    0.180  | | | | | | | r
6.000    1.800    0.300    0.540  | | | | | | r
4.000    1.800    0.450    0.810  | | | | | r
8.000    3.600    0.450    1.620  | | | | r
4.000    3.600    0.900    3.240  | | | r
8.000    7.200    0.900    6.480  | | r
6.000   10.800    1.800   19.440  | r
```