Oblicz napiwek

16

Ty i przyjaciel wchodzicie do baru. Barman traktuje cię dobrze, więc decydujesz się go napiwić. Wyciągasz zaufany komputer kieszonkowy i piszesz szybki program, który obliczy dla ciebie wskazówkę, ponieważ nie ma wbudowanego kalkulatora. Ale poczekaj! Twoje klucze operatora są zepsute! Twoim zadaniem jest obliczyć 20% napiwek dla dowolnej kwoty wejściowej. Wejścia testowe będą miały postać xx.xx, np. 20,96. Oto zasady:

  • Bez użycia następujących operatorów matematycznych: + - * / %(Dzięki Wally West)
  • Bez użycia wbudowanych funkcji procentowych lub interfejsów API
  • Brak dostępu do sieci
  • Bez użycia evallub podobne
  • Brak kalkulatora systemu Windows (tak, ludzie już wcześniej odpowiedzieli)
  • Brak wbudowanych funkcji podpowiedzi (nie żeby żaden język miałby taki)

Dane wyjściowe należy zaokrąglić w górę do dwóch miejsc po przecinku.

Wynik oparty jest na długości w bajtach.

-20%, jeśli twój program może zaakceptować dowolną kwotę napiwku. Dane dotyczące kwoty zostaną podane w postaci xx, np. 35, a nie 0,35

Milo
źródło
5
@mniip: Napiwek to dziwna dodatkowa kwota, którą należy zapłacić w restauracji, która nie jest częścią oficjalnej ceny. Nie wiem, czy robią to w Rosji.
user2357112 obsługuje Monikę
5
Och, ta nowa generacja ... Wolę używać papieru i pióra, jeśli nie mogę mentalnie podzielić liczby przez 5.
VisioN
4
@VisioN Uwaga: dzielenie przez pięć jest równoważne dzieleniu przez 10, a następnie mnożeniu przez 2, i oba powinny być bardzo łatwymi operacjami umysłowymi.
user12205
1
Czy ktoś może wyjaśnić zasady: Czy korzystanie z zabronionych operacji jest dozwolone, jeśli nie korzystasz z tych operatorów? Czy mnożenie jest dozwolone, jeśli nie używasz *?
Ypnypn
2
@TheDoctor czy to naprawdę duplikat? Ponieważ to nie dodaje.
Milo,

Odpowiedzi:

18

JavaScript 81

EDYCJA : Rezultatem jest teraz prawdziwe zaokrąglenie, nie obcięte.

Nie używaj ŻADNEJ matematyki, tylko manipulacje ciągami i operatory bitowe.
Wszystkie +znaki są konkatenacją ciągów lub konwersją ciągów do pływaków .
Działa z dowolnym wejściem i wyjściem xx.xx w formacie (x) x.xx

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

Sztuczka wyjaśniona: 20% jest dzielone przez 10 i mnożone przez 2.

  • Dokonaj podziału przez 10, poruszając się kropkę w lewo (manipulacja sznurkiem)
  • Pomnóż każdą część przez 2, przesuwając bity w lewo (operacja bitowa)
Michael M.
źródło
Gdy dane wejściowe są 99.99zwracane 19.998, więc nie są one „zaokrąglane w górę do dwóch miejsc po przecinku” zgodnie z OP.
Geobits
2
Umm, to długie rozwiązanie, ale ma 12 głosów pozytywnych. Co się dzieje z głosowaniem Code-Golf?
Justin
@Quincunx Tak, masz rację, to nie konkurs popularności!
Mukul Kumar
Ponieważ jest to gra w golfa kodowego, prawdopodobnie nie wygram, ale to nie znaczy, że ludzie nie mogą polubić mojego rozwiązania ... Często zwycięzcy gry w golfa kodowego nie mają takich pozytywnych opinii.
Michael M.
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳, absolutnie! Dziękujemy za zwrócenie na to uwagi. Naprawiono teraz :)
Michael M.
6

J (9 znaków)

Krótka odpowiedź w J:

^.(^.2)^~ 32
Thomas Baruchel
źródło
1
... a ja nie mówię J. Co to mówi?
CousinCocaine
Mówi: oblicz 32, podniesiony do logu mocy (2); zwykle wykładnik znajduje się po prawej stronie, ^ale tutaj ~oznacza, że ​​kolejność powinna zostać odwrócona; (^.2)jest log (.2), ​​a inicjałem, ^.który jest wykonywany jako ostatni, jest logarytm wszystkiego, z czego obliczono wcześniej: zatem log (32 ^ log (.2))
Thomas Baruchel
4

Pure Bash, 50 43 znaków

Jestem pewien, że to zostanie pokonane, ale oto początek:

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

Zgodnie z komentarzami:

  • /nie jest tutaj operatorem podziału, jest częścią rozszerzenia parametru podstawiania wzorca
  • % nie jest tutaj operatorem modulo, jest częścią rozszerzenia parametru
  • - nie jest tutaj operatorem odejmowania, jest negacją, która była dozwolona zgodnie z komentarzami

Wynik:

0,20pct.sh 0,96
.19
./20pct.sh 20,96
4.19
.20pct.sh 1020.96
204,19
$ 
Cyfrowa trauma
źródło
Myślę, że widzę tam cięcie do przodu.
Milo,
@Milo, który /jest częścią rozszerzenia parametru bash, a nie operatorem podziału. Dozwolone czy nie?
Digital Trauma
1
Pozwoliłbym na to, w tym przypadku nie jest to operator matematyczny ...
WallyWest
1
-3 działa jak negacja, a nie odejmowanie ... @Milo, musisz wziąć pod uwagę negację i inne sposoby, w których operatory te mogą być używane oprócz ich matematycznych odpowiedników ... na przykład + może być używany jako konkatenator w JavaScript. .. Czy mogę coś zasugerować? Zmień
Nieużywanie
2
@WallyWest Aby zagrać w adwokata diabła, negacja jest nadal operatorem matematycznym. Być może „Nie ma zastosowania następujących operatorów w ich niejednorodnej formie matematycznej: + - * /%” ;-)
Cyfrowa 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 (bez premii)

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

Uwaga

  • + służy do łączenia łańcuchów
  • * służy do tworzenia kopii ciągu

Nie golfił

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

Uwaga

W duchu pytania uważam, że poniższe rozwiązanie jest zgodne z wszystkimi zasadami tego pytania i stanowi nadużycie

Python 41

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

Wreszcie

Jeśli nalegasz, aby symbole matematyczne były zabronione, ma 90-znakowe rozwiązanie

Python 90 (bez żadnego symbolu matematycznego)

print' '.join(str(int(raw_input().replace(".",""))<<1)).replace(' ','.',1).replace(' ','')
Abhijit
źródło
1
Jak już powiedziano, *i +są zepsute KLUCZE (do czego ich używasz).
Thomas Baruchel
2
@ ברוכאל: No use of the following in mathematical form operators: + - * / % (Thanks Wally West). Innymi słowy, pytanie należy przeformułować. I nie użyłem ich w formie matematycznej
Abhijit
OK, ale w takim przypadku głosowanie na rozwiązanie APL nie było naprawdę uczciwe, ponieważ żadne inne rozwiązanie nie zostało z tego powodu odrzucone.
Thomas Baruchel
Twoja odpowiedź będzie miała problem z niewielką ilością pieniędzy, np 0.05.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
Możesz użyć `input`(backticks w zestawie) zamiast raw_input.
nyuszika7h
4

APL (9 znaków, nowy kod z 7 znakami, ustalony z 13 znakami)

Oblicz 20% podanej kwoty.

{⍟⍵*⍨*.2} 32

W APL * jest operatorem wykładniczym.

Wypróbuj online .

Ale po co do tego używać funkcji? Zobacz nową wersję:

⍟(*.2)* 32

Wypróbuj online .

Proszę, przed oddaniem głosu, * nie jest zabronione jako KLUCZ i nie oznacza tutaj mnożenia.

OK, oto wersja zaokrąglona do 2 miejsc po przecinku (Dyalog APL):

⎕PP←2⋄⍟(*.2)* 32.01
Thomas Baruchel
źródło
2
Potęgowanie jest nadal operacją matematyczną i *jest niedozwolone w jakiejkolwiek formie matematycznej zgodnie z regułami wyzwania.
Tony Ellis,
Potęgowanie nie jest tutaj zabronione i inne rozwiązania faktycznie go wykorzystują, ale masz rację co do faktu, że *jest zabroniony jako klucz, a nie jako jego matematyczne znaczenie.
Thomas Baruchel
@ Tony H. Proszę, możesz usunąć swoją opinię, ponieważ oczywiście wszystkie komentarze w innych rozwiązaniach wydają się w końcu akceptować takie KLUCZE, o ile nie są one używane do zabronionych operacji matematycznych na początkowej liście.
Thomas Baruchel
1
@ כאלרוכאל Rozumiem, że użycie gwiazdki w jakikolwiek sposób odnoszący się do znaczenia matematycznego jest zabronione, w tym potęgowanie. Każda inna jak dotąd odpowiedź wykorzystująca wykładniki jest w języku, który używa ^znaku daszka ( ) dla takiego operatora, lub używane jest wywołanie funkcji. Nie ma specyfikacji przez OP, która *jest niedozwolona tylko wtedy, gdy jest używana w kontekście mnożenia. Podejrzewam, że byłoby pomocne, gdyby OP miał o tym zadecydować, ustalić, który z nas źle interpretuje reguły wyzwania i wyjaśnić zamieszanie.
Tony Ellis,
1
Być może ×i ÷są dozwolone, nie ma ich na liście.
marinus
4

R, 30 27 36 34

Zaktualizowano do zaokrąglenia do 2 miejsc po przecinku

Uratował 2 postacie dzięki plannapusowi

Tworzy wektor od 0 do x i przyjmuje drugi element.

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

Przykład:

> a(20.36)
[1] 4.07

Dalsze wyjaśnienia:

seq(0,x,len=6)

tworzy wektor o długości 6 od 0 do wartości wejściowej x, z wartościami pomiędzy równo rozmieszczonymi.

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

Pierwsza wartość wynosi wtedy 0%, druga 20%, trzecia 40% itd.

Strzelanina
źródło
Czekaj, co ? Podaj więcej szczegółów, jak to działa dla tych (takich jak ja), którzy nie znają R.
Michael M.
@Michael zaktualizował moją odpowiedź, aby wyjaśnić kod
Rift
Twoje rozwiązanie nie zaokrągla.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳ masz rację (ale większość rozwiązań niczego nie zaokrągla). 9 dodatkowych znaków wykonałoby „normalne” zaokrąglanie. Tylko zaokrąglenie w górę byłoby znacznie trudniejsze ...
Rift
@Rift: Przetestowałem kilka odpowiedzi (głównie Python, JS i Perl, ponieważ są one łatwo dostępne) i większość z nich zaokrągla. Jednak żaden z tych, które testowałem, nie zaokrągla w górę.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
3

dc + sed + pipe (44 znaki)

Moja trzecia odpowiedź (jedna APL, jedna J, a teraz jedna ze starym i czcigodnym dc).

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

Poprosi o wprowadzenie wartości INTEGER i obliczy 20% w trudny sposób. Dane wejściowe są konwertowane na bazę 5 (łatwe do zrobienia z wieloma innymi narzędziami, ale czekaj ...); kropka jest dodawana przed ostatnią cyfrą z sed (niestety, dc nie radzi sobie bardzo dobrze z łańcuchami), A NASTĘPNIE, dc konwertuje z bazy 5 na liczbę zmiennoprzecinkową (nie wszystkie narzędzia mogą to zrobić).

Thomas Baruchel
źródło
1
„Wejście INTEGER” nie spełnia specyfikacji. Myślę, że można to naprawić zmieniając sed wyrażenia: dc -e 5o?p|sed 's/\(.\)\./.\1/'|dc -e 5i?p. Po tym i usunięciu seds -e, to jest 42. Ale rezultatem wciąż nie jest specyfikacja (nie 2 miejsca po przecinku)
Digital Trauma
@DigitalTrauma. Masz rację. Ale to rozwiązanie było raczej dowodem koncepcji i bardziej interesowała mnie niezwykła właściwość konwersji bazy w dc (a także w bc). Dziękujemy za komentarz i poprawkę w sed.
Thomas Baruchel,
2

Python, 88

Nie jest to wcale takie krótkie, ale pokazuje to, jak należy dokonać normalnego podziału mentalnego na pięć. Zakłada się, że dane wejściowe muszą mieć postać xx.xx

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

Lub do wprowadzenia dowolnej długości wymagane są dodatkowe 3 znaki.

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

Objaśnienie: Pobieramy dane wejściowe jako ciąg znaków, a następnie przesuwamy kropkę dziesiętną o jedno miejsce do przodu (dzieląc przez 10). Następnie rzucamy go na liczbę zmiennoprzecinkową i używamy ldexpfunkcji do pomnożenia przez 2.

Zauważ, że w tej odpowiedzi +są operatorami konkatenacji łańcuchów i %służą do formatowania print.

Jeśli nalegasz, aby nie używać żadnego z tych znaków, oto rozwiązanie dla 159 znaków:

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]])
użytkownik12205
źródło
Mówiłem już o wielu innych odpowiedziach, ale tak naprawdę nie sądzę +i -są dozwolone, ponieważ klucze są zepsute (cokolwiek oznaczają w twoim kodzie).
Thomas Baruchel
@ כאלרוכאל: Zobacz moją odpowiedź na Twój komentarz w mojej odpowiedzi
Abhijit
.split('.')
Użyłem
2

dc + sed - 45 * 0,8 = 36

(Zainspirowany odpowiedzi przez ברוכאל )

  • Obsługuje dowolną liczbę końcówek (liczbę całkowitą lub zmiennoprzecinkową)

Przykładowe przebiegi (dane wejściowe są akceptowane przez 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
źródło
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.

Justin
źródło
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
Justin
źródło
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 :(

Einacio
źródło
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).

user80551
źródło
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...

WallyWest
źródło
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',"$`.$&"
Heiko Oberdiek
źródło
@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>

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
źródło
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.

PyRulez
źródło