Análise dimensional


15

Calcular um produto ou proporção de unidades SI.

Por exemplo, kg m / s s(quilograma-metro por segundo ao quadrado) deve retornar N(newton).

A entrada será sempre:

  • Uma lista de símbolos para unidades SI, separadas por espaço (representando um produto) ou
  • Acima, /e acima (representando uma proporção).

A entrada nunca conterá outros caracteres (como literais numéricos ou outra pontuação).

Você pode assumir que isso sempre será igual a uma única unidade SI.

Use os seguintes 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

Exemplos:

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

O código mais curto (em bytes) vence.


2
kg m / s sseria na verdade quilogam-metro-segundo por segundo, ou apenas quilograma-metro. Trabalho de multiplicação e divisão LTR. O que você está procurando é kg m / (s s). Isso também se aplica aos outros exemplos.
precisa

@ Legion: Não necessariamente. Multiplicação e divisão implícitas com a barra são ambíguas; o ordr depende da convenção. Aqui a multiplicação implícita é considerada como tendo uma precedência mais alta que a divisão.
Deusovi 10/11/15

2
... que quebra sobre toda a matemática. Multiplicação implícita e explícita significa exatamente a mesma coisa.
precisa

@ LegionMammal978 Na verdade não. Será que 1 / 2xrealmente significa x / 2?
Ypnypn

5
@ LegionMammal978 - na verdade, 1 / 2x é uma notação comum para 1 / (2x). Geralmente, onde não é ambíguo, a barra seria interpretada como a linha divisória entre numerador e denominador. A convenção usada aqui é boa - especialmente porque essa convenção é padrão em unidades. kg / ms significa kg / (m * s) quando escrito como uma unidade. Tomá-lo de um cara com um doutorado em matemática.
Glen O

Respostas:


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

O acima é um hexdump; pode ser revertido com xxd -r.

Verifique todos os casos de teste de uma vez no intérprete CJam . 1

Execução de teste

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

Idéia

Podemos codificar cada unidade u = s a m b kg c A d como o vetor t u = (a + c - d, b, c, d) . 2

Dessa forma, para a entrada u 1 … u n / v 1 … v m , precisamos apenas calcular (t u 1 +… + t u n ) - (t v 1 +… + t v m ) e verificar qual unidade 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 Observe que, devido às limitações do intérprete online, não posso usar uma codificação diferente para código-fonte e E / S. Portanto, o símbolo Ω aparece como sua codificação UTF-8 (©). O intérprete oficial do Java não compartilha essa limitação.
2 Isso economiza alguns bytes no mapeamento direto para (a, b, c, d) , pois reduz o intervalo da primeira coordenada.


6

GNU sed, 1118

Muito longo, mas faz o trabalho.

A pontuação inclui +1 para a -ropção sed. Como se isso importasse aqui. A pontuação exclui comentários.

### 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/

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

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

Execuções de teste:

>> ["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     ->  Ω 
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.