# Dimensional Analysis

Calculate a product or ratio of SI units.

For example, kg m / s s (kilogram-meter per second squared) should return N (newton).

The input will always be either:

• A list of symbols for SI units, space-separated (representing a product) or
• The above, /, and the above (representing a ratio).

The input will never contain any other characters (such as numeric literals or other punctuation).

You may assume that this will always equal a single SI unit.

Use the following symbols:

Base quantities:
s               # second
m               # meter
kg              # kilogram
A               # ampere

Derived quantities:
N  = kg m / s s # newton
J  = N m        # joule
W  = J / s      # watt
Hz = W / J      # hertz
Pa = N / m m    # pascal
C  = s A        # coulomb
V  = J / C      # volt
F  = C / V      # farad
Ω  = V / A      # ohm      (you may use the O symbol instead, for a penalty of +3 bytes)
S  = A / V      # siemens
Wb = J / A      # weber
T  = Wb / m m   # tesla
H  = Wb / A     # henry


Examples:

m            => m
N m          => J
J / W        => s
A J / W      => C
T m m        => Wb
N / A m      => T
V s / A      => H
J S / F A    => V
s / s s      => Hz
Hz kg m Hz   => N
Hz s / Ω     => S
Wb / H       => A
V Pa S s / C => Pa
N s / m Hz   => kg
V A          => W
s / Ω        => F
J / A s A    => Ω


Shortest code (in bytes) wins.

• kg m / s s would actually be kilogam-meter-seconds per second, or just kilogram-meters. Multiplication and division work LTR. What you are looking for is kg m / (s s). This also applies to the other examples. – LegionMammal978 Nov 10 '15 at 22:03
• @Legion: Not necessarily. Implicit multiplication and division with the slash are ambiguous; the ordr depends on convention. Here implicit multiplication is taken to have a higher precedence than division. – Deusovi Nov 10 '15 at 22:06
• ...that breaks about all of mathematics. Implicit and explicit multiplication mean the exact same thing. – LegionMammal978 Nov 10 '15 at 22:09
• @LegionMammal978 Not really. Does 1 / 2x really mean x / 2? – Ypnypn Nov 10 '15 at 22:12
• @LegionMammal978 - actually, 1/2x is common notation for 1/(2x). More generally, where it's not ambiguous, the slash would be interpreted as the dividing line between numerator and denominator. The convention being used here is fine - especially because this convention is standard in units. kg/ms means kg/(m*s) when written as a unit. Take it from a guy with a PhD in Maths. – Glen O Nov 10 '15 at 22:49

# CJam, 18410598 96 bytes

00000000: 22 73 20 6d 20 6b 67 41 20 4e 20 4a 20 57 20 48  "s m kgA N J W H
00000010: 7a 50 61 43 20 56 20 46 20 ce a9 53 20 57 62 54  zPaC V F ..S WbT
00000020: 20 48 22 32 2f 53 66 2d 22 d6 9c 64 c6 a1 24 a4   H"2/Sf-"..d..$. 00000030: 4b f9 1c 4a 57 f4 61 79 31 ed 82 34 22 33 31 38 K..JW.ay1..4"318 00000040: 62 35 62 32 66 6d 34 2f 6c 53 25 32 24 32 24 65 b5b2fm4/lS%2$2$e 00000050: 72 22 2f 22 61 2f 3a 3a 2e 2b 3a 2e 2d 61 23 3d r"/"a/::.+:.-a#=  The above is a hexdump; it can be reversed with xxd -r. Verify all test cases at once in the CJam interpreter. 1 ### Test run $ LANG=en_US
$cjam si.cjam <<< 'Hz s / Ω'; echo S$ cjam si.cjam <<< 'J / A s A'; echo
Ω


### Idea

We can encode each unit u = sa mb kgc Ad as the vector tu = (a + c - d, b, c, d). 2

This way, for the input u1 … un / v1 … vm, we only have to calculate (tu1 + … + tun) - (tv1 + … + tvm) and check which unit it corresponds to.

### Code

"s m kgA N J W HzPaC V F Î©S WbT H"

2/     e# Split the string into chunks of length 2.
Sf-    e# Remove all spaces (if any) from each chunk.

"ÖdÆ¡$¤KùJWôay1í4" 318b e# Convert from base 318 to integer. 5b e# Convert from integer to base 5. 2fm e# Subtract 2 from each base-5 digit. 4/ e# Split into chunks of length 4. lS% e# Read one line of input sand split it at spaces. 2$2$e# Copy the unit names and the vector table. er e# Perform transliteration. "/"a/ e# Split at "/". ::.+ e# Add the vectors of numerator and denominator (if any). :.- e# Subtract the resulting sums (or leave a single sum untouched). a# e# Find the index of the resulting vector in the vector table. = e# Retrieve the corresponding unit.  1 Note that, due to limitations of the online interpreter, I cannot use a different encoding for source code and I/O. Therefore, the symbol Ω shows up as its UTF-8 encoding (Î©). The official Java interpreter does not share this limitation. 2 This saves a few bytes over the straightforward mapping to (a, b, c, d), since it shortens the range of the first coordinate. # GNU sed, 1118 Way too long but gets the job done. Score includes +1 for -r option to sed. As if it matters here. Score excludes comments. ### convert 2-letter units to 1-letter substitutes s/kg/k/g s/Hz/z/g s/Pa/P/g s/Wb/b/g ### remove spaces s/ //g ### start label for main loop to render all in terms of base units : ### convert N in denominator to s s / kg m s|/(.*)N|ss/\1km|;t ### convert N in numerator to kg m / ss s|N(.*)/|\1km/ss|;t ### convert N in non-rational to kg m / ss s|N(.*)|\1km/ss|;t ### ... etc for all other derived units s|/(.*)J|ss/\1kmm|;t s|J(.*)/|\1kmm/ss|;t s|J(.*)|\1kmm/ss|;t s|/(.*)W|sss/\1kmm|;t s|W(.*)/|\1kmm/sss|;t s|W(.*)|\1kmm/sss|;t s|/(.*)z|s/\1|;t s|z(.*)/|\1/s|;t s|z(.*)|\1/s|;t s|/(.*)P|mss/\1k|;t s|P(.*)/|\1k/mss|;t s|P(.*)|\1k/mss|;t s|C|sA|;t s|/(.*)V|sssA/\1kmm|;t s|V(.*)/|\1kmm/sssA|;t s|V(.*)|\1kmm/sssA|;t s|/(.*)F|kmm/\1ssssAA|;t s|F(.*)/|\1ssssAA/kmm|;t s|F(.*)|\1ssssAA/kmm|;t s|/(.*)Ω|sssAA/\1kmm|;t s|Ω(.*)/|\1kmm/sssAA|;t s|Ω(.*)|\1kmm/sssAA|;t s|/(.*)S|kmm/\1sssAA|;t s|S(.*)/|\1sssAA/kmm|;t s|S(.*)|\1sssAA/kmm|;t s|/(.*)b|ssA/\1kmm|;t s|b(.*)/|\1kmm/ssA|;t s|b(.*)|\1kmm/ssA|;t s|/(.*)T|ssA/\1k|;t s|T(.*)/|\1k/ssA|;t s|T(.*)|\1k/ssA|;t s|/(.*)H|ssAA/\1kmm|;t s|H(.*)/|\1kmm/ssAA|;t s|H(.*)|\1kmm/ssAA|;t ### cancel out any units appearing in both numerator and denominator s|(.)(.*/.*)\1|\2|;t ### remove trailing slash when rational cancels down to non-rational s|/$||
### sort numerator and denominator kg > m > s > A
:A;s|([^/A])A|A\1|;tA
:s;s|([^/s])s|s\1|;ts
:m;s|([^/m])m|m\1|;tm
:k;s|([^/k])k|k\1|;tk
### Final replacements back to derived units
s|kmm/sssAA|Ω|
s|kmm/sssA|V|
s|kmm/sss|W|
s|kmm/ssAA|H|
s|kmm/ssA|Wb|
s|kmm/ss|J|
s|km/ss|N|
s|k/mss|Pa|
s|k/ssA|T|
s|/s|Hz|
s|ssssAA/kmm|F|
s|sssAA/kmm|S|
s|sA|C|
s/k/kg/


# Javascript ES6, 479 bytes

f=(s,b="s, m, gk, A, gkm,ss gkmm,ss gkmm,sss gkmm,AAss gk,mss As, gkmm,Asss AAssss,gkmm gkmm,AAsss AAsss,gkmm gkmm,Ass gk,Ass ,s".split ,d="s m kgA N J W H PaC V F Ω S WbT Hz",p=s.split / .map(i=>i.split .map(i=>b[d.indexOf(i)/2].split,).reduce((p,c)=>(p[0]+=c[0],p[1]+=c[1],p),[[],[]])))=>(p[1]&&(p[0][0]+=p[1][1],p[0][1]+=p[1][0]),[x,y]=p[0].map(i=>[...i].sort().join),d.match(/../g)[b.indexOf([...x].reduce((p,c)=>(y==(n=y.replace(c,""))&&(p+=c),y=n,p),"")+","+y)])


Ungolfed:

f=(s,                                              // define function, accept string to calculate
// vvv derived quantities reduced to base quantities in the form of <numerator>,<denominator>
b="s, m, gk, A, gkm,ss gkmm,ss gkmm,sss gkmm,AAss gk,mss As, gkmm,Asss AAssss,gkmm gkmm,AAsss AAsss,gkmm gkmm,Ass gk,Ass ,s".split ,
d="s m kgA N J W H PaC V F Ω S WbT Hz",         // symbols list
p=s.split /                                   // split input into [numerator,denominator]
.map(i=>i.split                            // split numerator and denominator strings into list of symbols
.map(i=>b[d.indexOf(i)/2].split,) // convert symbols to their base quantities
.reduce((p,c)=>(p[0]+=c[0],p[1]+=c[1],p),[[],[]])) // consolidate base quantities
)=>(
p[1]&&(p[0][0]+=p[1][1],p[0][1]+=p[1][0]),     // if input was in form of numerator / denominator, reduce to numerator / 1
[x,y]=p[0].map(i=>[...i].sort().join),       // sort base quantities in numerator and denominator strings
d.match(/../g)[b.indexOf(                      // derive symbol from base quantities
[...x].reduce((p,c)=>(y==(n=y.replace(c,""))&&(p+=c),y=n,p),"")+","+y // remove duplicate symbols from numerator and denominator
)])


Test Runs:

>> ["m","N m","J / W","A J / W","T m m","N / A m","V s / A",
"J S / F A","s / s s","Hz kg m Hz","Hz s / Ω","Wb / H",
"V Pa S s / C","N s / m Hz","V A","s / Ω","J / A s A"]
.forEach(i=>console.log((i+" ".repeat(12)).slice(0,12)+"  ->  "+f(i)))

<< m             ->  m
N m           ->  J
J / W         ->  s
A J / W       ->  C
T m m         ->  Wb
N / A m       ->  T
V s / A       ->  H
J S / F A     ->  V
s / s s       ->  Hz
Hz kg m Hz    ->  N
Hz s / Ω      ->  S
Wb / H        ->  A
V Pa S s / C  ->  Pa
N s / m Hz    ->  kg
V A           ->  W
s / Ω         ->  F
J / A s A     ->  Ω