Task: Resistance calculator




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("")
}




Python: import strutils, strformat

type
  Node = ref object
    kind: char  
    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