Convertir entre prefijos SI

8

Introducción

El Sistema Internacional de Unidades es un sistema de medición en todo el mundo, excepto en algunos países, incluidos los EE . UU . El sistema SI (o sistema métrico) se basa en potencias de diez, que se enumeran a continuación (tenga en cuenta que esta es una tabla incompleta):

femto(f) pico(p) nano(n) micro(μ) milli(m) centi(c) (base unit) hecto(h) kilo(k) mega(M) giga(G) tera(T) peta(P)
10^-15   10^-12  10^-9   10^-6    10^-3    10^-2    10^0        10^2     10^3    10^6    10^9    10^12   10^15

Su trabajo será tomar una de estas medidas y convertirla en otra.

Entrada

La entrada será un número decimal 10^-16 < x < 2^31 - 1, un prefijo SI, una letra que representa una cantidad, otro prefijo SI para convertir y la misma letra de cantidad. La entrada estará en el formato 1234.56 mC to TCy siempre coincidirá con la expresión regular ^\d+(\.\d+)? [fpnμmchkMGTP](?'letter'[a-zA-Z]) to [fpnμmchkMGTP](?P=letter)$. Nunca tendrá que convertir a / desde la unidad base ( 10^0)

Salida

La salida será el mismo número que la entrada, recién convertida a un nuevo prefijo SI. Específicamente, el programa debe convertir el número de SI prefix 1a SI prefix 2en la entrada. Ejemplos:

Input: 1 nm to μm
Output: 0.001

Input: 82 kC to cC
Output: 8200000

Input: 6.54 MK to hK
Output: 65400

Input: 2000 MB to GB
Output: 2

Este es el , por lo que gana el código más corto en bytes.

GamrCorps
fuente
1
Otra cosa, al generar un número grande / pequeño de esta manera, ¿cuál debería ser la salida? por ejemplo1 PB to fB
FryAmTheEggman
@FryAmTheEggman, puede suponer que la entrada nunca producirá una salida que sea mayor / menor que el rango de dígitos que su idioma puede manejar de forma nativa (creo que eso es lo que está preguntando).
GamrCorps
¿Deberíamos usar U+00B5 MICRO SIGNo U+03BC GREEK SMALL LETTER MU? ¿Podemos elegir uno o tenemos que apoyar uno o ambos?
PurkkaKoodari
@ Pietu1998 cualquiera de los dos está bien.
GamrCorps
¿Se nos permite generar un número de coma flotante incluso si el resultado es un entero?
PurkkaKoodari

Respuestas:

1

Pyth, 46 44 bytes

El programa asume que el carácter µ( U+00B5 MICRO SIGN) se usa para el micro signo. En Windows, esto es lo que obtienes presionando Alt Gr+ M.

El código fuente contiene algunos no imprimibles, así que aquí hay un xxdvolcado hexadecimal reversible .

0000000: 2a76 684a 637a 645e 542d 466d 406a 4322  *vhJczd^T-Fm@jC"
0000010: 5c72 575d d623 8b9e 53bb 4c09 b275 2233  \rW].#..S.L..u"3
0000020: 3125 7443 6864 3137 2532 744a            1%tChd17%2tJ

Aquí hay una versión fácil de copiar:

*vhJczd^T-Fm@j1057004749883241517573776978549 31%tChd17%2tJ

Puede probar la demostración o usar el conjunto de pruebas . Si estos enlaces fallan, use la versión fácil de copiar ( demo , conjunto de pruebas ).

PurkkaKoodari
fuente
4

Javascript (ES7), 113 109 bytes

s=>(p=s.split` `)[m={f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21},0]/(10**(m[p[3][0]]-m[p[1][0]]))

Editar: Aparentemente podemos usar µ( U+00B5 MICRO SIGN) para el micro signo ahora, por lo que reemplazarlo ahorra un byte.

Para ES6, la compatibilidad (10**(m[p[3][0]]-m[p[1][0]]))se puede reemplazar Math.pow(10,m[p[3][0]]-m[p[1][0]])por 114 bytes.

Explicación

s=>                                  // s = input string
  (p=s.split` `)                     // p = input parts

    // m = dictionary of SI prefix digit powers of 10
    //     the exact values don't matter as long as they are relative to each other
    [m={f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21},

    0]                               // get the number
      /(10**(m[p[3][0]]-m[p[1][0]])) // get the factor to divide by from the difference
                                     //     between the SI prefix powers of 10

Prueba

Esta prueba se usa en Math.powlugar de **para que los navegadores comunes puedan probarla.

usuario81655
fuente
3

Ruby (2.2.1), 126 123 bytes

r={f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21};p ($*[0].to_r/10**(r[$*[3][0].to_sym]-r[$*[1][0].to_sym])).to_f

Guardado 3 bytes gracias a user81655

Explicación

# Hash of prefixes to relative powers
r={f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21};
p (                      # print (inspect)
  $*[0].to_r             # input value
  / 10 ** (              # divided by 10^...
    r[$*[3][0].to_sym]   # first prefix symbol
    -
    r[$*[1][0].to_sym]   # second prefix symbol
  )
).to_f                   # convert to float for proper format on output

Toma datos de la línea de comando, por ejemplo ruby si.rb 1 nm to μm

Este es mi primer golf!

Chris
fuente
1
Puede guardar 3 bytes si usa los valores {f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21}para la tabla hash. También se permite reemplazar μcon µ( U+00B5) y guardará otro byte.
user81655
@ user81655 buen consejo, gracias! Los dos símbolos mu / micro parecen dar el mismo número de bytes cuando utilizo mi archivo, ¿alguna idea de por qué?
Chris
No hay problema. Su archivo probablemente esté codificado usando algo como UTF-8 que divide los caracteres superiores a 127 en dos bytes. Si cambia a una codificación de un byte como ANSI, debería eliminar el byte adicional del archivo.
user81655
2

Haskell, 143 bytes

Llamar s.

import Data.List
s=i.words
i(n:f:_:[t])=read n*10**(x f-x t)
x=j.flip elemIndex"f  p  n  µ  mc   hk  M  G  T  P".head
j(Just n)=fromIntegral n
Leif Willerts
fuente
Me gusta mucho tu "f p n µ mc hk M G T P"truco. +1
Lynn
Me gusta este truco también. Un consejo: se puede combinar xy jcon un guardia de patrón a: x y|Just n<-elemIndex(y!!0)"f p n µ mc hk M G T P"=fromIntegral n.
nimi
2

CJam, 67 bytes

lS%:I0=dA"fpnµmchkMGTP"[-7 -4WY5 6ABEHK23]+:AAI3=c#C+=AAI1=c#C+=-#/

Pruébalo en línea!

Usa µ( U+00B5) para el micro signo, así que asegúrese de usar esto en su entrada en lugar de μ( U+03BC) en la pregunta.

Mi primer intento de usar CJam. ¡No dude en sugerir mejoras porque estoy seguro de que hay muchas!

Explicación

El mismo método que mi respuesta de JavaScript.

lS%:P                    e# P = input parts separated by space
0=d                      e# get number as double
  A
  "fpnµmchkMGTP"
    [-7 -4WY5 6ABEHK23]+
      :A                 e# A = array of SI prefixes followed by their (relative) values
   AP3=c                 e# desired SI prefix
     #C+=                e# get SI value of prefix
   AAP1=c                e# current SI prefix
     #C+=-               e# subtract value of prefix
   #                     e# get power of SI prefix difference
/                        e# divide value by 10 ^ SI prefix difference
usuario81655
fuente
1

Haskell, 121 bytes

(e:l:i)!d|e==d=fromEnum l|0<1=i!d
b#i="f`pcnfµimlcmhqkrMuGxT{P~"!(b!!i)
g[(a,b)]=10**fromIntegral(b#1-b#7)*read a
f=g.lex

Define una función f :: String -> Double. Por ejemplo:

*Main> f "6.54 MK to hK"
65400.0
Lynn
fuente
0

Perl 5 , 113 + 8 (-p -Mutf8) = 121 bytes

%c=(f,-15,p,-12,n,-9,µ,-6,'m',-3,c,-2,h,2,k,3,M,6,G,9,T,12,P,15);/([0-9.]+) (.).*(.)./;$_=$1*10**($c{$2}-$c{$3})

Pruébalo en línea!

Xcali
fuente