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


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.