Calcular uma dica

16

Você e um amigo entram em um bar. O barman trata você bem, então você decide dar uma gorjeta nele. Então você pega seu confiável computador de bolso e escreve um programa rápido para calcular uma dica para você, pois ele não possui uma calculadora embutida. Mas espere! As chaves do seu operador estão quebradas! Sua tarefa é calcular uma gorjeta de 20% para qualquer valor de entrada. As entradas de teste terão a forma de xx.xx, por exemplo, 20.96. Aqui estão as regras:

  • Não é possível usar o seguinte em operadores de formato matemático: + - * / %(Obrigado Wally West)
  • Nenhum uso de funções ou APIs de porcentagem incorporadas
  • Não há acesso à rede
  • Sem uso evalou similar
  • Não há calculadora do Windows (sim, as pessoas já responderam antes)
  • Nenhuma função de dica integrada (não que qualquer idioma tenha uma)

A saída deve ser arredondada para duas casas decimais.

A pontuação é baseada no comprimento em bytes.

-20% se o seu programa aceitar qualquer valor de gorjeta. A entrada para quantidade será dada na forma de xx, por exemplo, 35 e não 0,35

Milo
fonte
5
@mniip: Uma dica é uma quantia extra bizarra de dinheiro que você deve pagar em um restaurante que não faz parte do preço oficial. Não sei se eles fazem isso na Rússia.
User2357112 suporta Monica
5
Oh, essa nova geração ... Eu preferiria usar papel e caneta se eu não puder mentalmente dividir um número por 5.
visão
4
Nota: dividir por cinco equivale a dividir por 10 e depois multiplicar por 2, e ambas devem ser operações mentais muito fáceis.
user12205
11
Alguém pode esclarecer as regras: É permitido o uso das operações proibidas se você não usar esses operadores? A multiplicação é permitida se você não usar *?
Ypnypn
2
@TheDoctor é realmente uma duplicata? Porque não está adicionando.
Milo

Respostas:

18

Javascript 81

EDIT : O resultado agora é um arredondamento real, não truncado.

Não use QUALQUER matemática aqui, apenas manipulação de cadeias e operadores bit a bit.
Todos os +caracteres são concatenação de string ou conversão de string para float .
Funciona para qualquer entrada e saída xx.xx no formato (x) x.xx

s='00'+(prompt().replace('.','')<<1);(+s.replace(/(.*)(...)/,'$1.$2')).toFixed(2)

Truque explicado: 20% é dividido por 10 e multiplicado por 2.

  • Faça uma divisão por 10 movendo o ponto para a esquerda (manipulação de cordas)
  • Multiplique cada parte por 2 movendo os bits para a esquerda (operação bit a bit)
Michael M.
fonte
Quando a entrada é 99.99, isso retorna 19.998, portanto, não é "arredondado para duas casas decimais" conforme o OP.
Geobits 12/03
2
Hum, essa é uma solução longa, mas possui 12 votos positivos. O que está acontecendo com a votação do code-golf?
Justin
@ Quincunx Sim, você está certo, não é um concurso de popularidade!
Mukul Kumar 13/03
Como é um código de golfe, provavelmente não vencerei, mas isso não significa que as pessoas não gostem da minha solução ... Muitas vezes, os vencedores de código de golfe não são os que têm mais votos positivos.
Michael M.
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, absolutamente! Obrigado por apontar isto. Corrigido agora :)
Michael M.
6

J (9 caracteres)

Uma resposta curta em J:

^.(^.2)^~ 32
Thomas Baruchel
fonte
11
... e eu não falo J. O que diz?
CousinCocaine 13/03
Diz: cálculo 32 elevado ao log de energia (2); normalmente, o expoente está à direita de, ^mas aqui ~indica que a ordem deve ser revertida; (^.2)é log (0,2), e a inicial ^.que é executada por último é o logaritmo de tudo compute dpreviously: assim log (32 ^ log (0,2))
Thomas Baruchel
4

Pure bash, 50 43 caracteres

Certamente isso será superado, mas aqui está um começo:

a=$[10#${1/.}<<1]
echo ${a%???}.${a: -3:2}

Conforme os comentários:

  • /não é um operador de divisão aqui, faz parte de uma expansão de parâmetro de substituição de padrão
  • % não é um operador de módulo aqui, é parte de uma expansão de parâmetro
  • - não é um operador de subtração aqui, é uma negação, o que foi permitido de acordo com os comentários

Resultado:

$ ./20pct.sh 0,96
.19
$ ./20pct.sh 20,96
4.19
$ ./20pct.sh 1020.96
204.19
$ 
Trauma Digital
fonte
Eu acho que vejo uma barra aqui.
Milo
@Milo que /faz parte de uma expansão do parâmetro bash e não um operador de divisão. Permitido ou não?
Digital Trauma
11
Eu permitiria isso, não é um operador matemático neste caso ...
Wally West
11
-3 atua como uma negação, não como uma subtração ... @Milo, é necessário considerar a negação e outras maneiras pelas quais esses operadores podem ser usados ​​além de seus equivalentes matemáticos ... por exemplo + podem ser usados ​​como concatenadores em JavaScript. .. Posso fazer uma sugestão? Altere "Não use os seguintes operadores: + - * /%" para "Não use os seguintes operadores em sua forma matemática: + - * /%"
WallyWest
2
@WallyWest Para bancar o advogado do diabo, a negação aqui ainda é um operador matemático. Talvez "Não use os seguintes operadores em sua forma matemática não unária: + - * /%" ;-)
Digital Trauma
4

Python 98 * 0,8 = 78,4

d=`len('X'*int("{}{:>02}".format(*(raw_input()+".0").split('.')))*2)`;print'%s.%s'%(d[:-3],d[-3:])

Python 74 (sem bônus)

d=len('X'*int(raw_input().replace('.',''))*2);print'%s.%s'%(d[:-3],d[-3:])

Nota

  • + é usado para concatenação de cadeias
  • * usado para criar cópias de string

Ungolfed

def tip():
    amount = raw_input()
    #Add an extra decimal point so that we can accept integer
    #amount
    amount += ".0"
    #Split the integer and decimal part
    whole, frac = amount.split('.')
    #Multiply amount by 100 :-)
    amount = "{}{:>02}".format(whole, frac)
    #Create amount copies of a character
    st = 'X'*amount
    #Double it
    st *= 2
    #Calculate the Length
    d = len(st)
    #Display the result as 3 decimal fraction
    print'%s.%s'%(d[:-3],d[-3:])

Nota

No espírito da pergunta, acredito que a seguinte solução, embora siga todas as regras da pergunta, seja um abuso

Python 41

print __import__("operator")(input(),0.2)

Finalmente

Se você insiste que os símbolos matemáticos são proibidos, ela é uma solução de 90 caracteres

Python 90 (sem nenhum símbolo matemático)

print' '.join(str(int(raw_input().replace(".",""))<<1)).replace(' ','.',1).replace(' ','')
Abhijit
fonte
11
Como já foi dito, *e +estão quebradas as CHAVES (para o que você as usar).
Thomas Baruchel
2
@ ברוכאל: No use of the following in mathematical form operators: + - * / % (Thanks Wally West). Em outras palavras, a questão precisa ser reformulada. E eu não usei-los em forma matemática
Abhijit
OK, mas nesse caso, o voto negativo da solução APL não era realmente justo, pois nenhuma outra solução foi votada por esse motivo.
Thomas Baruchel
Sua resposta terá problemas com uma quantidade minúscula de dinheiro, por exemplo 0.05.
N
Você pode usar `input`(backticks incluídos) em vez de raw_input.
nyuszika7h
4

APL (9 caracteres, novo código com 7 caracteres, corrigido com 13 caracteres)

Calcule 20% da quantidade fornecida.

{⍟⍵*⍨*.2} 32

Em APL *é o operador exponencial.

Experimente online .

Mas por que usar uma função para isso? Veja esta nova versão:

⍟(*.2)* 32

Experimente online .

Por favor, antes da votação baixa, o *não é proibido como uma CHAVE e não significa multiplicação aqui.

OK, aqui está a versão arredondada para 2 casas decimais (Dyalog APL):

⎕PP←2⋄⍟(*.2)* 32.01
Thomas Baruchel
fonte
2
A exponenciação ainda é uma operação matemática e *não é permitida em nenhuma forma matemática, de acordo com as regras do desafio.
Tony Ellis
A exponenciação não é proibida aqui e outras soluções realmente a usam, mas você está certo quanto ao fato de *ser proibido como chave e não como seu significado matemático.
Thomas Baruchel
@ Tony H. Por favor, você poderia remover seu voto negativo, pois obviamente todos os comentários em outras soluções parecem finalmente aceitar tais CHAVES, desde que não sejam usados ​​para as operações matemáticas proibidas na lista inicial.
Thomas Baruchel
11
@ ברוכאל Entendo que o uso de um asterisco de qualquer maneira que pertença a um significado matemático é proibido, incluindo exponenciação. Todas as outras respostas até agora que usam expoentes estão em um idioma que usa o sinal de intercalação ( ^) para esse operador, ou uma chamada de função é usada. Não há especificação pelo OP que *não seja permitida apenas se for usada no contexto de multiplicação. Suspeito que seria útil que o OP decidisse sobre isso, acertar qual de nós está interpretando mal as regras do desafio e esclarecer a confusão.
Tony Ellis
11
Talvez ×e ÷sejam permitidos, esses não estão listados.
marinus
4

R, 30 27 36 34

Atualizado para arredondar para duas casas decimais

Guardou 2 caracteres graças ao plannapus

Cria um vetor de 0 a x e pega o 2º elemento.

a=function(x)round(seq(0,x,l=6)[2],2)

Exemplo:

> a(20.36)
[1] 4.07

Mais explicações:

seq(0,x,len=6)

cria um vetor de comprimento 6 de 0 ao valor de entrada x, com os valores igualmente espaçados.

> seq(0,5,len=6)
[1] 0 1 2 3 4 5

O primeiro valor é então 0%, o segundo 20%, o terceiro 40%, etc.

Rift
fonte
Espere o que ? Por favor dar mais detalhes de como ele funciona para aqueles (como eu) que não sabem R.
Michael M.
@ Michael atualizei a minha resposta para explicar o código
Rift
Sua solução não faz nenhum arredondamento.
N
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ você está certo (mas a maioria das soluções não está arredondando nada). 9 caracteres extras fariam arredondamentos "normais". Apenas arredondamento seria a maneira mais difícil ...
Rift
@Rift: Eu testei várias respostas (principalmente Python, JS e Perl, pois são facilmente disponíveis) e a maioria delas faz arredondamentos. Nenhum dos que eu testei aparece, no entanto.
N
3

dc + sed + pipes (44 caracteres)

Minha terceira resposta (uma APL, uma J e agora uma com o antigo e venerável dc).

dc -e 5o?p|sed -e 's/\(.\)$/.\1/'|dc -e 5i?p

Ele solicitará uma entrada INTEGER e calculará 20% de uma maneira complicada. A entrada é convertida na base 5 (fácil de fazer com muitas outras ferramentas, mas espere ...); um ponto é acrescentado antes do último dígito com sed (infelizmente, dc não consegue lidar muito bem com seqüências de caracteres) e ENTÃO, dc converte de volta da base 5 em um número flutuante (nem todas as ferramentas podem fazer isso).

Thomas Baruchel
fonte
11
A "entrada INTEGER" não atende às especificações. Eu acho que você pode corrigi-lo, alterando sua expressão sed: dc -e 5o?p|sed 's/\(.\)\./.\1/'|dc -e 5i?p. Com isso e removendo seds -es, isso é 42. Mas o resultado ainda não foi especificado (sem duas casas decimais)
Digital Trauma
@DigitalTrauma. Você está certo. Mas essa solução era na verdade uma prova de conceito e eu estava mais interessado na propriedade incomum da conversão de base em dc (e também em bc). Obrigado pelo seu comentário e sua correção no sed.
Thomas Baruchel
2

Python, 88

Não é nem um pouco curto, mas isso demonstra como deve ser feita uma divisão mental normal por cinco. Isso pressupõe que a entrada deve estar no formato xx.xx

import math
a,b=raw_input().split('.')
print'%.2f'%math.ldexp(float(a[0]+'.'+a[1]+b),1)

Ou para entrada de qualquer tamanho, é necessário adicionar 3 caracteres.

import math
a,b=raw_input().split('.')
print'%.2f'%math.ldexp(float(a[:-1]+'.'+a[-1]+b),1)

Explicação: Tomamos a entrada como sequência e, em seguida, movemos o ponto decimal uma casa para a frente (dividindo por 10). Em seguida, o convertemos para um float e usamos a ldexpfunção para multiplicá-lo por 2.

Observe que nesta resposta, os +operadores de concatenação são string e %são usados ​​para formatar print.

Se você insistir em não usar nenhum desses caracteres, aqui está uma solução de 159 caracteres:

import math
a,b=raw_input().split('.')
l=[a[0]]
l.append('.')
l.append(a[1])
l.append(b)
c=str(math.ldexp(float(''.join(l)),1))
print ''.join([c[0:2],c[2:4]])
user12205
fonte
Já disse para muitas outras respostas, mas eu realmente não acho isso +e -é permitido, pois as KEYS estão quebradas (o que elas significam no seu pedaço de código).
Thomas Baruchel
@ ברוכאל: Veja minha resposta ao seu comentário na minha resposta
Abhijit
Usou seu .split('.')na minha resposta, picada de um caractere
user80551
2

dc + sed - 45 * 0,8 = 36

(Inspirado na resposta de ברוכאל )

  • Lida com qualquer quantidade de ponta (número inteiro ou flutuante)

Execuções de exemplo (a entrada é aceita via STDIN):

$ dc -e 5o?.0+p|sed 's/\(.\)\./.\1/'|dc -e 5i?p
42
8.400
$ dc -e 5o?.0+p|sed 's/\(.\)\./.\1/'|dc -e 5i?p
20.96
4.1920
devnull
fonte
A .0+ideia é ótima; Votei na sua solução inspirada na minha, mas alguns podem dizer que você está usando adição; talvez alguma solução alternativa? Eu tentei, dc -e 9k5o?v2^pmas tem mais 2 caracteres.
Thomas Baruchel
@ ברוכאל Eu não sabia que o + mesmo nesse contexto poderia se qualificar como adição.
devnull
@ ברוכאל Eu vou excluir este. Solicite que você modifique o seu para que ele possa lidar com carros alegóricos e se qualificar para -20%!
devnull
2

Mathematica, 19

Log[(E^.2)^Input[]]

No uso dos operadores matemáticos de +, -,* , /, ou %. Usa propriedades dos logaritmos para calcular a resposta; quando você simplifica a expressão, você obtém.2*Input[]

Com o bônus ( 30 * 0,8 = 24 ):

Log[((E^.01)^Input[])^Input[]]

Insira a porcentagem primeiro e depois a quantidade.

Ao simplificar a expressão, você obtém Input[]*Input[]*.01 .

Agradecemos a ברוכאל pela ajuda na redução do código.

Justin
fonte
3
Tem certeza de que não pode ser simplificado? Para mim Log[E^2]ou Log[E^Input[]]pode ser escrito mais em breve. Even 10^-1pode ser escrito .01(embora eu não use o Mathematica, mas tenho certeza que ele pode). A expressão inteira (E^10^-1)^Log[E^2]parece ser algo como E^.2, não é?
Thomas Baruchel
1

TI-89 Básico - 39 * 0,8 = 31,2

Input y:Input x:Disp ln(((e^y)^.01)^x))

Funciona inserindo os dois números e, em seguida, usando as propriedades do logaritmo para calcular x * y / 100.

Se eu puder assumir a entrada do posicionamento em variáveis ​​globais xe y, isso é muito menor, para uma pontuação de 17 * 0,8 = 13,6 :

ln(((e^y)^.01)^x)

Sem bônus ( 12 ):

ln((e^.2)^x)

Mas se precisar ser envolvido em uma função, isso funcionará ( 38 caracteres, por 30,4 ):

:f(x,y):Func:ln(((e^y)^.01)^x):EndFunc
Justin
fonte
Por favor, veja meus comentários para sua outra solução (no Mathematica); esse código pode realmente ser muito simplificado.
Thomas Baruchel
Input x,y??? Trabalha em 83/84.
Timtech
Não @Timtech funciona em 89, mas talvez eu possa fazer algo assim Input{x,y}(não 83/84 tem ln?)
Justin
@ Quincunx Sim, veja minha nova resposta.
Timtech
žr¹msmžr.n- porta descarada deste código para 05AB1E.
Magic Octopus Urn
1

PHP 107 * .8 = 85,6

não posso realmente executar código-golfe com PHP, mas pelo menos eu posso operar com strings. aceita os dois números como argumentos da linha de comando.

<? @$r=strrev;unset($argv[0]);echo$r(substr_replace($r(str_replace('.','',array_product($argv)))),'.',2,0);

tive que reverter isso duas vezes desde que eu não posso usar -2 :(

Einacio
fonte
1

Python, 81 80 89 caracteres

a,b=map(str,raw_input().split('.'));c=str(int(a+b)<<1).zfill(4);print c[:-3]+'.'+c[-3:-1]

Explicação

x = raw_input()       # say 20.96
a , b = x.split('.')  # a = 20 , b = 96
c = a + b             # c = '2096'      # string concatenation , multiplying by 100
d = int(c)<<1         # multiply by 2 by bitshift left , c = 4096
e = str(d).zfill(4)   # zfill pads 0's making the string 
                      # atleast 4 chars which is required 
                      # for decimal notation next

#     divide by 1000 (4) + . (4.) + fraction rounded to 2 decimals (4.09)
print        e[:-3]      +   '.'  +              e[-3:-1]

Tecnicamente, isso é trapaça, pois trunca para duas casas decimais em vez de arredondá-la, mas posso argumentar que ela é arredondada para baixo (melhor para você, menos dica).

user80551
fonte
Eu acho que você pode fazer, em [-3:]vez de[-3:-1]
Justin
@ Quincunx Não é possível, o -1 é truncar com duas casas decimais.
user80551
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Sim, consertou.
user80551
1

JavaScript 251 (restrição forçada: não +, -, *,? Ou% de qualquer maneira)

Embora eu saiba que isso não vai ganhar, imaginei que tentaria obter pontos brownie adotando uma abordagem muito rigorosa e nem sequer pensaria em usar os operadores restritos de qualquer forma ou forma ... como resultado, criei essa beleza ...

A=(x,y)=>{for(;x;)b=x^y,x=(a=x&y)<<1,y=b;return y};D=(x,y,i=x,j=0)=>{for(;i>=y;)i=A(i,A(~y,1)),j=A(j,1);return j};alert(parseFloat((x="00".concat(String(D(prompt().replace(".",""),5)))).substr(0,A(x.length,y=A(~2,1))).concat(".").concat(x.substr(y))))

Eu usei operações bit a bit para criar a função Add Ae comecei a encadear a partir daí:

A função de divisão inteira Dusou uma série de Adição Negada (subtração na forma deA(x,A(~y,1) sobre um loop; o resto é manipulação e concatenação de cadeias, para evitar o uso de +operadores de concatenação ...

O número deve ser fornecido na forma decimal com duas casas decimais para que isso funcione ...

WallyWest
fonte
Ah, agora ... embora, se eu tivesse que seguir as novas regras, tivesse que expandir ... 251 bytes agora ...
Wally West
1

Perl, 50 60 bytes

$_=<>;s|\.||;$_<<=1;$_="00$_";m|\d{3}$|;printf'%.2f',"$`.$&"

A entrada é esperada em STDIN. Ele deve conter o separador decimal com dois dígitos decimais. A saída é gravada em STDOUT.

Atualização: a etapa $_<<=1remove os zeros iniciais. Portanto m|\d{3}$|, não corresponderia às contas <1. Portanto, $_="00$foram adicionados dez bytes , agora mesmo0.00 funciona.

Exemplos:

  • Entrada:, 20.96saída:4.19
  • Entrada: 12.34saída:2.47

Versão não destruída:

$_=<>;
s|\.||; # multiply by 100
$_ <<= 1; # multiply by 2
$_="00$_";
m|\d{3}$|; # divide by 1000
printf '%.2f'," $`.$&"

Primeiro, o número é lido em STDIN. Em seguida, o ponto decimal é removido, multiplicado por 100. Em seguida, o valor é dobrado por um operador de deslocamento. Em seguida, o ponto decimal é reinserido e o resultado é impresso e arredondado para dois dígitos decimais.

50 bytes, se a conta for ≥ 1:

Se x.xxfor maior ou igual a 1.00, 10 bytes podem ser removidos:

$_=<>;s|\.||;$_<<=1;m|\d{3}$|;printf'%.2f',"$`.$&"
Heiko Oberdiek
fonte
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳: Obrigado, corrigido agora.
Heiko Oberdiek
1

JavaScript (ES6) (Regex) 142

Regex é ótimo e pode fazer muitas coisas. Pode até fazer matemática!

a=('x'.repeat(prompt().replace('.', ''))+'xxxx').match(/^((x*)\2{99}(x{0,99}))\1{4}x{0,4}$/);c=a[3].length;alert(a[2].length+'.'+(c<10?'0'+c:c))

Versão legível:

function tip(m) {
    var s = 'x'.repeat(m.replace('.', '')) + 'xxxx';
    var a = s.match(/^((x*)\2{99}(x{0,99}))\1{4}x{0,4}$/);
    var c = a[3].length;
    if (c < 10) c = '0' + c;
    return a[2].length + '.' + c;
}

A tip()função espera o argumento String, em vez de Number.

Todas as instâncias de *, /, +não estão relacionados com operações matemáticas.

  • + é concatenação de strings em todas as instâncias em que é usado.
  • * faz parte da sintaxe RegExp
  • / é o delimitador do literal RegExp

A entrada deve ser usada .como ponto decimal e deve haver haver 2 dígitos após o ponto decimal.

Snippet de pilha

<button onclick = "a=('x'.repeat(prompt().replace('.', ''))+'xxxx').match(/^((x*)\2{99}(x{0,99}))\1{4}x{0,4}$/);c=a[3].length;alert(a[2].length+'.'+(c<10?'0'+c:c))">Try it out</button>

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
fonte
0

Haskell 32 caracteres -20% = 25,6 caracteres

t y x=log $(^x)$(**0.01)$ exp y

Abusa do fato de que expoentes se tornam multiplicação em logaritmos.

PyRulez
fonte