팁 계산


16

당신과 친구가 술집에 들어갑니다. 바텐더는 당신을 잘 대접하므로 팁을 주기로 결정합니다. 신뢰할 수있는 포켓 컴퓨터를 꺼내고 계산기가 내장되어 있지 않으므로 팁을 계산하는 빠른 프로그램을 작성하십시오. 하지만 기다려! 운영자 키가 고장났습니다! 주어진 입력량에 대해 20 % 팁을 계산해야합니다. 테스트 입력은 xx.xx 형식입니다 (예 : 20.96). 규칙은 다음과 같습니다.

  • 수학 양식 연산자에서 다음을 사용하지 마십시오. + - * / %(Willy West 감사합니다)
  • 내장 퍼센트 함수 또는 API를 사용하지 않음
  • 네트워크에 액세스하지 않습니다
  • 사용 eval또는 유사 하지 않음
  • Windows 계산기 없음 (예 : 이전에 답변을받은 사람)
  • 내장 된 팁 기능이 없음

출력은 소수점 이하 두 자리로 반올림되어야합니다.

점수는 바이트 길이를 기준으로합니다.

프로그램이 팁 금액을 수락 할 수있는 경우 -20 % 금액에 대한 입력은 xx 형식으로 제공됩니다 (예 : 35가 아닌 0.35).


5
@ mniip : 팁은 공식 가격의 일부가 아닌 식당에서 지불해야 할 기괴한 추가 금액입니다. 그들이 러시아에서 그렇게하는지 모르겠습니다.
user2357112는 Monica

5
오, 그 신세대 .. 정신적으로 숫자를 5로 나눌 수 없다면 종이와 펜을 사용하고 싶습니다.
VisioN

4
@VisioN 참고 : 5로 나누는 것은 10으로 나누고 2를 곱한 것과 같으며 둘 다 매우 쉬운 정신 연산이어야합니다.
user12205

1
누군가가 규칙을 명확하게 설명 할 수 있습니까? 금지 된 작업을 사용할 수 있습니까? 사용하지 않으면 곱셈이 허용 *됩니까?
Ypnypn

2
@ TheDoctor 정말 중복입니까? 추가하지 않기 때문입니다.
Milo

답변:


18

자바 스크립트 81

편집 : 결과는 이제 잘리지 않고 실제 반올림입니다.

사용하지 마십시오 어떤 여기에 수학, 단지 문자열 조작 및 비트 연산자.
모든 +문자는 문자열 연결 또는 문자열 대 부동 변환입니다.
(x) x.xx 형식의 모든 xx.xx 입력 및 출력에 작동

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

트릭 설명 : 20 %는 10으로 나누어지고 2가 곱해집니다.

  • 점을 왼쪽 으로 이동 하여 10으로 나누기 (문자열 조작)
  • 비트를 왼쪽 으로 이동 하여 각 파트에 2를 곱합니다 (비트 연산)

input이 99.99이면을 반환 19.998하므로 OP에 따라 소수점 이하 두 자리로 반올림되지 않습니다.
Geobits

2
음, 이것은 긴 해결책이지만 12 개의 공감대가 있습니다. 코드 골프 투표는 어떻게 되나요?
Justin

@Quincunx 그렇습니다. 인기 콘테스트가 아닙니다!
Mukul Kumar

그것이 코드 골프이기 때문에 아마 이길 수는 없지만 사람들이 내 솔루션을 좋아할 수 없다는 것을 의미하지는 않습니다 ... 종종 코드 골프 승자가 가장 많은 공짜를 가진 사람들이 아닙니다.
Michael M.

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, 절대적으로! 이것을 지적 해 주셔서 감사합니다. 수정되었습니다 :)
Michael M.

6

J (9 자)

J의 짧은 대답 :

^.(^.2)^~ 32

1
... 저는 J를 못해요. 무슨 말입니까?
CousinCocaine

그것은 계산한다 : 32를 power log (2)로 올렸다; 일반적으로 지수는 오른쪽에 ^있지만 여기 ~에서 순서를 반대로해야합니다. (^.2)는 log (.2)이고 ^.마지막으로 실행되는 초기 값은 이전에 계산 된 모든 것의 로그입니다. 따라서 log (32 ^ log (.2))
Thomas Baruchel

4

순수 배쉬, 50 43 문자

이길 것이라고 확신하지만 시작은 다음과 같습니다.

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

의견에 따라 :

  • / 여기에 나누기 연산자가 아니며 패턴 대체의 일부입니다. 매개 변수 확장의
  • % 여기서 모듈로 연산자가 아니며 매개 변수 확장의 일부입니다.
  • - 여기에 빼기 연산자가 아니라 부정입니다. 주석에 따라 허용되었습니다.

산출:

$ ./20pct.sh 0.96
.19
$ ./20pct.sh 20.96
4.19
$ ./20pct.sh 1020.96
204.19
$ 

나는 거기에 슬래시가 보인다고 생각합니다.
Milo

@Milo 는 나누기 연산자가 아닌 bash 매개 변수 확장의/ 일부입니다 . 허용 여부
Digital Trauma

1
나는 그것을 허용 할 것이다.이 경우에는 수학 연산자가 아니다.
WallyWest

1
-3은 빼기가 아닌 부정의 역할을합니다 ... @Milo, 부정과 수학 연산자와는 별도로이 연산자를 사용할 수있는 다른 방법을 고려해야합니다. 예를 들어 +는 JavaScript에서 연결 자로 사용할 수 있습니다. .. 제안 할 수 있습니까? 변경 '다음 연산자를 사용하지 않음 : + - * / % ""자신의 수학적 형태로 다음과 같은 연산자를 사용하지 않음 : + - * / % "
WallyWest

2
@WallyWest 악마의 옹호자를 연기하기 위해, 여기서의 부정은 여전히 ​​수학 연산자입니다. 아마도 "단일 비 수학적 형태로 다음 연산자를 사용하지 마십시오 : +-* / %" ;-)
Digital Trauma

4

파이썬 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 (보너스 제외)

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

노트

  • + 문자열 연결에 사용됩니다
  • * 문자열 복사본을 만드는 데 사용

언 골프

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

노트

질문의 정신에서, 나는 다음 해결책이 질문의 모든 규칙을 따르지만 남용이라고 생각합니다

파이썬 41

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

드디어

수학 기호가 금지되어 있다고 주장하면 90 문자 솔루션입니다.

Python 90 (수학적 기호 없음)

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

1
으로 이미 말했다, *그리고 +(당신이 그들을 사용 무엇이든) 키를 끊어집니다.
Thomas Baruchel

2
@ ברוכאל : No use of the following in mathematical form operators: + - * / % (Thanks Wally West). 다시 말해, 질문은 다시 표현되어야합니다. 그리고 나는 그것들을 수학적 형태로 사용하지 않았습니다
Abhijit

그러나 APL 솔루션의 downvote는 그다지 다른 솔루션이 downvoted되지 않았기 때문에 공평하지 않았습니다.
Thomas Baruchel

귀하의 답변은 적은 금액의 돈에 문제가있을 것입니다 (예 :) 0.05.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

`input`대신 (백틱 포함)을 사용할 수 있습니다 raw_input.
nyuszika7 시간

4

APL (9 자, 7 자 새 코드, 13 자 고정)

주어진 금액의 20 %를 계산합니다.

{⍟⍵*⍨*.2} 32

APL *에서 지수 연산자입니다.

온라인으로 사용해보십시오 .

그러나 왜 그 기능을 사용합니까? 이 새로운 버전을보십시오 :

⍟(*.2)* 32

온라인으로 사용해보십시오 .

downvoting하기 전에 키로 *금지되지 않으며 여기에 곱셈을 의미하지는 않습니다.

자, 다음은 소수점 이하 2 자리 (Dyalog APL)입니다.

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

2
지수화는 여전히 수학적 연산이며 *도전 규칙에 따라 수학적 형태로 허용되지 않습니다.
Tony Ellis

지수는 여기에서 금지되지 않으며 다른 솔루션은 실제로 그것을 사용하지만, *수학적 의미가 아니라 열쇠로 금지되는 사실에 대해서는 귀하가 옳습니다 .
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
@ברוכאל It's my understanding that usage of an asterisk in any way that pertains to a mathematical meaning is forbidden, that includes exponentiation. Every other answer thus-far that uses exponents is in a language that uses the caret (^) for such an operator, or a function call is used. There is no specification by the OP that * is disallowed only if it's used in the context of multiplication. I suspect it would be helpful if OP were to rule on this, to settle which one of us is misinterpreting the rules of the challenge and to clear up the confusion.
Tony Ellis

1
Perhaps × and ÷ are allowed, those are not listed.
marinus

4

R, 30 27 36 34

소수점 이하 2 자리로 반올림하여 업데이트

plannapus 덕분에 2 자 절약

0에서 x까지의 벡터를 만들고 두 번째 요소를 가져옵니다.

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

예:

> a(20.36)
[1] 4.07

추가 설명 :

seq(0,x,len=6)

값이 같은 간격으로 0에서 입력 값 x까지의 길이 6의 벡터를 만듭니다.

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

첫 번째 값은 0 %, 두 번째 20 %, 세 번째 40 % 등입니다.


무엇을 기다립니다 ? 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.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.