Resistance calculator: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added 11l [RPN])
(Added FreeBASIC)
(9 intermediate revisions by 7 users not shown)
Line 48: Line 48:
{{trans|Python}}
{{trans|Python}}
===RPN===
===RPN===
<lang 11l>T Resistor
<syntaxhighlight lang="11l">T Resistor
Float resistance
Float resistance
voltage = 0.0
voltage = 0.0
Resistor? a
Resistor? a, b
Resistor? b
Char symbol
Char symbol


Line 120: Line 119:
print(‘ Ohm Volt Ampere Watt Network tree’)
print(‘ Ohm Volt Ampere Watt Network tree’)
node.setVoltage(18.0)
node.setVoltage(18.0)
node.report()</lang>
node.report()</syntaxhighlight>


=={{header|CoffeeScript}}==
=={{header|CoffeeScript}}==
===RPN===
===RPN===
<lang coffeescript>nd = (num) -> num.toFixed(3).padStart 8
<syntaxhighlight lang="coffeescript">nd = (num) -> num.toFixed(3).padStart 8


class Resistor
class Resistor
Line 164: Line 163:
node.setVoltage 18.0
node.setVoltage 18.0
print " Ohm Volt Ampere Watt Network tree"
print " Ohm Volt Ampere Watt Network tree"
node.report ""</lang>
node.report ""</syntaxhighlight>

=={{header|FreeBASIC}}==
===Infix===
{{trans|Go}}
<syntaxhighlight lang="vbnet">Const NULL As Any Ptr = 0

Type Resistor
symbol As String
resistance As Double
voltage As Double
a As Resistor Ptr
b As Resistor Ptr
End Type

Function res(r As Resistor Ptr) As Double
Select Case r->symbol
Case "+"
Return res(r->a) + res(r->b)
Case "*"
Return 1 / (1 / res(r->a) + 1 / res(r->b))
Case Else
Return r->resistance
End Select
End Function

Sub setVoltage(r As Resistor Ptr, voltage As Double)
Select Case r->symbol
Case "+"
Dim ra As Double = res(r->a)
Dim rb As Double = res(r->b)
setVoltage(r->a, ra / (ra + rb) * voltage)
setVoltage(r->b, rb / (ra + rb) * voltage)
Case "*"
setVoltage(r->a, voltage)
setVoltage(r->b, voltage)
End Select
r->voltage = voltage
End Sub

Function current(r As Resistor Ptr) As Double
Return r->voltage / res(r)
End Function

Function effect(r As Resistor Ptr) As Double
Return current(r) * r->voltage
End Function

Sub report(r As Resistor Ptr, level As String)
Print Using "###.### ###.### ###.### ###.### & &"; res(r); r->voltage; current(r); effect(r); level; r->symbol
If r->a <> NULL Then report(r->a, level + " |")
If r->b <> NULL Then report(r->b, level + " |")
End Sub

Function sum(r1 As Resistor Ptr, r2 As Resistor Ptr) As Resistor Ptr
Dim r As Resistor Ptr = Callocate(1, Sizeof(Resistor))
r->symbol = "+"
r->a = r1
r->b = r2
Return r
End Function

Function mul(r1 As Resistor Ptr, r2 As Resistor Ptr) As Resistor Ptr
Dim r As Resistor Ptr = Callocate(1, Sizeof(Resistor))
r->symbol = "*"
r->a = r1
r->b = r2
Return r
End Function

Dim As Resistor Ptr r(9)
Dim As Double resistances(9) = {6, 8, 4, 8, 4, 6, 8, 10, 6, 2}
For i As Integer = 0 To 9
r(i) = Callocate(1, Sizeof(Resistor))
r(i)->symbol = "r"
r(i)->resistance = resistances(i)
Next
Dim As Resistor Ptr node
node = sum(r(7), r(9))
node = mul(node, r(8))
node = sum(node, r(6))
node = mul(node, r(5))
node = sum(node, r(4))
node = mul(node, r(3))
node = sum(node, r(2))
node = mul(node, r(1))
node = sum(node, r(0))
setVoltage(node, 18)
Print " Ohm Volt Ampere Watt Network tree"
report(node, "")

Sleep</syntaxhighlight>
{{out}}
<pre> 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
</pre>

===RPN===
{{trans|Go}}
<syntaxhighlight lang="vbnet">Const NULL As Any Ptr = 0

Type Resistor
symbol As String
resistance As Double
voltage As Double
a As Resistor Ptr
b As Resistor Ptr
End Type

Sub push(s() As Resistor Ptr, r As Resistor Ptr)
Redim Preserve s(Ubound(s) + 1)
s(Ubound(s)) = r
End Sub

Sub pop(s() As Resistor Ptr, Byref r As Resistor Ptr)
r = s(Ubound(s))
Redim Preserve s(Ubound(s) - 1)
End Sub

Function res(r As Resistor Ptr) As Double
Select Case r->symbol
Case "+"
Return res(r->a) + res(r->b)
Case "*"
Return 1 / (1 / res(r->a) + 1 / res(r->b))
Case Else
Return r->resistance
End Select
End Function

Sub setVoltage(r As Resistor Ptr, voltage As Double)
Select Case r->symbol
Case "+"
Dim ra As Double = res(r->a)
Dim rb As Double = res(r->b)
setVoltage(r->a, ra / (ra + rb) * voltage)
setVoltage(r->b, rb / (ra + rb) * voltage)
Case "*"
setVoltage(r->a, voltage)
setVoltage(r->b, voltage)
End Select
r->voltage = voltage
End Sub

Function current(r As Resistor Ptr) As Double
Return r->voltage / res(r)
End Function

Function effect(r As Resistor Ptr) As Double
Return current(r) * r->voltage
End Function

Sub report(r As Resistor Ptr, level As String)
Print Using "###.### ###.### ###.### ###.### & &"; res(r); r->voltage; current(r); effect(r); level; r->symbol
If r->a <> NULL Then report(r->a, level + " |")
If r->b <> NULL Then report(r->b, level + " |")
End Sub

Sub splitString(s As String, delim As String, result() As String)
Dim As Integer start = 1, endd
While start <= Len(s)
endd = Instr(start, s, delim)
If endd = 0 Then endd = Len(s) + 1
Redim Preserve result(Ubound(result) + 1)
result(Ubound(result)) = Mid(s, start, endd - start)
start = endd + Len(delim)
Wend
End Sub

Sub build(rpn As String, Byref node As Resistor Ptr)
Dim As Resistor Ptr s()
Dim As String tokens()
splitString(rpn, " ", tokens())
Dim As Integer i
For i = 0 To Ubound(tokens)
Dim As Resistor Ptr r = Callocate(1, Sizeof(Resistor))
Select Case tokens(i)
Case "+", "*"
pop(s(), r->b)
pop(s(), r->a)
r->symbol = tokens(i)
Case Else
r->resistance = Val(tokens(i))
r->symbol = "r"
End Select
push(s(), r)
Next
pop(s(), node)
End Sub

Dim As Resistor Ptr node
build("10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +", node)
setVoltage(node, 18)
Print " Ohm Volt Ampere Watt Network tree"
report(node, "")

Sleep</syntaxhighlight>
{{out}}
<pre>Same as Infix version</pre>


=={{header|Go}}==
=={{header|Go}}==
===Infix===
===Infix===
{{trans|Nim}}
{{trans|Nim}}
<lang go>package main
<syntaxhighlight lang="go">package main


import "fmt"
import "fmt"
Line 240: Line 455:
fmt.Println(" Ohm Volt Ampere Watt Network tree")
fmt.Println(" Ohm Volt Ampere Watt Network tree")
node.report("")
node.report("")
}</lang>
}</syntaxhighlight>


===RPN===
===RPN===
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 340: Line 555:
fmt.Println(" Ohm Volt Ampere Watt Network tree")
fmt.Println(" Ohm Volt Ampere Watt Network tree")
node.report("")
node.report("")
}</lang>
}</syntaxhighlight>


=={{header|Julia}}==
=={{header|Julia}}==
{{trans|Raku}}
{{trans|Raku}}
====Infix====
====Infix====
<lang julia>using Formatting
<syntaxhighlight lang="julia">using Formatting
import Base.+, Base.*
import Base.+, Base.*


Line 409: Line 624:
println(" Ohm Volt Ampere Watt Network tree")
println(" Ohm Volt Ampere Watt Network tree")
report(node)
report(node)
</lang>{{out}}
</syntaxhighlight>{{out}}
<pre>
<pre>
Ohm Volt Ampere Watt Network tree
Ohm Volt Ampere Watt Network tree
Line 434: Line 649:


====RPN====
====RPN====
<lang julia>function rpn(arr::Vector)
<syntaxhighlight lang="julia">function rpn(arr::Vector)
stack = Any[]
stack = Any[]
for op in arr
for op in arr
Line 452: Line 667:
setvoltage(node, 18)
setvoltage(node, 18)
report(node)
report(node)
</lang>{{out}}
</syntaxhighlight>{{out}}
Same as infix version.
Same as infix version.


=={{header|Nim}}==
=={{header|Nim}}==
<lang python>import tables,strutils,sequtils,sugar,strformat
<syntaxhighlight lang="python">import strutils, strformat


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


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


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


proc report(node : Node, level : string = "") =
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}"
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 "+*":
if node.kind in "+*":
node.a.report level & "| "
node.a.report level & "| "
node.b.report level & "| "
node.b.report level & "| "


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


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


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


===RPN===
===RPN===
<lang python>proc rpn(voltage:float, s:string): Node = calculate(voltage, s.split ' ')
<syntaxhighlight lang="python">proc rpn(voltage:float, s:string): Node = calculate(voltage, s.split ' ')
var node = rpn 18.0,"10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +"
var node = rpn(18, "10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +")
assert 10 == node.res
assert 10 == node.res
assert 18 == node.voltage
assert 18 == node.voltage
assert 1.8 == node.current()
assert 1.8 == node.current()
assert 32.4 == node.effect()
assert 32.4 == node.effect()
assert '+' == node.kind</lang>
assert '+' == node.kind</syntaxhighlight>


===Infix===
===Infix===
<lang python>proc parse(s: string): seq[string] =
<syntaxhighlight lang="python">proc parse(s: string): seq[string] =
var tmp = ""
var tmp = ""
for ch in s:
for ch in s:
if ch == ' ':
case ch
of ' ':
if tmp!="": result.add tmp
tmp = ""
if tmp != "": result.add tmp
tmp = ""
continue
continue
if ch in "+*()":
of '+', '*', '(', ')':
if tmp!="": result.add tmp
if tmp != "": result.add tmp
tmp=""
tmp = ""
result.add fmt"{ch}"
result.add $ch
else: tmp &= ch
else:
if tmp!="": result.add tmp
tmp &= ch
if tmp != "": result.add tmp


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

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

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


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


=={{header|Perl}}==
=={{header|Perl}}==
===Infix===
===Infix===
{{trans|Raku}}
{{trans|Raku}}
<lang perl>use strict;
<syntaxhighlight lang="perl">use v5.36;
use warnings;
use feature <say state>;


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


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

my ($class, $args) = @_;
sub new ($class, $args) {
my $self = {
my $self = {
symbol => $args->{symbol},
symbol => $args->{symbol},
Line 588: Line 807:
}
}


sub res {
sub res ($self) {
my $self = shift;
if ($self->{symbol} eq '+') { return res($self->{a}) + res($self->{b}) }
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})) }
elsif ($self->{symbol} eq '*') { return 1 / (1/res($self->{a}) + 1/res($self->{b})) }
else { return $self->{resistance} }
else { return $self->{resistance} }
}
}


sub set_voltage {
sub set_voltage ($self,$voltage) {
my($self,$voltage) = @_;
if ($self->{symbol} eq '+') {
if ($self->{symbol} eq '+') {
my $ra = res($self->{a});
my $ra = res($self->{a});
Line 609: Line 826:
}
}


sub current { my $self = shift; return $self->{voltage} / res($self) }
sub current ($self) { return $self->{voltage} / res($self) }
sub effect { my $self = shift; return $self->{voltage} * current($self) }
sub effect ($self) { return $self->{voltage} * current($self) }

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


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


sub report {
sub report ($self,$level = 0) {
my($self,$level) = @_;
state @results;
state @results;
push @results, ' Ohm Volt Ampere Watt Network tree' and $level = 1 unless $level;
push @results, ' Ohm Volt Ampere Watt Network tree' and $level = 1 unless $level;
Line 633: Line 846:


package main;
package main;
Resistor->import;


my ($R1, $R2, $R3, $R4, $R5, $R6, $R7, $R8, $R9, $R10) =
my ($R1, $R2, $R3, $R4, $R5, $R6, $R7, $R8, $R9, $R10) =
Line 640: Line 854:
* $R4 + $R3) * $R2 + $R1;
* $R4 + $R3) * $R2 + $R1;


Resistor::set_voltage($node,18);
set_voltage($node,18);
say Resistor::report($node);</lang>
say report($node);</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:20ex"> Ohm Volt Ampere Watt Network tree
<pre> Ohm Volt Ampere Watt Network tree
10.000 18.000 1.800 32.400 | +
10.000 18.000 1.800 32.400 | +
4.000 7.200 1.800 12.960 | | *
4.000 7.200 1.800 12.960 | | *
Line 665: Line 879:


=={{header|Phix}}==
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>-- node contents:
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
enum KIND, -- '+', '*', or 'r'
<span style="color: #008080;">constant</span> <span style="color: #000000;">RPN</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span> <span style="color: #000080;font-style:italic;">// or false for infix (same output)
RESISTANCE, VOLTAGE,
-- node contents:</span>
A, B -- nested nodes or NULL
<span style="color: #008080;">enum</span> <span style="color: #000000;">KIND</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- '+', '*', or 'r'</span>
<span style="color: #000000;">RESISTANCE</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">VOLTAGE</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">A</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">B</span> <span style="color: #000080;font-style:italic;">-- nested nodes or NULL</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">resistance</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">switch</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">KIND</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'+'</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">resistance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">A</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">resistance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">B</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'*'</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">/</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">resistance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">A</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">resistance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">B</span><span style="color: #0000FF;">]))</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'r'</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">return</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">RESISTANCE</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">default</span><span style="color: #0000FF;">:</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- unknown node kind</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">setVoltage</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">voltage</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">kind</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">KIND</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">RESISTANCE</span><span style="color: #0000FF;">]</span>
<span style="color: #000080;font-style:italic;">-- v = node[VOLTAGE] -- not needed!</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">na</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">A</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">nb</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">B</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">switch</span> <span style="color: #000000;">kind</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'+'</span><span style="color: #0000FF;">:</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">ra</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">resistance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">na</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">rb</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">resistance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nb</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">na</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">setVoltage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">na</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ra</span> <span style="color: #0000FF;">/</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ra</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">rb</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">voltage</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">nb</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">setVoltage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nb</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rb</span> <span style="color: #0000FF;">/</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">ra</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">rb</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">voltage</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">'*'</span><span style="color: #0000FF;">:</span>
<span style="color: #000000;">na</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">setVoltage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">na</span><span style="color: #0000FF;">,</span><span style="color: #000000;">voltage</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">nb</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">setVoltage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nb</span><span style="color: #0000FF;">,</span><span style="color: #000000;">voltage</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #000000;">node</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">kind</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">voltage</span><span style="color: #0000FF;">,</span><span style="color: #000000;">na</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nb</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">node</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">current</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VOLTAGE</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">resistance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">effect</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">current</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VOLTAGE</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">report</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">=</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%8.3f %8.3f %8.3f %8.3f %s%c\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">resistance</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">VOLTAGE</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">current</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">effect</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">KIND</span><span style="color: #0000FF;">]})</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">A</span><span style="color: #0000FF;">]!=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">report</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">A</span><span style="color: #0000FF;">],</span><span style="color: #000000;">level</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">"| "</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">B</span><span style="color: #0000FF;">]!=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">report</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">[</span><span style="color: #000000;">B</span><span style="color: #0000FF;">],</span><span style="color: #000000;">level</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">"| "</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">push_op</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">tok</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">switch</span> <span style="color: #000000;">tok</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #008000;">"+"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"*"</span><span style="color: #0000FF;">:</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[$],</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">stack</span><span style="color: #0000FF;">[$]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tok</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">default</span><span style="color: #0000FF;">:</span> <span style="color: #004080;">integer</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">r</span><span style="color: #0000FF;">}}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">scanf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tok</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">'r'</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">stack</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">-- RPN</span>
function resistance(sequence node)
<span style="color: #008080;">function</span> <span style="color: #000000;">rpn</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
switch node[KIND] do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
case '+': return resistance(node[A]) + resistance(node[B])
<span style="color: #000000;">tokens</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
case '*': return 1 / (1/resistance(node[A]) + 1/resistance(node[B]))
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tokens</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
case 'r': return node[RESISTANCE]
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">push_op</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tokens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
default: ?9/0 -- unknown node kind
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end switch
<span style="color: #008080;">return</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[$]</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function setVoltage(sequence node, atom voltage)
<span style="color: #000080;font-style:italic;">-- Infix, slightly trickier:</span>
switch node[KIND] do
<span style="color: #008080;">constant</span> <span style="color: #000000;">ops</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"+"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"*"</span><span style="color: #0000FF;">}</span>
case '+':
<span style="color: #008080;">function</span> <span style="color: #000000;">infix</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
atom ra := resistance(node[A]),
<span style="color: #004080;">string</span> <span style="color: #000000;">lastnum</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
rb := resistance(node[B])
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tokens</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
node[A] = setVoltage(node[A], ra / (ra + rb) * voltage)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
node[B] = setVoltage(node[B], rb / (ra + rb) * voltage)
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
case '*':
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'9'</span> <span style="color: #008080;">then</span>
node[A] = setVoltage(node[A],voltage)
<span style="color: #000000;">lastnum</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">ch</span>
node[B] = setVoltage(node[B],voltage)
<span style="color: #008080;">else</span>
end switch
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lastnum</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
node[VOLTAGE] = voltage
<span style="color: #000000;">tokens</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tokens</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lastnum</span><span style="color: #0000FF;">)</span>
return node
<span style="color: #000000;">lastnum</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">tokens</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tokens</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">&</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
function current(sequence node)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return node[VOLTAGE] / resistance(node)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lastnum</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">tokens</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tokens</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lastnum</span><span style="color: #0000FF;">)</span>
function effect(sequence node)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return current(node) * node[VOLTAGE]
<span style="color: #004080;">sequence</span> <span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
end function
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tokens</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">token</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tokens</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">op</span>
procedure report(sequence node, string level="")
<span style="color: #008080;">switch</span> <span style="color: #000000;">token</span> <span style="color: #008080;">do</span>
printf(1,"%8.3f %8.3f %8.3f %8.3f %s%c\n", {resistance(node), node[VOLTAGE], current(node), effect(node), level, node[KIND]})
<span style="color: #008080;">case</span> <span style="color: #008000;">"("</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">,</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span>
if node[A]!=NULL then
<span style="color: #008080;">case</span> <span style="color: #008000;">")"</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
report(node[A],level & "| ")
<span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[$]</span>
end if
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
if node[B]!=NULL then
<span style="color: #008080;">if</span> <span style="color: #000000;">op</span> <span style="color: #0000FF;">==</span> <span style="color: #008000;">"("</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
report(node[B],level & "| ")
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">push_op</span><span style="color: #0000FF;">(</span><span style="color: #000000;">result</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end procedure
<span style="color: #008080;">else</span><span style="color: #0000FF;">:</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">tp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">token</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ops</span><span style="color: #0000FF;">)</span>
function push(sequence stack, string tok)
<span style="color: #008080;">if</span> <span style="color: #000000;">tp</span> <span style="color: #008080;">then</span>
switch tok do
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
case "+","*": sequence b = stack[$],
a = stack[$-1]
<span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[$]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">sp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ops</span><span style="color: #0000FF;">)</span>
stack = stack[1..$-1]
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">sp</span> <span style="color: #008080;">or</span> <span style="color: #000000;">tp</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">sp</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
stack[$] = {tok[1], 0, 0, a, b}
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
default: integer {{r}} = scanf(tok,"%d")
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">push_op</span><span style="color: #0000FF;">(</span><span style="color: #000000;">result</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">)</span>
stack = append(stack,{'r', r, 0, NULL, NULL})
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end switch
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">,</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span>
return stack
<span style="color: #008080;">else</span>
end function</lang>
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">push_op</span><span style="color: #0000FF;">(</span><span style="color: #000000;">result</span><span style="color: #0000FF;">,</span><span style="color: #000000;">token</span><span style="color: #0000FF;">)</span>
===RPN===
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<lang Phix>function rpn(string s)
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
sequence stack = {},
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
tokens = split(s)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
for i=1 to length(tokens) do
<span style="color: #000000;">result</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">push_op</span><span style="color: #0000FF;">(</span><span style="color: #000000;">result</span><span style="color: #0000FF;">,</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
stack = push(stack,tokens[i])
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">return</span> <span style="color: #000000;">result</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
return stack[$]
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
end function
<span style="color: #004080;">sequence</span> <span style="color: #000000;">node</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">RPN</span><span style="color: #0000FF;">?</span><span style="color: #000000;">rpn</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +"</span><span style="color: #0000FF;">)</span>
sequence node = rpn("10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +")
<span style="color: #0000FF;">:</span><span style="color: #000000;">infix</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"((((10+2)*6+8)*6+4)*8+4)*8+6"</span><span style="color: #0000FF;">))</span>
node = setVoltage(node,18)
<span style="color: #000000;">node</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">setVoltage</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">,</span><span style="color: #000000;">18</span><span style="color: #0000FF;">)</span>
printf(1," Ohm Volt Ampere Watt Network tree\n")
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" Ohm Volt Ampere Watt Network tree\n"</span><span style="color: #0000FF;">)</span>
report(node,"")</lang>
<span style="color: #000000;">report</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 760: Line 1,038:
6.000 10.800 1.800 19.440 | r
6.000 10.800 1.800 19.440 | r
</pre>
</pre>
===infix===
slightly trickier
<lang Phix>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 break end if
result = push(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(result,op)
end while
stack = append(stack,token)
else
result = push(result,token)
end if
end switch
end for
for i=length(stack) to 1 by -1 do
result = push(result,stack[i])
end for
return result[1]
end function

sequence node = infix("((((10+2)*6+8)*6+4)*8+4)*8+6")</lang>
then as per last 3 lines of RPN, same output.


=={{header|Python}}==
=={{header|Python}}==
===RPN===
===RPN===
<lang python>class Resistor :
<syntaxhighlight lang="python">class Resistor :
def __init__(self, resistance, a=None, b=None, symbol='r'):
def __init__(self, resistance, a=None, b=None, symbol='r'):
self.resistance = resistance
self.resistance = resistance
Line 863: Line 1,085:
print(" Ohm Volt Ampere Watt Network tree")
print(" Ohm Volt Ampere Watt Network tree")
node.setVoltage(18.0)
node.setVoltage(18.0)
node.report()</lang>
node.report()</syntaxhighlight>


===Infix===
===Infix===
<lang python>class Resistor :
<syntaxhighlight lang="python">class Resistor :
def __init__(self, resistance, a=None, b=None, symbol='r') :
def __init__(self, resistance, a=None, b=None, symbol='r') :
self.resistance = resistance
self.resistance = resistance
Line 905: Line 1,127:
node.setVoltage(18)
node.setVoltage(18)
print(" Ohm Volt Ampere Watt Network tree")
print(" Ohm Volt Ampere Watt Network tree")
node.report()</lang>
node.report()</syntaxhighlight>


=={{header|Raku}}==
=={{header|Raku}}==
Line 911: Line 1,133:
===Infix===
===Infix===
{{trans|Nim}}
{{trans|Nim}}
<lang perl6>class Resistor {
<syntaxhighlight lang="raku" line>class Resistor {
has Str $.symbol;
has Str $.symbol;
has Numeric ( $.voltage, $.resistance );
has Numeric ( $.voltage, $.resistance );
Line 962: Line 1,184:


say ' Ohm Volt Ampere Watt Network tree';
say ' Ohm Volt Ampere Watt Network tree';
$node.report;</lang>
$node.report;</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:20ex"> Ohm Volt Ampere Watt Network tree
<pre style="height:20ex"> Ohm Volt Ampere Watt Network tree
Line 989: Line 1,211:
{{trans|Go}}
{{trans|Go}}
{{libheader|Wren-fmt}}
{{libheader|Wren-fmt}}
<lang ecmascript>import "/fmt" for Fmt
<syntaxhighlight lang="wren">import "./fmt" for Fmt


class Resistor {
class Resistor {
Line 1,043: Line 1,265:
node.voltage = 18
node.voltage = 18
System.print(" Ohm Volt Ampere Watt Network tree")
System.print(" Ohm Volt Ampere Watt Network tree")
node.report("")</lang>
node.report("")</syntaxhighlight>


{{out}}
{{out}}
Line 1,073: Line 1,295:
Additonally:
Additonally:
{{libheader|Wren-seq}}
{{libheader|Wren-seq}}
<lang ecmascript>import "/fmt" for Fmt
<syntaxhighlight lang="wren">import "./fmt" for Fmt
import "/seq" for Stack
import "./seq" for Stack


class Resistor {
class Resistor {
Line 1,144: Line 1,366:
node.voltage = 18
node.voltage = 18
System.print(" Ohm Volt Ampere Watt Network tree")
System.print(" Ohm Volt Ampere Watt Network tree")
node.report("")</lang>
node.report("")</syntaxhighlight>


{{out}}
{{out}}
Line 1,150: Line 1,372:
Same as Infix version
Same as Infix version
</pre>
</pre>

=={{header|Zig}}==
{{trans|Nim}}
{{works with|Zig|0.11dev}}

Zig requires more "code" than dynamic languages. The following three items account for a good portion of the "extra code".
<ul>
<li>There are no hidden memory allocations. Manual memory management.</li>
<li>Errors are values, and may not be ignored.</li>
<li>Generic data structures and functions.</li>
</ul>

===Postfix (RPN)===
<syntaxhighlight lang="zig">
// 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;
}
return tokens.toOwnedSlice();
}
</syntaxhighlight>

===Infix===
<syntaxhighlight lang="zig">
// 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;
}
return tokens.toOwnedSlice();
}

const ShuntPostfixError = error{
LParenNotAllowed,
RParenNotAllowed,
};

/// Input infix (infix tokens) in infix order.
/// Output postfix (postfix tokens) in postfix order.
///
/// Caller owns resultant slice and is responsible for freeing.
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();
}
};
</syntaxhighlight>

===Shared Infix/Postfix Code===
<syntaxhighlight lang="zig">
// 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;
}
};
}
</syntaxhighlight>


=={{header|zkl}}==
=={{header|zkl}}==
<lang zkl>class Resistor{
<syntaxhighlight lang="zkl">class Resistor{
fcn init(resistance_,symbol_="r", a_=Void, b_=Void){
fcn init(resistance_,symbol_="r", a_=Void, b_=Void){
var resistance,a,b,symbol, voltage=Void;
var resistance,a,b,symbol, voltage=Void;
Line 1,180: Line 1,836:
fcn __opAdd(other){ Resistor(0,"+",self,other) }
fcn __opAdd(other){ Resistor(0,"+",self,other) }
fcn __opMul(other){ Resistor(0,"*",self,other) }
fcn __opMul(other){ Resistor(0,"*",self,other) }
}</lang>
}</syntaxhighlight>
===Infix===
===Infix===
<lang zkl>R1,R2,R3,R4,R5,R6,R7,R8,R9,R10 := T(6,8,4,8,4,6,8,10,6,2].apply(Resistor);
<syntaxhighlight lang="zkl">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:=((((R8 + R10)*R9 + R7)*R6 + R5)*R4 + R3)*R2 + R1;
node.setVoltage(18);
node.setVoltage(18);
println(" Ohm Volt Ampere Watt Network tree");
println(" Ohm Volt Ampere Watt Network tree");
node.report();</lang>
node.report();</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:15ex">
<pre style="height:15ex">
Line 1,211: Line 1,867:
</pre>
</pre>
===RPN===
===RPN===
<lang zkl>fcn build(rpnStr){
<syntaxhighlight lang="zkl">fcn build(rpnStr){
stack:=List();
stack:=List();
foreach symbol in (rpnStr.split()){
foreach symbol in (rpnStr.split()){
Line 1,230: Line 1,886:
node.setVoltage(18);
node.setVoltage(18);
println(" Ohm Volt Ampere Watt Network tree");
println(" Ohm Volt Ampere Watt Network tree");
node.report();</lang>
node.report();</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:15ex">
<pre style="height:15ex">

Revision as of 17:41, 8 March 2024

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

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
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 ""

FreeBASIC

Infix

Translation of: Go
Const NULL As Any Ptr = 0

Type Resistor
    symbol As String
    resistance As Double
    voltage As Double
    a As Resistor Ptr
    b As Resistor Ptr
End Type

Function res(r As Resistor Ptr) As Double
    Select Case r->symbol
    Case "+"
        Return res(r->a) + res(r->b)
    Case "*"
        Return 1 / (1 / res(r->a) + 1 / res(r->b))
    Case Else
        Return r->resistance
    End Select
End Function

Sub setVoltage(r As Resistor Ptr, voltage As Double)
    Select Case r->symbol
    Case "+"
        Dim ra As Double = res(r->a)
        Dim rb As Double = res(r->b)
        setVoltage(r->a, ra / (ra + rb) * voltage)
        setVoltage(r->b, rb / (ra + rb) * voltage)
    Case "*"
        setVoltage(r->a, voltage)
        setVoltage(r->b, voltage)
    End Select
    r->voltage = voltage
End Sub

Function current(r As Resistor Ptr) As Double
    Return r->voltage / res(r)
End Function

Function effect(r As Resistor Ptr) As Double
    Return current(r) * r->voltage
End Function

Sub report(r As Resistor Ptr, level As String)
    Print Using "###.### ###.### ###.### ###.### & &"; res(r); r->voltage; current(r); effect(r); level; r->symbol
    If r->a <> NULL Then report(r->a, level + " |")
    If r->b <> NULL Then report(r->b, level + " |")
End Sub

Function sum(r1 As Resistor Ptr, r2 As Resistor Ptr) As Resistor Ptr
    Dim r As Resistor Ptr = Callocate(1, Sizeof(Resistor))
    r->symbol = "+"
    r->a = r1
    r->b = r2
    Return r
End Function

Function mul(r1 As Resistor Ptr, r2 As Resistor Ptr) As Resistor Ptr
    Dim r As Resistor Ptr = Callocate(1, Sizeof(Resistor))
    r->symbol = "*"
    r->a = r1
    r->b = r2
    Return r
End Function

Dim As Resistor Ptr r(9)
Dim As Double resistances(9) = {6, 8, 4, 8, 4, 6, 8, 10, 6, 2}
For i As Integer = 0 To 9
    r(i) = Callocate(1, Sizeof(Resistor))
    r(i)->symbol = "r"
    r(i)->resistance = resistances(i)
Next
Dim As Resistor Ptr node
node = sum(r(7), r(9))
node = mul(node, r(8))
node = sum(node, r(6))
node = mul(node, r(5))
node = sum(node, r(4))
node = mul(node, r(3))
node = sum(node, r(2))
node = mul(node, r(1))
node = sum(node, r(0))
setVoltage(node, 18)
Print "    Ohm   Volt   Ampere    Watt  Network tree"
report(node, "")

Sleep
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

Translation of: Go
Const NULL As Any Ptr = 0

Type Resistor
    symbol As String
    resistance As Double
    voltage As Double
    a As Resistor Ptr
    b As Resistor Ptr
End Type

Sub push(s() As Resistor Ptr, r As Resistor Ptr)
    Redim Preserve s(Ubound(s) + 1)
    s(Ubound(s)) = r
End Sub

Sub pop(s() As Resistor Ptr, Byref r As Resistor Ptr)
    r = s(Ubound(s))
    Redim Preserve s(Ubound(s) - 1)
End Sub

Function res(r As Resistor Ptr) As Double
    Select Case r->symbol
    Case "+"
        Return res(r->a) + res(r->b)
    Case "*"
        Return 1 / (1 / res(r->a) + 1 / res(r->b))
    Case Else
        Return r->resistance
    End Select
End Function

Sub setVoltage(r As Resistor Ptr, voltage As Double)
    Select Case r->symbol
    Case "+"
        Dim ra As Double = res(r->a)
        Dim rb As Double = res(r->b)
        setVoltage(r->a, ra / (ra + rb) * voltage)
        setVoltage(r->b, rb / (ra + rb) * voltage)
    Case "*"
        setVoltage(r->a, voltage)
        setVoltage(r->b, voltage)
    End Select
    r->voltage = voltage
End Sub

Function current(r As Resistor Ptr) As Double
    Return r->voltage / res(r)
End Function

Function effect(r As Resistor Ptr) As Double
    Return current(r) * r->voltage
End Function

Sub report(r As Resistor Ptr, level As String)
    Print Using "###.### ###.### ###.### ###.### & &"; res(r); r->voltage; current(r); effect(r); level; r->symbol
    If r->a <> NULL Then report(r->a, level + " |")
    If r->b <> NULL Then report(r->b, level + " |")
End Sub

Sub splitString(s As String, delim As String, result() As String)
    Dim As Integer start = 1, endd
    While start <= Len(s)
        endd = Instr(start, s, delim)
        If endd = 0 Then endd = Len(s) + 1
        Redim Preserve result(Ubound(result) + 1)
        result(Ubound(result)) = Mid(s, start, endd - start)
        start = endd + Len(delim)
    Wend
End Sub

Sub build(rpn As String, Byref node As Resistor Ptr)
    Dim As Resistor Ptr s()
    Dim As String tokens()
    splitString(rpn, " ", tokens())
    Dim As Integer i
    For i = 0 To Ubound(tokens)
        Dim As Resistor Ptr r = Callocate(1, Sizeof(Resistor))
        Select Case tokens(i)
        Case "+", "*"
            pop(s(), r->b)
            pop(s(), r->a)
            r->symbol = tokens(i)
        Case Else
            r->resistance = Val(tokens(i))
            r->symbol = "r"
        End Select
        push(s(), r)
    Next
    pop(s(), node)
End Sub

Dim As Resistor Ptr node 
build("10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 +", node)
setVoltage(node, 18)
Print "    Ohm   Volt   Ampere    Watt  Network tree"
report(node, "")

Sleep
Output:
Same as Infix version

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 := r[7].add(r[9]).mul(r[8]).add(r[6]).mul(r[5]).add(r[4]).mul(r[3]).add(r[2]).mul(r[1]).add(r[0])
    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)
    nfmt(x::Real) = rpad(format(x, precision=3), 12)
    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 = ""
      result.add $ch
    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 "(":
      stack.add token
    of ")":
      while stack.len > 0:
        op = stack.pop()
        if op == "(": break
        result.add op
    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
          discard stack.pop()
          result.add op
        stack.add token
      else: result.add token

  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);
    say "$f $pad" . $self->{symbol};
    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 __add__(self,other) : return Serial(self,other)
	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');
        say "$f $pad$.symbol";
        $.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

Additonally:

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;
    }
    return tokens.toOwnedSlice();
}

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;
    }
    return tokens.toOwnedSlice();
}

const ShuntPostfixError = error{
    LParenNotAllowed,
    RParenNotAllowed,
};

/// Input infix (infix tokens) in infix order.
/// Output postfix (postfix tokens) in postfix order.
///
/// Caller owns resultant slice and is responsible for freeing.
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 __opAdd(other){ Resistor(0,"+",self,other) }
   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