Calcola un suggerimento


16

Tu e un amico entrate in un bar. Il barista ti tratta bene, quindi decidi di dargli la mancia. Quindi estraete il vostro fidato computer tascabile e scrivete un programma rapido per calcolare un suggerimento per voi poiché non ha una calcolatrice integrata. Ma aspetta! Le chiavi dell'operatore sono rotte! Il tuo compito è calcolare una mancia del 20% per ogni dato importo di input. Gli ingressi del test saranno in forma di xx.xx, ad es. 20.96. Ecco le regole:

  • Nessun uso di quanto segue negli operatori di moduli matematici: + - * / %(Grazie Wally West)
  • Nessun uso di funzioni percentuali o API integrate
  • Nessun accesso alla rete
  • Nessun uso evalo simili
  • Nessun calcolatore di Windows (sì, le persone hanno già risposto in precedenza)
  • Nessuna funzione di suggerimento integrata (non che nessuna lingua ne abbia una)

L'output deve essere arrotondato al massimo di due decimali.

Il punteggio si basa sulla lunghezza in byte.

-20% se il programma può accettare qualsiasi importo di mancia. L'immissione dell'importo verrà fornita sotto forma di xx, ad es. 35 e non 0,35


5
@mniip: un suggerimento è una bizzarra quantità extra di denaro che ti aspetti di pagare in un ristorante che non fa parte del prezzo ufficiale. Non so se lo fanno in Russia.
user2357112 supporta Monica

5
Oh, quella nuova generazione ... Preferirei usare carta e penna se non riesco a dividere mentalmente un numero per 5.
VisioN,

4
@VisioN Nota: dividere per cinque equivale a dividere per 10, quindi moltiplicare per 2, ed entrambi dovrebbero essere operazioni mentali molto facili.
user12205

1
Qualcuno può chiarire le regole: è consentito utilizzare le operazioni vietate se non si utilizzano tali operatori? La moltiplicazione è consentita se non si utilizza *?
Ypnypn,

2
@TheDoctor è davvero un duplicato però? Perché non sta aggiungendo.
Milo,

Risposte:


18

Javascript 81

EDIT : il risultato è ora un vero arrotondamento, non troncato.

Non usare NESSUNA matematica qui, solo manipolazione di stringhe e operatori bit per bit.
Tutti i +caratteri sono concatenazione di stringhe o conversione da stringa a virgola mobile .
Funziona con qualsiasi input e output xx.xx in formato (x) x.xx

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

Trucco spiegato: il 20% è diviso per 10 e moltiplicato per 2.

  • Fai una divisione per 10 spostandoti il punto a sinistra (manipolazione stringa)
  • Moltiplicare ogni parte per 2 spostando i bit verso sinistra (operazione bit a bit)

Quando l'input è 99.99, questo ritorna 19.998, quindi non è "arrotondato al massimo di due decimali" come per l'OP.
Geobits

2
Questa è una soluzione lunga, ma ha 12 voti. Cosa sta succedendo con il voto di code-golf?
Giustino,

@Quincunx Sì, hai ragione, non è un concorso di popolarità!
Mukul Kumar,

Dato che si tratta di un codice-golf, probabilmente non vincerò, ma questo non significa che alla gente non piacerà la mia soluzione ... Spesso, i vincitori del codice-golf non sono quelli con il maggior numero di voti.
Michael M.

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, assolutamente! Grazie per averlo segnalato. Risolto ora :)
Michael M.

6

J (9 caratteri)

Una breve risposta in J:

^.(^.2)^~ 32

1
... e io non parlo J. Che cosa dice?
Cugina Cocaina,

Dice: calcolo 32 elevato a power log (2); di solito, l'esponente è alla destra di ^ma qui ~indica che l'ordine dovrebbe essere invertito; (^.2)è log (.2) e l'iniziale ^.che viene eseguita per ultima è il logaritmo di tutto il calcolo precedente: quindi log (32 ^ log (.2))
Thomas Baruchel

4

Bash puro, 50 43 caratteri

Abbastanza sicuro che questo sarà battuto, ma ecco un inizio:

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

Secondo i commenti:

  • /non è un operatore di divisione qui, fa parte dell'espansione di un parametro di sostituzione del modello
  • % non è un operatore modulo qui, fa parte dell'espansione di un parametro
  • - non è un operatore di sottrazione qui, è una negazione, che è stata consentita secondo i commenti

Produzione:

$ ./20pct.sh 0.96
.19
$ ./20pct.sh 20.96
4.19
$ ./20pct.sh 1020.96
204,19
$ 

Penso di vedere una barra in avanti.
Milo,

@Milo che /fa parte dell'espansione di un parametro bash e non di un operatore di divisione. Consentito o no?
Trauma digitale

1
Lo permetterei, in questo caso non è un operatore matematico ...
WallyWest

1
-3 funge da negazione, non da sottrazione ... @Milo, è necessario tenere conto della negazione e di altri modi in cui questi operatori possono essere utilizzati a parte i loro equivalenti matematici ... ad esempio + può essere usato come concatenatore in JavaScript. .. Posso dare un suggerimento? Modifica "Nessun utilizzo dei seguenti operatori: + - * /%" su "Nessun utilizzo dei seguenti operatori nella loro forma matematica: + - * /%"
WallyWest

2
@WallyWest Per interpretare l'avvocato del diavolo, la negazione qui è ancora un operatore matematico. Forse "Nessun uso dei seguenti operatori nella loro forma matematica non unaria: + - * /%" ;-)
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 (senza bonus)

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

Nota

  • + viene utilizzato per la concatenazione di stringhe
  • * usato per creare copie di stringhe

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

Nello spirito della domanda, credo che la seguente soluzione sebbene segua tutte le regole della domanda è un abuso

Python 41

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

Infine

Se insisti sul fatto che i simboli matematici sono vietati, lei è una soluzione di 90 caratteri

Python 90 (senza alcun simbolo matematico)

print' '.join(str(int(raw_input().replace(".",""))<<1)).replace(' ','.',1).replace(' ','')

1
Come già detto, *e +vengono rotti i TASTI (qualunque cosa li usi).
Thomas Baruchel,

2
@ ברוכאל: No use of the following in mathematical form operators: + - * / % (Thanks Wally West). In altre parole, la domanda deve essere riformulata. E non li ho usati in forma matematica
Abhijit,

OK, ma in quel caso, il downvote della soluzione APL non era davvero giusto, dal momento che nessun'altra soluzione è stata votata per quel motivo.
Thomas Baruchel,

La tua risposta avrà problemi con un importo minimo di denaro, ad es 0.05.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

È possibile utilizzare `input`(backtick inclusi) invece di raw_input.
nyuszika7h,

4

APL (9 caratteri, nuovo codice con 7 caratteri, fisso con 13 caratteri)

Calcola il 20% dell'importo indicato.

{⍟⍵*⍨*.2} 32

In APL *è l'operatore esponenziale.

Provalo online .

Ma perché usare una funzione per questo? Vedi questa nuova versione:

⍟(*.2)* 32

Provalo online .

Per favore, prima del downvoting, *non è vietato come CHIAVE e non significa moltiplicazione qui.

OK, ecco l'arrotondamento della versione a 2 decimali (Dyalog APL):

⎕PP←2⋄⍟(*.2)* 32.01

2
Exponentiation is still a mathematical operation, and * is disallowed in any mathematical form as per the rules of the challenge.
Tony Ellis

Exponentiation is not fobidden here and other solutions actually use it, but you are right concerning the fact that * is forbidden as a key and not as its mathematical meaning.
Thomas Baruchel

@Tony H. Please, could you remove your downvote, since obviously all comments in other solutions seem to finally accept such KEYS as long as they aren't used for the forbidden mathematical operations in the initial list.
Thomas Baruchel

1
@ ברוכאל Comprendo che l'uso di un asterisco in qualsiasi modo pertinente a un significato matematico sia proibito, compreso l'espiazione. Ogni altra risposta finora che utilizza esponenti è in una lingua che utilizza il punto di inserimento ( ^) per tale operatore, oppure viene utilizzata una chiamata di funzione. Non esiste alcuna specifica da parte dell'OP che *non sia consentita solo se utilizzata nel contesto della moltiplicazione. Ho il sospetto che sarebbe utile se l'OP dovesse decidere su questo, stabilire chi di noi interpreta male le regole della sfida e chiarire la confusione.
Tony Ellis,

1
Forse ×e ÷sono ammessi, quelli non sono elencati.
Marin

4

R, 30 27 36 34

Updated to round to 2 decimal places

Saved 2 characters thanks to plannapus

Creates a vector from 0 to x and takes the 2nd element.

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

Example:

> a(20.36)
[1] 4.07

Further explanation:

seq(0,x,len=6)

creates a vector of length 6 from 0 to the input value x, with the values in between equally spaced.

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

The first value is then 0%, the second 20%, third 40%, etc.


Wait... what ? Please give more details of how it works for those (like me) who don't know R.
Michael M.

@Michael updated my answer to explain the code
Rift

Your solution doesn't do any rounding.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ you are right (but most solutions aren't rounding anything). 9 extra characters would do "normal" rounding. Only rounding up would be way harder...
Rift

@Rift: I have tested several answers (mostly Python, JS and Perl, since they are easily available) and most of them do rounding. None of those I have tested rounds up, though.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

3

dc + sed + pipes (44 characters)

My third answer (one APL, one J, and now one with the old and venerable dc).

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

It will ask for an INTEGER input and compute 20% with a tricky way. Input is converted to base 5 (easy to do with many other tools but wait...); a dot is appended before the last digit with sed (unfortunately, dc can't handle strings very well), and THEN, dc converts back from base 5 on a float number (not all tools can do that).


1
"INTEGER input" doesn't meet the spec. I think you can fix it by changing your sed expression: dc -e 5o?p|sed 's/\(.\)\./.\1/'|dc -e 5i?p. With this and removing seds -es, this is 42. But the result is still not to spec (not 2 decimal places)
Digital Trauma

@DigitalTrauma. You are right. But this solution was actually rather a proof of concept and I was more interested by the unusual property of base conversion in dc (and also in bc). Thank you for your comment and your fix in sed.
Thomas Baruchel

2

Python, 88

This is no where near short, but this demonstrate how a normal mental division by five should be done. This assumes that the input must be of the form xx.xx

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

Or for input of any length, an addition of 3 characters is required.

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

Explanation: We take the input as string, then move the decimal point one place forward (dividing by 10). We then cast it to a float, and use the ldexp function to multiply it by 2.

Note that in this answer, the + are string concatenation operators, and the % are used to format print.

If you insist on not using any of these characters, here is a 159 character solution:

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

Already said for many other answers, but I really don't think that + and - are allowed since the KEYS are broken (whatever they mean in your piece of code).
Thomas Baruchel

@ברוכאל: See my response to your comment in my answer
Abhijit

Used your .split('.') in my answer, chopped one char
user80551

2

dc + sed -- 45 * 0.8 = 36

(Inspired by the answer by ברוכאל)

  • Handles any tip amount (integer or float)

Example runs (input is accepted 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

The .0+ idea is great; I voted up for your solution inspired by mine, but some may tell you are using addition; maybe some workaround? I tried dc -e 9k5o?v2^p but it is 2 characters more.
Thomas Baruchel

@ברוכאל I didn't realize that the + even in this context might qualify as addition.
devnull

@ברוכאל I'll delete this one. Request you to modify your so that it could handle floats and qualify for -20%!
devnull

2

Mathematica, 19

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

No use of the mathematical operators of +, -, *, /, or %. Uses properties of logarithms to calculate the answer; when you simplify the expression, you get .2*Input[]

With the bonus (30 * 0.8 = 24):

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

Input the percentage first, then the amount.

When you simplify the expression, you get Input[]*Input[]*.01.

Thanks to ברוכאל for help with shortening the code.


3
Are you really sure it can't be simplified? To me Log[E^2] or Log[E^Input[]] can be written more shortly. Even 10^-1 can be written .01 (though I don't use Mathematica but I am pretty sure it can). The whole expression (E^10^-1)^Log[E^2] seems to be something like E^.2, isn't it?
Thomas Baruchel

1

TI-89 Basic - 39 * 0.8 = 31.2

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

Works by inputting the two numbers, then using the logarithm properties to compute x * y / 100.

If I can assume input from placement in global variables x and y, then this is much shorter, for a score of 17 * 0.8 = 13.6:

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

Without bonus (12):

ln((e^.2)^x)

But if it needs to be wrapped in a function, then this works (38 chars, for 30.4):

:f(x,y):Func:ln(((e^y)^.01)^x):EndFunc

Please, see my comments to your other solution (in Mathematica); this code can really be simplified much.
Thomas Baruchel

Input x,y ??? Works in 83/84.
Timtech

@Timtech Doesn't work in 89, but maybe I can do something like Input{x,y} (does 83/84 have ln?)
Justin

@Quincunx Yes, see my new answer.
Timtech

žr¹msmžr.n - shameless port of this code into 05AB1E.
Magic Octopus Urn

1

PHP 107 *.8 = 85.6

can't really run for code-golf with PHP, but at least I can operate on strings. accepts both numbers as command-line arguments.

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

had to reverse it twice since I can't use -2 :(


1

Python, 81 80 89 characters

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

Explanation

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]

Technically, this is cheating as it truncates to two decimals rather than rounding it but I can argue that it rounds down(Better for you, less tip).


I think you can do [-3:] instead of [-3:-1]
Justin

@Quincunx Can't , the -1 is to truncate to two decimals.
user80551

@n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Yep, fixed it.
user80551

1

JavaScript 251 (forced restriction: no +, -, *, ? or % in any manner)

While I know this won't win, I figured I'd try to get brownie points through taking a very strict approach and not even think about using the restricted operators in any shape or form... as a result, I came up with this beauty...

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))))

I used bitwise operations to create the Add function A, and then started chaining up from there:

The integer division function D used a series of Negated Addition (subtraction in the form of A(x,A(~y,1) over a loop; the rest is string manipulation and concatenation so as to avoid using + concatenation operators...

The number must be provided in decimal form with two decimal places for this to work...


Ah, it will now... though if I had to keep to the new rules, I had to expand on it... 251 bytes now...
WallyWest

1

Perl, 50 60 bytes

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

The input is expected at STDIN. It must contain the decimal separator with two decimal digits. The output is written to STDOUT.

Update: The step $_<<=1 removes leading zeroes. Therefore m|\d{3}$| would not match for bills < 1. Therefore ten bytes $_="00$ were added, Now even 0.00 works.

Examples:

  • Input: 20.96, output: 4.19
  • Input: 12.34, output: 2.47

Ungolfed version:

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

First the number is read from STDIN. Then the decimal dot is removed, that is multiplied with 100. Then the amount is doubled by a shifting operator. Then the decimal dot is reinserted and the result is printed and rounded to two decimal digits.

50 bytes, if bill ≥ 1:

If x.xx is greater or equal than 1.00, then 10 bytes can be removed:

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

@n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳: Thanks, fixed now.
Heiko Oberdiek

1

JavaScript (ES6) (Regex) 142

Regex is great and it can do many things. It can even do maths!

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))

Readable version:

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;
}

The tip() function expects String argument, rather than Number.

All instances of *, /, + are not related to math operations.

  • + is string concatenation in all instances it is used.
  • * is part of RegExp syntax
  • / is the delimiter of RegExp literal

The input must use . as decimal point, and there must be 2 digits after decimal point.

Stack Snippet

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


0

Haskell 32 Chars -20% = 25.6 Chars

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

Abuses the fact that exponents become multiplication in logarithms.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.