Volts, Amps, Watts and Ohms: given two, calculate the other two



Ohm's law tells us that the current (I) in amps flowing through a resistance (R) in Ohms when a voltage (V) is applied across it is given as follows:

V = I / R

Similarly the power (P) in watts dissipated by that resistance is given by:

P = V * I

By rearrangement and substitution, formulae may be derived for calculating two of these quantities when any of the other two is given. These formulae are summarised as follows (note this image uses E instead of V for volts):

Absolute Power Corrupts Absolutely! Resistance is Futile!

Given an input of any two of these quantities in a string, output the other two.

  • Input numbers will be decimals in whatever format is appropriate for your language. Precision should be to at least 3 decimal places. (IEEE 754-2008 binary32 floats are sufficient.)
  • Each input number will be suffixed with a unit. This will be one of V A W R for Voltage, Amperage, Power and Resistance (or the equivalent lowercase). Additionally, you may use Ω instead of R. The units will not have any decimal prefixes (Kilo-, milli-, etc).
  • The two input quantities will be given in any order in one string, separated by a single space.
  • Input quantities will always be real numbers greater than 0.
  • Output will be in the same format as input.
  • Equation-solving builtins are disallowed.

Example Inputs

1W 1A
12V 120R
10A 10V
8R 1800W
230V 13A
1.1W 2.333V

Corresponding Outputs

1V 1R
0.1A 1.2W
1R 100W
120V 15A
2990W 17.692R
0.471A 4.948R

It should be noted that solutions to this challenge will effectively be self-inverses. In other words if you apply a solution to input A B and get output C D, then apply a solution to input C D, then the output should be A B again, though possibly out of order and perturbed due to FP rounding. So test inputs and outputs may be used interchangeably.

Digital Trauma

Posted 2016-03-08T21:35:10.233

Reputation: 64 644

Can we output all 4 values? – CalculatorFeline – 2016-03-08T21:58:40.967

@CatsAreFluffy No - input and output will always both be exactly 2 values. – Digital Trauma – 2016-03-08T22:03:04.400

12This may actually be the most immediately descriptive title I've ever seen for a challenge. – Alex A. – 2016-03-09T01:23:36.837

5@AlexA. yes, I was trying to think up something catchy and exciting - electrifying, if you will. But I came up short - Captain Obvious won the day – Digital Trauma – 2016-03-09T01:27:39.377



Ruby 171 bytes

Input as function argument. Output to stdout with trailing space (can be revised if necessary.)

%w{EA9.EAAVAA.WVA GS;.A?#WWV.RRR}.map{|w|m=w[n=(a+c+?!).sum%10].ord;print (b**(m%9-4)*d**(m/9-5))**0.5,w[n+7],' '}}


All formulas can be expressed in the form b**x*d**y where b & d are the two input values and x & y are powers. For golfing reasons the expression (b**x*d**y)**0.5 was finally preferred as it means x and y become integers in the range -4 to 4.

The following table shows the required expressions (inputs are assumed sorted alphabetically) and the encoded values for the powers. Where x and y are the doubled powers, they are encoded as (x+4)+(y+4)*9+9 or equivalently (x+4)+(y+5)*9. This puts all encodings in the printable ASCII range. Power operators are omitted from the formulas for brevity.

n is a kind of checksum made from the input unit symbols; it can take the values 0,1,2,4,5,6 (3 is not used.)

n     formula 1 formula 2      formula 1                formula 2
value                      powers x+4 y+4 encoding   powers x+4 y+4 encoding

0      A*R=V    A2*R=W       1 1    6 6   69 E        2 1     8 6   71 G  
1    R-1*V=A  R-1*V2=W      -1 1    2 6   65 A       -1 2     2 8   83 S
2 R-.5*W.5=A R.5*W.5=V     -.5 .5   3 5   57 9       .5 .5    5 5   59 ;
3          .         .                       .                         .
4      A*V=W   A-1*V=R       1 1    6 6   69 E       -1 1     2 6   65 A
5    A-1*W=V   A-2*W=R      -1 1    2 6   65 A       -2 1     0 6   63 ?
6    V-1*W=A  V2*W-1=R      -1 1    2 6   65 A        2 -1    8 2   35 #

Ungolfed in test program

  a,b,c,d=s.split.map{|z|[z[-1],z.to_f]}.        #split the input into an array [[symbol1,value1],[symbol2,value2]]
  sort.flatten                                   #sort alphabetically by symbol and flatten to assign the 4 objects to different variables
  n=(a+c+?!).sum%10                              #sum the ascii codes of the symbols (plus that of ! for good value distribution) and take mod 10. gives a number 0..6 (3 is not used)
  %w{EA9.EAAVAA.WVA GS;.A?#WWV.RRR}.             #for each of the outputs, there is a 14 character string. 1st 7 characters encode powers, 2nd 7 characters are output symbol
  map{|w|                                        #iterate through the 2 outputs
    m=w[n].ord                                   #select one character according to value of n and convert to a number encoding the powers to raise the two inputs to
    print (b**(m%9-4)*d**(m/9-5))**0.5,w[n+7],' '#decode the powers, evaluate the expression and output, append the unit symbol and a space

f["6W 3A"]
f["12V 120R"]
f["10A 10V"]
f["8R 1800W"]
f["6W 2V"]
f["2A 3R"]


2.0V 0.6666666666666666R
0.1A 1.2W
100.0W 1.0R
15.0A 120.0V
3.0A 0.6666666666666666R
6.0V 12.0W

Level River St

Posted 2016-03-08T21:35:10.233

Reputation: 22 049


Python 3, 193 187 190 bytes

import re
exec(re.sub('(.+?) (.)',r'\2=\1;',input()))
for s,r in zip('AVRW'*3,'V/R (W*R)**.5 V/A V*V/R W/V W/A V*V/W R*A*A (W/R)**.5 A*R W/A**2 V*A'.split()):

Try it online

Converts the input of the form <value> <unit> <value> <unit> into assignment statements. Then, use eval on every formula, with the try/except ignoring the errors from the ones for which the variables haven't been assigned.

Edit (190): Idk how the bug stayed in the program for 3 years, but I fixed the program giving some wrong answers. It was previously doing sqrt before dividing. The TIO program now runs all test cases at once.


Posted 2016-03-08T21:35:10.233

Reputation: 21 944


Python 3, 329 347 343 339 326 305 267 251 249 245 237 bytes

This is pretty bloated. There is definitely still a lot of golfing to do.

Edit: Temporarily fixed the output. For some reason, return' '.join(str(eval(z[m][i]))+t[i]for i in range(2)) refuses to work properly.

Edit: Dropped eval.

This function now borrows parts of Level River St's answer. I changed the ops dictionary, first into a dictionary of modified exponents exponent*2+4 for b**((p-4)/2) * d**((q-4)/2), so that each p and q would be a one digit number. For example, b*d == b**1*d**1 == b**((6-4)/2)*d**((6-4)/2), and the result would be 66 in the dictionary.

Then, I turned the dictionary into a string z with those modified exponents and the units that are needed in a line and in a particular order. First, the ASCII value of each character in ARVW mod 10 is 5, 2, 6, 7. When any two of these values are added, they give a unique number mod 10. Thus, each two-character combination can be given a unique number with (ord(x[0]) + ord(y[10] + 3) % 10, giving AR: 0, AV: 4, AW: 5, RV: 1, RW: 2, VW: 6 (very similar to Lever River St's checksum). Arranging the modified exponents to be in this order, i.e. [AR] [RV] [RW] [blank] [AV] [AW] [VW], allows z to be accessed efficiently (in terms of bytes).

Edit: Golfed the list comprehension under return. Golfed the definition of m.


def e(s):x,y=sorted((i[-1],float(i[:-1]))for i in s.split());m=(ord(x[0])+ord(y[0])+3)%10*6;z="6686VW2628AW3555AV0000002666RW0626RV2682AR";return' '.join(str((x[1]**(int(z[m+i*2])-4)*y[1]**(int(z[m+i*2+1])-4))**.5)+z[m+i+4]for i in(0,1))


def electric(s):
    x, y = sorted((i[-1],float(i[:-1]))for i in s.split())
    m = (ord(x[0]) + ord(y[0]) + 3) % 10 * 6
    z = "6686VW2628AW3555AV0000002666RW0626RV2682AR"
    h = []
    for i in range(2):
         f = (x[1] ** (int(z[m*6+i*2])-4) * y[1] ** (int(z[m*6+i*2+1])-4)) ** 0.5
    return ' '.join(h)


Posted 2016-03-08T21:35:10.233

Reputation: 11 664