Análisis dimensional

15

Calcular un producto o relación de unidades SI.

Por ejemplo, kg m / s s(kilogramo-metro por segundo al cuadrado) debería regresar N(newton).

La entrada siempre será:

  • Una lista de símbolos para unidades SI, separadas por espacios (que representan un producto) o
  • Lo anterior, /y lo anterior (que representa una relación).

La entrada nunca contendrá ningún otro carácter (como literales numéricos u otros signos de puntuación).

Puede suponer que esto siempre será igual a una sola unidad SI.

Use los siguientes símbolos:

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

Ejemplos:

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    => Ω

El código más corto (en bytes) gana.

Ypnypn
fuente
2
kg m / s sen realidad serían kilogam-metro-segundos por segundo, o simplemente kilogramo-metros. Multiplicación y división de trabajo LTR. Lo que estás buscando es kg m / (s s). Esto también se aplica a los otros ejemplos.
LegionMammal978
@Legion: No necesariamente. La multiplicación implícita y la división con la barra son ambiguas; el ordr depende de la convención. Aquí se considera que la multiplicación implícita tiene mayor prioridad que la división.
Deusovi
2
... eso rompe con todas las matemáticas. La multiplicación implícita y explícita significa exactamente lo mismo.
LegionMammal978
@ LegionMammal978 En realidad no. ¿ 1 / 2xRealmente significa x / 2?
Ypnypn
55
@ LegionMammal978: en realidad, 1 / 2x es una notación común para 1 / (2x). Más generalmente, donde no es ambiguo, la barra se interpretará como la línea divisoria entre el numerador y el denominador. La convención que se usa aquí está bien, especialmente porque esta convención es estándar en unidades. kg / ms significa kg / (m * s) cuando se escribe como una unidad. Tómelo de un chico con un doctorado en matemáticas.
Glen O

Respuestas:

7

CJAM, 184 105 98 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#=

Lo anterior es un hexdump; Se puede revertir con xxd -r.

Verifique todos los casos de prueba a la vez en el intérprete de CJam . 1

Prueba de funcionamiento

$ LANG=en_US
$ cjam si.cjam <<< 'Hz s / Ω'; echo
S
$ cjam si.cjam <<< 'J / A s A'; echo
Ω

Idea

Podemos codificar cada unidad u = s a m b kg c A d como el vector t u = (a + c - d, b, c, d) . 2

De esta manera, para la entrada u 1 ... u n / v 1 ... v m , solo tenemos que calcular (t u 1 + ... + t u n ) - (t v 1 + ... + t v m ) y verificar qué unidad corresponde a

Código

"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 Tenga en cuenta que, debido a las limitaciones del intérprete en línea, no puedo usar una codificación diferente para el código fuente y la E / S. Por lo tanto, el símbolo Ω aparece como su codificación UTF-8 (Î ©). El intérprete oficial de Java no comparte esta limitación.
2 Esto ahorra algunos bytes sobre la asignación directa a (a, b, c, d) , ya que acorta el rango de la primera coordenada.

Dennis
fuente
6

GNU sed, 1118

Demasiado tiempo pero hace el trabajo.

La puntuación incluye +1 para la -ropción de sed. Como si importara aquí. La puntuación excluye los comentarios.

### 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/
Trauma digital
fuente
3

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)])

Sin golf:

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
  )])

Pruebas de funcionamiento:

>> ["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     ->  Ω 
Dendrobium
fuente