Рассчитать чаевые


16

Вы и друг идете в бар. Бармен относится к вам хорошо, поэтому вы решаете дать ему чаевые. Таким образом, вы достаете свой надежный карманный компьютер и пишете быструю программу для расчета чаевых, поскольку в ней нет встроенного калькулятора. Но ждать! Ваши ключи оператора сломаны! Ваша задача - рассчитать 20% чаевых для любой заданной суммы ввода. Входные данные теста будут иметь вид xx.xx, например, 20,96. Вот правила:

  • Не использовать следующие операторы в математической форме: + - * / %(спасибо Wally West)
  • Не использовать встроенные функции процента или API
  • Нет доступа к сети
  • Не использовать evalили аналогичные
  • Нет калькулятора Windows (да, люди ответили ранее)
  • Нет встроенных функций подсказки (не то, чтобы у любого языка была такая)

Выходные данные должны быть округлены до двух десятичных знаков.

Оценка основана на длине в байтах.

-20%, если ваша программа может принять любую сумму чаевых. Вход для суммы будет дан в виде хх например 35, а не 0,35


5
@mniip: чаевые - это странная дополнительная сумма денег, которую вы должны заплатить в ресторане, которая не является частью официальной цены. Я не знаю, делают ли они это в России.
user2357112 поддерживает Monica

5
О, это новое поколение ... Я бы предпочел использовать бумагу и ручку, если не могу мысленно разделить число на 5.
VisioN

4
@VisioN Примечание: деление на пять эквивалентно делению на 10, а затем умножению на 2, и оба должны быть очень простыми умственными операциями.
user12205

1
Может кто-то уточнить правила: разрешено ли использование запрещенных операций, если вы не используете эти операторы? Разрешено ли умножение, если вы не используете *?
Ypnypn

2
@TheDoctor действительно дубликат, хотя? Потому что это не добавление.
Мило

Ответы:


18

Javascript 81

РЕДАКТИРОВАТЬ : Результат теперь реальное округление, а не усечены.

Не используйте здесь ЛЮБУЮ математику, только манипуляции со строками и побитовые операторы.
Все +символы являются конкатенацией строк или преобразованием строки в число с плавающей точкой .
Работает для любого входа и выхода xx.xx в формате (x) x.xx

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

Трюк объяснил: 20% делится на 10 и умножается на 2.

  • Сделайте деление на 10, переместив точку влево (манипуляции со строками)
  • Умножьте каждую часть на 2, сдвинув биты влево (побитовая операция)

Когда ввод равен 99.99, он возвращается 19.998, поэтому он не «округляется до двух десятичных разрядов» согласно ОП.
Geobits

2
Хм, это долгое решение, но оно имеет 12 голосов. Что происходит с голосованием Code-Golf?
Джастин

@Quincunx Да, вы правы, это не популярный конкурс!
Мукул Кумар

Поскольку это код-гольф, я, вероятно, не выиграю, но это не значит, что людям не понравится мое решение ... Часто победители код-гольфа не те, у кого больше голосов.
Майкл М.

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, абсолютно! Спасибо за указание на это. Исправлено сейчас :)
Майкл М.

6

J (9 знаков)

Краткий ответ на J:

^.(^.2)^~ 32

1
... и я не говорю J. Что это говорит?
двоюродный брат Кокаин

Там написано: вычислить 32, возведенное в power log (2); как правило, показатель степени справа, ^но здесь ~указывает, что порядок должен быть обратным; (^.2)является log (.2), ​​и инициал, ^.который выполняется последним, является логарифмом всего, что вычислялось ранее: таким образом, log (32 ^ log (.2))
Томас Барухель

4

Чистая Баш, 50 43 символов

Я уверен, что это будет лучше, но вот начало:

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

Согласно комментариям:

  • /здесь не оператор деления, это часть расширения параметра подстановки шаблона
  • % здесь не оператор по модулю, это часть расширения параметра
  • - здесь не оператор вычитания, это отрицание, которое было разрешено согласно комментариям

Выход:

$ ./20pct.sh 0,96
0,19
$ ./20pct.sh 20,96
4,19
$ ./20pct.sh 1020,96
204,19
$ 

Я думаю, что я вижу косую черту там.
Мило

@Milo, который /является частью расширения параметра bash, а не оператором деления. Разрешено или нет?
Цифровая травма

1
Я бы позволил, это не математический оператор в этом случае ...
WallyWest

1
-3 действует как отрицание, а не как вычитание ... @Milo, вам нужно учитывать отрицание и другие способы, которыми эти операторы могут использоваться помимо их математических эквивалентов ... например + может использоваться как конкатенатор в JavaScript. .. Могу ли я сделать предложение? Измените «Не использовать следующие операторы: + - * /%» на «Не использовать следующие операторы в их математической форме: + - * /%»
WallyWest

2
@WallyWest Чтобы играть адвоката дьявола, отрицание здесь все еще математический оператор. Возможно «Не использовать следующие операторы в их неунарной математической форме: + - * /%» ;-)
Цифровая травма

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 (без бонуса)

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

Заметка

  • + используется для объединения строк
  • * используется для создания копий строки

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

Заметка

В духе вопроса, я считаю, что следующее решение, хотя следует всем правилам вопроса, является злоупотреблением

Python 41

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

в заключение

Если вы настаиваете на том, что математические символы запрещены, то это 90-символьное решение

Python 90 (без какого-либо математического символа)

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

1
Как уже сказано, *и +сломаны КЛЮЧИ (для чего вы их используете).
Томас Барухель

2
@ ברוכאל: No use of the following in mathematical form operators: + - * / % (Thanks Wally West). Другими словами, вопрос необходимо перефразировать. И я не использовал их в математической форме
Abhijit

Хорошо, но в этом случае отрицательное влияние решения APL было не совсем справедливым, поскольку по этой причине ни одно другое решение не было отклонено.
Томас Барухель

Ваш ответ будет иметь проблемы с незначительной суммой денег, например 0.05.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Вы можете использовать `input`(включая обратные ссылки) вместо raw_input.
nyuszika7h

4

APL (9 символов, новый код из 7 символов, фиксированный из 13 символов)

Вычислить 20% от указанной суммы.

{⍟⍵*⍨*.2} 32

В APL *есть экспоненциальный оператор.

Попробуйте онлайн .

But why use a function for that? See this new version:

⍟(*.2)* 32

Try it online.

Please, before downvoting, the * is not forbidden as a KEY and it doesn't mean multiplication here.

OK, here is the version rounding to 2 decimals (Dyalog APL):

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

2
Возведение в степень по-прежнему остается математической операцией и *запрещено в любой математической форме согласно правилам испытания.
Тони Эллис

Возведение в степень здесь не запрещено, и другие решения фактически используют его, но вы правы в том, что *запрещено как ключ, а не как его математическое значение.
Томас Барухель

@ Тони Х. Пожалуйста, не могли бы вы удалить свое отрицательное голосование, поскольку очевидно, что все комментарии в других решениях, по-видимому, наконец принимают такие КЛЮЧИ, если они не используются для запрещенных математических операций в начальном списке.
Томас Барухель

1
@ ברוכאל Насколько я понимаю, использование звездочки любым способом, имеющим математическое значение, запрещено, включая возведение в степень. Любой другой ответ, который до сих пор использует экспоненты, находится на языке, который использует caret ( ^) для такого оператора, или используется вызов функции. У OP нет спецификации, которая *запрещена, только если она используется в контексте умножения. Я подозреваю, что было бы полезно, если бы ОП решило это, чтобы выяснить, кто из нас неправильно истолковывает правила вызова, и устранить путаницу.
Тони Эллис

1
Возможно ×и ÷разрешено, таковых нет в списке.
Marinus

4

R, 30 27 36 34

Обновлено с округлением до 2 знаков после запятой

Спас 2 персонажа благодаря планнапу

Создает вектор от 0 до x и принимает 2-й элемент.

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

Пример:

> a(20.36)
[1] 4.07

Дальнейшее объяснение:

seq(0,x,len=6)

создает вектор длиной 6 от 0 до входного значения x с равными интервалами между значениями.

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

Первое значение составляет 0%, второе 20%, третье 40% и т. Д.


Чего ждать ? Пожалуйста, дайте более подробную информацию о том, как это работает для тех (как я), которые не знают Р.
Майкл М.

@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» не соответствует спецификации. Я думаю , что вы можете это исправить, изменив выражение патча в : dc -e 5o?p|sed 's/\(.\)\./.\1/'|dc -e 5i?p. С этим и удаляя seds -es, это 42. Но результат все еще не для спецификации (не 2 десятичных знака)
Digital Trauma

@DigitalTrauma. Вы правы. Но это решение было на самом деле скорее доказательством концепции, и меня больше интересовало необычное свойство преобразования базы в dc (а также в bc). Спасибо за ваш комментарий и ваше исправление в sed.
Томас Барухель

2

Python, 88

Это не где-то близко, но это демонстрирует, как нормальное умственное разделение на пять должно быть сделано. Это предполагает, что входные данные должны иметь форму xx.xx

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

Или для ввода любой длины требуется добавление 3 символов.

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

Объяснение: Мы берем входные данные как строку, а затем перемещаем десятичную точку на одно место вперед (деление на 10). Затем мы бросаем его на поплавок и используемldexp функцию для умножения на 2.

Обратите внимание, что в этом ответе +используются операторы конкатенации строк, и %они используются для форматированияprint .

Если вы настаиваете на том, чтобы не использовать ни один из этих символов, вот решение из 159 символов:

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

Уже сказано для многих других ответов, но я действительно не думаю , что +и -разрешается поскольку КЛЮЧИ сломаны (то , что они означают в вашей части кода).
Томас Барухель

@ ברוכאל: См. Мой ответ на ваш комментарий в моем ответе
Abhijit

Использовал свой .split('.')в моем ответе, расколол один символ
user80551

2

dc + sed - 45 * 0,8 = 36

(Вдохновленный ответ по ברוכאל )

  • Обрабатывает любое количество чаевых (целое число или число с плавающей запятой)

Пример выполнения (ввод принят через 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

.0+Идея велика; Я голосовал за ваше решение, вдохновленное моим, но некоторые могут сказать, что вы используете дополнение; может быть какой-то обходной путь? Я пытался, dc -e 9k5o?v2^pно это на 2 символа больше.
Томас Барухель

@ ברוכאל Я не понимал, что + даже в этом контексте может рассматриваться как дополнение.
devnull

@ ברוכאל Я удалю этот. Прошу вас изменить ваш так, чтобы он мог обрабатывать поплавки и претендовать на -20%!
devnull

2

Математика, 19

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

Нет использование математических операторов +, -, *, /, или %. Использует свойства логарифмов для вычисления ответа; когда вы упрощаете выражение, вы получаете.2*Input[]

С бонусом ( 30 * 0,8 = 24 ):

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

Сначала введите процент, а затем сумму.

Когда вы упрощаете выражение, вы получаете Input[]*Input[]*.01.

Спасибо ברוכאל за помощь в сокращении кода.


3
Вы действительно уверены, что это нельзя упростить? Мне Log[E^2]или Log[E^Input[]]можно написать короче. Даже 10^-1можно написать .01(хотя я не использую Mathematica, но я уверен, что это возможно). Все выражение (E^10^-1)^Log[E^2]выглядит как-то так E^.2, не так ли?
Томас Барухель

1

TI-89 Basic - 39 * 0,8 = 31,2

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

Работает, введя два числа, затем используя свойства логарифма для вычисления x * y / 100.

Если я могу предположить ввод от размещения в глобальных переменных xи y, то это намного короче, для оценки 17 * 0,8 = 13,6 :

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

Без бонуса ( 12 ):

ln((e^.2)^x)

Но если его нужно обернуть в функцию, то это работает ( 38 символов, для 30.4 ):

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

Пожалуйста, смотрите мои комментарии к вашему другому решению (в Mathematica); этот код действительно может быть значительно упрощен.
Томас Барухель

Input x,y??? Работает в 83/84.
Timtech

@Timtech не работает в 89, но, может быть, я могу сделать что-то вроде Input{x,y}(есть 83/84 ln?)
Джастин

@Quincunx Да, смотрите мой новый ответ.
Тимтех

žr¹msmžr.n бесстыдный порт этого кода в 05AB1E.
Волшебная Урна Осьминога

1

PHP 107 * .8 = 85,6

не могу действительно бегать за гольф-кодом с PHP, но по крайней мере я могу работать со строками. принимает оба числа в качестве аргументов командной строки.

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

пришлось дважды поменять его, так как я не могу использовать -2 :(


1

Python, 81 80 89 символов

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

объяснение

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]

Технически, это обман, поскольку он усекает до двух десятичных знаков вместо округления, но я могу утверждать, что он округляется (лучше для вас, меньше чаевых).


Я думаю, что вы можете сделать [-3:]вместо[-3:-1]
Джастин

@Quincunx Не могу, -1 означает усечение до двух десятичных знаков.
user80551

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Да, исправил.
user80551

1

JavaScript 251 (принудительное ограничение: нет +, -, *,? Или% любым способом)

Хотя я знаю, что это не победит, я подумал, что постараюсь получить очки брауни за счет очень строгого подхода и даже не думать об использовании операторов с ограничениями в любой форме или форме ... в результате я придумал эта красота ...

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

Я использовал побитовые операции для создания функции Add A , а затем начал цепочку оттуда:

Функция целочисленного деления Dиспользовала серию Negated Addition (вычитание в форме A(x,A(~y,1)над циклом; остальное - манипуляции со строками и конкатенация, чтобы избежать использования+ операторов конкатенации ...

Число должно быть предоставлено в десятичной форме с двумя десятичными разрядами, чтобы это работало ...


Ах, теперь это произойдет ... хотя, если бы мне пришлось придерживаться новых правил, мне пришлось бы расширить это ... 251 байт сейчас ...
WallyWest

1

Perl, 50 60 байт

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

Ввод ожидается в STDIN. Он должен содержать десятичный разделитель с двумя десятичными цифрами. Вывод записывается в STDOUT.

Обновление: шаг $_<<=1удаляет ведущие нули. Поэтому m|\d{3}$|не будет соответствовать для счетов <1. Поэтому $_="00$было добавлено десять байтов , теперь даже0.00 работает.

Примеры:

  • Вход:, 20.96выход:4.19
  • Вход:, 12.34выход:2.47

Безголовая версия:

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

Сначала число читается из STDIN. Затем удаляется десятичная точка, которая умножается на 100. Затем сумма удваивается с помощью оператора сдвига. Затем десятичная точка вставляется заново, а результат печатается и округляется до двух десятичных цифр.

50 байтов, если счет ≥ 1:

Если x.xxбольше или равно 1.00, то 10 байтов могут быть удалены:

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

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳: Спасибо, сейчас исправлено.
Хейко Обердик,

1

JavaScript (ES6) (Regex) 142

Regex великолепен и может делать много вещей. Это может даже сделать математику!

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

Читаемая версия:

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

tip()Функция ожидает строки аргумента, а не номер.

Все экземпляры *, /, +которые не связаны с математическими операциями.

  • + это конкатенация строк во всех случаях, когда она используется.
  • * является частью синтаксиса RegExp
  • / является разделителем литерала RegExp

Ввод должен использоваться в .качестве десятичной точки, и после десятичной точки должно быть 2 цифры.

Фрагмент стека

<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 символа -20% = 25,6 символа

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

Злоупотребляет тем фактом, что показатели становятся умножением в логарифмах.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.