Humanos odeiam pows ​​e programadores odeiam humanos - vamos conectá-los!

8

fundo

A tarefa é simples, mas todo programador a implementou pelo menos uma vez. O Stackoverflow possui muitas amostras, mas elas são curtas o suficiente para ganhar?

História do problema

Você é um programador mal-humorado que recebeu a tarefa de implementar a entrada de tamanho de arquivo para os usuários. Como os usuários não usam bytes, todos digitam "1M", "1K", "3G", "3,14M" - mas você precisa de bytes! Então você escreve um programa para fazer a conversão.

Em seguida, seu gerente entrega dezenas de relatórios de usuários com reclamações sobre números grandes e estranhos na entrada do tamanho do arquivo. Parece que você precisará codificar a conversão reversa também.

O que você precisa fazer?

Aqui está o truque: você deve implementar a conversão bidirecional em um único pedaço de código. Duas funções separadas usadas conforme necessário? Nah, isso é muito simples - vamos fazer um, um curto!

Para os propósitos deste desafio, "kilobyte" significa 1024 bytes, "megabyte" significa 1024 * 1024 = 1048576 bytes e "gigabytle" significa 1024 * 1024 * 1024 = 1073741824 bytes.

Dados de teste

Input   -> Output  
5       -> 5  
1023    -> 1023  
1024    -> 1K  
1K      -> 1024  
1.5K    -> 1536  
1536    -> 1.5K  
1048576 -> 1M  
1M      -> 1048576  

Regras

  • O valor do teste não excederá 2 * 1024 * 1024 * 1024 ou 2G
  • Os seguintes postfixes são usados ​​pelos usuários: K para kilobytes, M para megabytes, G para gigabytes
  • O código não é necessário para trabalhar com números negativos
  • Não use nenhuma biblioteca externa (por exemplo, BCMathem PHP) além das que estão incluídas no pacote (por exemplo math.h)
  • As brechas padrão não são permitidas
  • O código não deve produzir nada no stderr
  • Seu programa pode receber e produzir resultados usando métodos padrão
kiler129
fonte
1
Normalmente, os programas não tome entrada e saída variável ...
TheDoctor
7
1024 não é um kilobyte (k); é um kibibyte (KiB). Da mesma forma, 1048576 não é um megabyte (M); é um mebibyte (MiB).
Todd Lehman
5
Apesar de talvez não ser útil para a vida real, esse desafio é bem especificado e uma tarefa não trivial. Eu acho que só precisa de um pouco mais de polimento nas palavras. FYI, @ kiler129, para desafios futuros, você pode resolver todos esses problemas antecipadamente, publicando primeiro na Sandbox .
DLosc
2
Possível duplicata: codegolf.stackexchange.com/questions/51928/…
Digital Trauma
4
quantos dígitos decimais você deseja? 1024 = 1k, 1025 = 1,0 k ou 1k? 1526398 = 1.45568656921 M ....
don bright

Respostas:

4

Python 2, 204 190 bytes

Este é o meu primeiro codegolf.

s=raw_input()
p=' KMG'
if s[-1]<='9':
 e=0;r=int(s)
 while r>=1024:r/=1024.0;e+=1
else:
 e=p.index(s[-1]);r=eval(s[:-1])
 while e>0:r*=1024;e-=1
print(`r`if r%1!=0 else`int(r)`)+p[e].strip()
TFeld
fonte
1

Pip, 60 bytes

l:" KMG"Fi1,4Ia>=Y1024x:(a/:y).l@ix|aR`.+([KMG])`_*y**(l@?B)

Pega entrada da linha de comando (atribuída à avariável) e gera saída para stdout.

Versão não destruída:

l : " KMG"
Y 1024
F i 1,4
 I a>=y {
  a /: y
  x : a . l@i
 }
x | a R `.+([KMG])` {a*y**(l@?b)}

Algoritmo:

  • Para ide 1 a 3:
    • Se a >= 1024, esse é um valor de byte que precisa ser convertido em uma unidade maior:
      • Divida apor 1024
      • Defina xcomo o valor atual de aconcatenado com a unidade atual
  • Se xfoi definido pela etapa anterior, faça a saída. Caso contrário, aera menor que 1024 (com um possível sufixo de unidade), portanto:
    • Faça uma substituição de regex com uma função ativada ase houver uma KMGno final: traduza a letra para a potência apropriada de 1024 e multiplique o número pelo resultado.
    • Para valores menores que 1024 sem sufixo, isso deixa o valor inalterado.
DLosc
fonte
1

JavaScript, 144 106 bytes

n=>((G=(M=(K=2<<9)<<10)<<10),+n>0?n<K?n:n<M?n/K+'K':n<G?n/M+'M':n/G+'G':eval(n.replace(/[KMG]/,m=>'*'+m)))

Definitivamente, isso pode ser encurtado e será feito mais tarde. Só queria ter algo feio por aí;)

Mwr247
fonte
0

Python2 199 bytes

isso é bobagem, mas funciona (ignorando a questão da precisão decimal) desde que você tenha dezenas de gigabytes de RAM. caso contrário, sua máquina poderá congelar e travar. A primeira coisa que faz é alocar uma matriz de 2gigabyte de números inteiros.

n,bn={'K':2**10,'M':2**20,'G':2**30},range(2**30+1)
for i in bn:
 for j in 'KMG':
  if i>=n[j]: bn[i]=str(float(i/n[j]))+j 
def f(i):
 if i[-1] in 'KMG': return n[i[-1]]*float(i[:-1])
 return bn[int(i)]
não brilhante
fonte
0

C 206 183 bytes

Livrei-me do máximo que pude.

#include<stdlib.h>
main(y,z)char**z;{char*i="KMG";float f=atof(*++z);while(*++*z)y=**z;if(y>57){do f*=1024;while(y!=*i++);y=0;}else while(f>1023)y=*i++,f/=1024;printf("%.1lf%c",f,y);}

Resultado

Input: 1023
Output: 1023.0

Input: 1M
Output: 1048576.0

Input: 1048576
Output: 1.0M

Explicação

#include <stdlib.h> //needed for atof()
main(y,z)char **z; //y will hold the size indicator
{
    char *i="KMG";//holds the characters for the size indicators
    float f=atof(*++z); //get the number from the string

    while(*++*z) //loops through the string
        y=**z;
    if(y>57) //57 is ASCII for 9
    {
        do f*=1024;
        while(y!=*i++); //loop through until we hit the correct size
        y=0;
    }
    else
        while(f>1023) //loop through until number is less than 1024
            y=*i++,f/=1024; 
    printf("%.1lf%c",f,y); //print number and size character 
}
Chris Loonam
fonte