Resistance calculator: Difference between revisions
Content added Content deleted
No edit summary |
Alextretyak (talk | contribs) m (→{{header|11l}}: Void) |
||
(53 intermediate revisions by 12 users not shown) | |||
Line 1: | Line 1: | ||
{{draft task}} |
|||
== Introduction == |
|||
;Introduction |
|||
* Calculate the resistance of a network of resistors. |
* Calculate the resistance of a network of resistors. |
||
* The resistors can be connected in series or parallel. |
* The resistors can be connected in series or parallel. |
||
Line 5: | Line 7: | ||
* Calculate resistance, voltage, current and power for every resistor and operation. |
* Calculate resistance, voltage, current and power for every resistor and operation. |
||
;Background |
|||
* Serial Resistors: the sum of the resistors gives the equivalent resistor |
* Serial Resistors: the sum of the resistors gives the equivalent resistor |
||
* Parallel Resistors: the inverse of the sum of the inverse of the resistors |
* Parallel Resistors: the inverse of the sum of the inverse of the resistors |
||
Line 12: | Line 14: | ||
* Power = Current * Voltage |
* Power = Current * Voltage |
||
;Input |
|||
[https://photos.app.goo.gl/58heQVm8UJYf8Ra29 Resistance Calculator] |
|||
Please Insert Picture Here: https://www.electronics-tutorials.ws/wp-content/uploads/2013/08/res54.gif |
|||
* Infix: (((( |
* Infix: ((((10 + 2) * 6 + 8) * 6 + 4) * 8 + 4) * 8 + 6 |
||
* RPN: 10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 + |
* RPN: 10 2 + 6 * 8 + 6 * 4 + 8 * 4 + 8 * 6 + |
||
== Output == |
|||
* Voltage = 18.0 V |
* Voltage = 18.0 V |
||
;Output |
|||
* 10.000 ohms in the upper left corner is the equivalent resistance. |
* 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. |
* The first operation is 10 + 2 = 12 which can be found in the three middle rows. |
||
Line 42: | Line 44: | ||
8.000 7.200 0.900 6.480 | | r |
8.000 7.200 0.900 6.480 | | r |
||
6.000 10.800 1.800 19.440 | r |
6.000 10.800 1.800 19.440 | r |
||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
===RPN=== |
|||
<syntaxhighlight lang="11l">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) -> Void |
|||
.voltage = voltage |
|||
F current() |
|||
R .voltage / .res() |
|||
F effect() |
|||
R .current() * .voltage |
|||
F report(level = ‘’) -> Void |
|||
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) -> Void |
|||
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) -> Void |
|||
.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()</syntaxhighlight> |
|||
=={{header|CoffeeScript}}== |
|||
===RPN=== |
|||
<syntaxhighlight lang="coffeescript">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 ""</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}}== |
|||
===Infix=== |
|||
{{trans|Nim}} |
|||
<syntaxhighlight lang="go">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("") |
|||
}</syntaxhighlight> |
|||
===RPN=== |
|||
<syntaxhighlight lang="go">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("") |
|||
}</syntaxhighlight> |
|||
=={{header|Julia}}== |
|||
{{trans|Raku}} |
|||
====Infix==== |
|||
<syntaxhighlight lang="julia">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) |
|||
</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==== |
|||
<syntaxhighlight lang="julia">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) |
|||
</syntaxhighlight>{{out}} |
|||
Same as infix version. |
|||
=={{header|Nim}}== |
|||
<syntaxhighlight lang="python">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</syntaxhighlight> |
|||
===RPN=== |
|||
<syntaxhighlight lang="python">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</syntaxhighlight> |
|||
===Infix=== |
|||
<syntaxhighlight lang="python">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</syntaxhighlight> |
|||
=={{header|Perl}}== |
|||
===Infix=== |
|||
{{trans|Raku}} |
|||
<syntaxhighlight lang="perl">use v5.36; |
|||
package Resistor; |
|||
require Exporter; |
|||
our @ISA = qw(Exporter); |
|||
our @EXPORT = qw(set_voltage report); |
|||
use overload '+' => \&serial, '*' => \∥ |
|||
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);</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> |
|||
=={{header|Phix}}== |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
<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) |
|||
-- node contents:</span> |
|||
<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> |
|||
<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> |
|||
<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;">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> |
|||
<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: #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> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[$]</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #000080;font-style:italic;">-- Infix, slightly trickier:</span> |
|||
<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> |
|||
<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> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">lastnum</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tokens</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
<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> |
|||
<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> |
|||
<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> |
|||
<span style="color: #000000;">lastnum</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">ch</span> |
|||
<span style="color: #008080;">else</span> |
|||
<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> |
|||
<span style="color: #000000;">lastnum</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> |
|||
<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> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<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> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<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> |
|||
<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> |
|||
<span style="color: #008080;">switch</span> <span style="color: #000000;">token</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: #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> |
|||
<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> |
|||
<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: #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: #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> |
|||
<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> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
|||
<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> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">tp</span> <span style="color: #008080;">then</span> |
|||
<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> |
|||
<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> |
|||
<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> |
|||
<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;">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> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</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> |
|||
<span style="color: #008080;">else</span> |
|||
<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> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<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> |
|||
<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> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<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> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<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> |
|||
<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> |
|||
<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> |
|||
<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> |
|||
<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}} |
|||
<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> |
|||
=={{header|Python}}== |
|||
===RPN=== |
|||
<syntaxhighlight lang="python">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()</syntaxhighlight> |
|||
===Infix=== |
|||
<syntaxhighlight lang="python">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()</syntaxhighlight> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
===Infix=== |
|||
{{trans|Nim}} |
|||
<syntaxhighlight lang="raku" line>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;</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:20ex"> 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> |
|||
=={{header|Wren}}== |
|||
===Infix=== |
|||
{{trans|Go}} |
|||
{{libheader|Wren-fmt}} |
|||
<syntaxhighlight lang="wren">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("")</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=== |
|||
Additonally: |
|||
{{libheader|Wren-seq}} |
|||
<syntaxhighlight lang="wren">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("")</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Same as Infix version |
|||
</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}}== |
|||
<syntaxhighlight lang="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) } |
|||
}</syntaxhighlight> |
|||
===Infix=== |
|||
<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.setVoltage(18); |
|||
println(" Ohm Volt Ampere Watt Network tree"); |
|||
node.report();</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:15ex"> |
|||
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=== |
|||
<syntaxhighlight lang="zkl">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();</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:15ex"> |
|||
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> |
Latest revision as of 08:38, 7 May 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
- 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
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) -> Void
.voltage = voltage
F current()
R .voltage / .res()
F effect()
R .current() * .voltage
F report(level = ‘’) -> Void
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) -> Void
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) -> Void
.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
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
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
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
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
use v5.36;
package Resistor;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(set_voltage report);
use overload '+' => \&serial, '*' => \∥
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
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
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:
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
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();
}
};
// 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