Vamos abreviar esses números! Agora reverter?

11

Introdução:

Como o Twitter, o Instagram e outros, eu queria exibir números como 1.2Ke em 3.8 Mvez de 1,222ou 3,823,456.

Mas isso não é tudo! Como todos sabemos, pode haver alguns seres humanos que, sem dúvida, não gostam dessas abreviações e tentam revertê-las. Então, 1.2kse tornará 1,200e 3.8 Mse tornará 3,800,000.

A tarefa:

  • sua tarefa é escrever um programa ou uma função que converta uma lista de números ( que são dados como cadeias ) em seus pares abreviados e vice-versa.

Por exemplo, se a lista de entrada (ou qualquer uma STDIN) fosse ['1.4k', '1,234,567', '7.99M'], você deve gerar:

['1,400', '1.2M', '7,990,000']

Você pode seguir o próximo esquema para abreviações:

  • 10 3 -> um quilo -> K
  • 10 6 -> um milhão -> M
  • 10 9 -> um bilhão -> B

Seu código pode assumir todas as letras minúsculas, todas as maiúsculas, maiúsculas ou minúsculas para entrada e usar qualquer uma dessas para saída, mas deve ser consistente.

Regras e restrições:

  • você pode escrever um programa ou função, recebendo entrada via STDIN(ou alternativa mais próxima), argumento da linha de comando ou argumento da função e emitindo o resultado via STDOUT(ou alternativa mais próxima), valor de retorno da função ou parâmetro da função (saída).
  • A entrada pode estar em qualquer formato conveniente de lista ou string. Você pode assumir que são menores que cada um e que a lista contém pelo menos um elemento.ai231
  • cada número abreviado conterá apenas um, . enquanto um número normal conterá quantos forem , necessários (você pode presumir que esses números não serão alterados).
  • você NÃO PODE inserir um número, '123456'mas sim123,456
  • aplicam regras de padrão .

Casos de teste:

Input: ['1.5M', '77.6k', '123,456,789']         Output: ['1,500,000', '77,600', '123.4M']
Input: ['3,000,000,000', '581k', '2b']          Output: ['3B', '581,000', '2,000,000,000']
Input: ['0.1k']                                 Output: ['100']
Input: ['888', '33']                            Output: ['0.888k', '0.033k']

Esclarecimentos:

  • para números <1000 após o ponto decimal na saída da abreviação, você deve ter quantos dígitos forem necessários para obter o resultado correto. (por exemplo: 2-> se tornará 0.002k) - isso significa no máximo 3 casas decimais ; para números> 1000, você pode ter no máximo 1 decimal .
  • a abreviação pode estar em maiúsculas ou minúsculas
  • Eu removi a restrição interna, conforme sugerido nos comentários

O código mais curto em bytes vence!

Grajdeanu Alex.
fonte
1
Pedidos de esclarecimento: quantos dígitos após o ponto decimal na saída da abreviação? como abreviar números <1000? maiúsculas ou minúsculas ou ambos na entrada e na saída?
Edc65 3/11
1
Não deveria '123,456,789' -> '123.4M'? Além disso, isso não esclarece quantas casas decimais usar. Certamente qualquer coisa abaixo de 1000 não precisa ser abreviada de qualquer maneira.
Kade
1
@ anonymous2 leu a terceira regra.
Grajdeanu Alex.
4
"você não tem permissão para usar nenhum módulo / função embutida" Alguma função embutida?
precisa saber é o seguinte
1
Seu uso de "kilo" sugere prefixos de SI e esses seriam ["k", "M", "G"]. O que significa "embora um número normal contenha o número necessário " significa que, no meu país, seria um erro usá-lo.
Angs

Respostas:

2

PHP, 234 224 213 201 205 bytes

for(;$x=$argv[++$n];){$y=str_replace(",","",$x)/1e3;for($i=0;$y>999;$i++)$y=($y|0)/1e3;echo(A<$c=substr($x,strlen($x)-1))?number_format($x*[k=>1e3,m=>1e6,b=>1e9][$c]):($i?($y*10|0)/10:$y).kmb[$i]," ";}

6 bytes salvos por insertusernamehere, 4 bytes inspirados nisso.


  • recebe entrada dos argumentos da linha de comando, imprime os resultados separados por espaço com um separador à direita
  • espera abreviação em minúsculas
  • correr com -r

-2 bytes se sublinhado como separador estiver ok: Substitua " "por _.
-1 byte se o arredondamento correto estiver correto: Substitua ($y*10|0)/10por round($y,1).
-17 bytes para o PHP 7.1: Substitua substr($x,strlen($x)-1)por $x[-1].


80 (63) bytes para expandir apenas um argumento:

<?=number_format(($x=$argv[1])*[K=>1e3,M=>1e6,B=>1e9][substr($x,strlen($x)-1)]);

salve no arquivo, execute (ou substitua <?=por echo+ espaço e execute com -r.

Titus
fonte
Seu segundo exemplo não compila.
precisa saber é o seguinte
1
Você tem parênteses desequilibrados.
precisa saber é o seguinte
1
-4 Bytes: for($j=1;$x=$argv[$j++];) - em vez deforeach($argv as$i=>$x)if($i)
insertusernamehere
1
-2 bytes: kmb[$i] - em vez de "kmb"[$i].
usar o seguinte comando
1
@insertusernamehere Índices negativos de strings estão chegando no PHP 7.1; e isso é um RC (ainda). Obrigado pelos outros bytes!
Titus
2

JavaScript, 545 524 522 518 514 508 504 498 494 214 bytes

Obrigado a @ETHproductions por economizar 180 bytes!

d=F=>F.map(f=>1/f.slice(-1)?f=(f=f.replace(/,/g,""))[9]?(f/1e8|0)/10+"B":f[6]?(f/1e5|0)/10+"M":f/1e3+"k":R(R(f.slice(0,-1)+"e"+' kMB'.indexOf(f.substr(-1))*3-0+"").match(/.{1,3}/g)+""),R=x=>[...x].reverse().join``)

Para chamar a função:

d(["1.5M","1,500,000"]) //["1,500,500","1.5M"]

Saídas como alert, onde cada alertuma contém um elemento diferente da entrada

Versão legível:

d = F => F.map(f => 1 / f.slice(-1) ? f = (f = f.replace(/,/g, ""))[9] ? (f / 1e8 | 0) / 10 + "B" : f[6] ? (f / 1e5 | 0) / 10 + "M" : f / 1e3 + "k" : R(R(f.slice(0, -1) + "e" + ' kMB'.indexOf(f.substr(-1)) * 3 - 0 + "").match(/.{1,3}/g) + ""), R = x => [...x].reverse().join ``)

Resumo das edições: função convertida em uma função de seta

  • ponto e vírgula removido ';'
  • removido var
  • convertido em uma função de seta
  • mapa usado para iterar pelos elementos individuais da matriz
  • usado em |0vez de andar
  • regex usado para teste
  • operadores ternários usados ​​em vez de instruções if-else
  • incluiu uma função separada para .reverse().join''
user41805
fonte
3
Aqui estão algumas das maneiras de jogar isso para baixo. Sinta-se livre para fazer qualquer pergunta que você pode ter :-)
ETHproductions