Los humanos odian los poderes y los programadores odian a los humanos. ¡Conéctelos!

8

Antecedentes

La tarea es simple pero cada programador la ha implementado al menos una vez. Stackoverflow tiene muchas muestras, pero ¿son lo suficientemente cortas como para ganar?

Historia del problema

Eres un programador gruñón al que se le asignó la tarea de implementar la entrada de tamaño de archivo para los usuarios. Como los usuarios no usan bytes, todos ingresarán "1M", "1K", "3G", "3.14M", ¡pero necesita bytes! Entonces escribes un programa para hacer la conversión.

Luego, su gerente le entrega docenas de informes de usuarios con quejas sobre grandes números extraños en la entrada de tamaño de archivo. Parece que también necesitarás codificar la conversión inversa.

¿Qué es lo que hay que hacer?

Aquí está el truco: debe implementar la conversión bidireccional en una sola pieza de código. ¿Se utilizan dos funciones separadas según sea necesario? No, eso es demasiado simple: ¡hagamos uno corto!

Para los propósitos de este desafío, "kilobyte" significa 1024 bytes, "megabyte" significa 1024 * 1024 = 1048576 bytes y "gigabytle" significa 1024 * 1024 * 1024 = 1073741824 bytes.

Datos de prueba

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

Reglas

  • El valor de la prueba no excederá 2 * 1024 * 1024 * 1024 o 2G
  • Los usuarios utilizan los siguientes postfixes: K para kilobytes, M para megabytes, G para gigabytes
  • No se requiere código para trabajar con números negativos
  • No utilice bibliotecas externas (por ejemplo, BCMathen PHP) además de las agrupadas (por ejemplo math.h)
  • Las lagunas estándar no están permitidas
  • El código no debe producir nada en stderr
  • Su programa puede tomar entradas y producir salidas usando métodos estándar
kiler129
fuente
1
Por lo general, los programas no toman entradas y salidas variables ...
TheDoctor
77
1024 no es un kilobyte (k); Es un kibibyte (KiB). Del mismo modo, 1048576 no es un megabyte (M); Es un mebibyte (MiB).
Todd Lehman
55
A pesar de que tal vez no sea útil para la vida real, este desafío está bien especificado y es una tarea no trivial. Por mi parte, creo que solo necesita un poco más de esmalte en la redacción. Para su información, @ kiler129, para futuros desafíos, puede resolver todos estos problemas antes de publicarlos en el Sandbox primero.
DLosc
2
Posible duplicado: codegolf.stackexchange.com/questions/51928/…
Digital Trauma
44
¿Cuántos dígitos decimales quieres? 1024 = 1k, 1025 = 1.0 k o 1k? 1526398 = 1.45568656921 M ....
don brillante

Respuestas:

4

Python 2, 204 190 bytes

Este es mi primer 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
fuente
1

Pip, 60 bytes

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

Toma la entrada de la línea de comando (asignada a la avariable) y las salidas a stdout.

Versión sin golf:

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 idel 1 al 3:
    • Si a >= 1024, este es un valor de byte que debe convertirse en una unidad más grande:
      • Dividir apor 1024
      • Establecido xpara ser el valor actual de aconcatenado con la unidad actual
  • Si xfue establecido por el paso anterior, envíelo. De lo contrario, aera inferior a 1024 (con un posible sufijo de unidad), entonces:
    • Realice un reemplazo de expresiones regulares con una función activada asi tiene una de KMGal final: traduzca la letra a la potencia adecuada de 1024 y multiplique el número por el resultado.
    • Para valores inferiores a 1024 sin sufijo, esto deja el valor sin cambios.
DLosc
fuente
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)))

Esto definitivamente se puede acortar, y lo hará más tarde. Solo quería sacar algo feo por ahí;)

Mwr247
fuente
0

Python2 199 bytes

Esto es una tontería pero funciona (ignorando la pregunta de precisión decimal) siempre que tenga docenas de gigabytes de RAM. no lo ejecute de otra manera, su máquina podría congelarse y bloquearse. Lo primero que hace es asignar una matriz de enteros de 2 gigabytes.

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)]
don brillante
fuente
0

C 206 183 bytes

Me libré de todo lo 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);}

Salida

Input: 1023
Output: 1023.0

Input: 1M
Output: 1048576.0

Input: 1048576
Output: 1.0M

Explicación

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