Converter entre prefixos SI

8

Introdução

O Sistema Internacional de Unidades é um sistema de medição em todo o mundo, exceto em alguns países, incluindo os EUA . O sistema SI (ou sistema métrico) é baseado em potências de dez, listadas abaixo (observe que esta é uma tabela 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

Seu trabalho será tomar uma dessas medidas e convertê-la em outra.

Entrada

A entrada será um número decimal 10^-16 < x < 2^31 - 1, um prefixo de SI, uma letra representando uma quantidade, outro prefixo de SI para o qual converter e a mesma letra de quantidade. A entrada estará no formato 1234.56 mC to TCe sempre corresponderá ao regex ^\d+(\.\d+)? [fpnμmchkMGTP](?'letter'[a-zA-Z]) to [fpnμmchkMGTP](?P=letter)$. Você nunca precisará converter de / para a unidade base ( 10^0)

Resultado

A saída será o mesmo número da entrada, apenas convertida em um novo prefixo SI. Especificamente, o programa deve converter o número de SI prefix 1para SI prefix 2na entrada. Exemplos:

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

Isso é , então o código mais curto em bytes vence!

GamrCorps
fonte
1
Outra coisa, ao gerar um número grande / pequeno dessa maneira, qual deve ser a saída? por exemplo1 PB to fB
FryAmTheEggman 3/15/15
@FryAmTheEggman, você pode assumir que a entrada nunca produzirá uma saída maior / menor que o intervalo de dígitos com o qual o seu idioma pode lidar nativamente (acho que é isso que você está perguntando).
GamrCorps 03/12/2015
Devemos usar U+00B5 MICRO SIGNou U+03BC GREEK SMALL LETTER MU? Podemos escolher um ou temos que apoiar um ou ambos?
PurkkaKoodari
@ Pietu1998 qualquer um está bem.
GamrCorps
Podemos emitir um número de ponto flutuante, mesmo que o resultado seja um número inteiro?
PurkkaKoodari

Respostas:

1

Pitão, 46 44 bytes

O programa assume que o caractere µ( U+00B5 MICRO SIGN) é usado para o sinal de micro. No Windows, é isso que você obtém pressionando Alt Gr+ M.

O código fonte contém alguns imprimíveis, então aqui está um xxddespejo hexadecimal reversível .

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

Aqui está uma versão de cópia amigável:

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

Você pode experimentar a demonstração ou usar o conjunto de testes . Se esses links falharem, use a versão de cópia amigável ( demo , suíte de testes ).

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

Edit: Aparentemente, podemos usar µ( U+00B5 MICRO SIGN) para o sinal de micro agora, substituindo por que salva um byte.

Para o ES6, a compatibilidade (10**(m[p[3][0]]-m[p[1][0]]))pode ser substituída Math.pow(10,m[p[3][0]]-m[p[1][0]])por 114 bytes.

Explicação

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

Teste

Este teste usa em Math.powvez de, **para que navegadores comuns possam testá-lo.

user81655
fonte
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 graças a user81655

Explicação

# 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

Recebe entrada da linha de comando, por exemplo ruby si.rb 1 nm to μm

Este é o meu primeiro golfe!

Chris
fonte
1
Você pode salvar 3 bytes se usar os 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 a tabela de hash. Também é permitido substituir μpor µ( U+00B5) e salvar outro byte.
user81655
@ user81655 bons conselhos, obrigado! Os dois símbolos mu / micro parecem dar a mesma contagem de bytes quando eu wc -c meu arquivo, alguma idéia do porquê?
Chris
Sem problemas. Seu arquivo provavelmente está codificado usando algo como UTF-8, que divide os caracteres acima de 127 em dois bytes. Se você alternar para uma codificação de um byte como ANSI, ele deverá remover o byte extra do arquivo.
user81655
2

Haskell, 143 bytes

Ligue 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
fonte
Eu gosto muito do seu "f p n µ mc hk M G T P"truque. +1
Lynn
Eu também gosto desse truque. Uma dica: você pode combinar xe jcom um guarda padrão para: 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+=-#/

Experimente online!

Usa µ( U+00B5) para o sinal de micro, portanto, certifique-se de usá-lo em sua entrada, em vez de μ( U+03BC) na pergunta.

Minha primeira tentativa de usar o CJam. Sinta-se livre para sugerir melhorias, porque tenho certeza de que existem muitas!

Explicação

O mesmo método da minha resposta 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
user81655
fonte
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 uma função f :: String -> Double. Por exemplo:

*Main> f "6.54 MK to hK"
65400.0
Lynn
fonte
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})

Experimente online!

Xcali
fonte