loading...

Daily Challenge #241 - Tip Calculator

thepracticaldev profile image dev.to staff ・1 min read

Complete the function, which calculates how much you need to tip based on the total amount of the bill and the service.

You need to consider the following ratings:

Terrible: tip 0%
Poor: tip 5%
Good: tip 10%
Great: tip 15%
Excellent: tip 20%

The rating is case insensitive (so "great" = "GREAT"). If an unrecognized rating is received, then you need to return:
"Rating not recognized" in JavaScript, Python and Ruby...
...or null in Java
...or -1 in C#

Because you're a nice person, you always round up the tip, regardless of the service.

Examples
calculatetip(30, "poor") => 2
calculatetip(20, "hi")=> "Rating Not Recognized"
calculatetip(107.65, "great") => 17

Tests
calculatetip(78, "good") =>
calculatetip(50, "poor") =>
calculatetip(125, "excellent") =>

Good luck!


This challenge comes from Katbow on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Posted on by:

thepracticaldev profile

dev.to staff

@thepracticaldev

The hardworking team behind dev.to ❀️

Discussion

pic
Editor guide
 
 RATINGS = {
   terrible: 0,
   poor: 5,
   good: 10,
   great: 15,
   excellent: 20
 }.freeze

def calculatetip(bill, service)
  service = service.downcase.to_sym
  service_percentage = RATINGS[service]

  return 'Rating Not Recognized' unless service_percentage 

  tip = (bill.to_f * service_percentage.to_f / 100).ceil

  tip
end

calculatetip(78, "good") => 8
calculatetip(50, "poor") => 3
calculatetip(125, "excellent") => 25

 

Some minor suggestions:

  1. Move ratings out of the method, no need to recreate it.
  2. You can try to retrieve the service and do a nil check instead of checking keys, which seems to be more common in Ruby code in the wild.
  3. Floats are "viral", introducing one into the calculation makes all to_f calls redundant.
RATINGS = {
  terrible: 0,
  poor: 5,
  good: 10,
  great: 15,
  excellent: 20
}.freeze

def calculate_tip(bill, service)
  service = RATINGS[service.downcase.to_sym]
  return 'Rating Not Recognized' unless service

  (bill * service / 100.0).ceil
end
 

Python 3

# Solution
import math
RATINGS = {
    'terrible': .0,
    'poor': 0.05,
    'good': 0.1,
    'great': 0.15,
    'excellent': 0.2
}

tip = lambda p, s:  math.ceil(p * RATINGS[s.lower()]) if s.lower() in RATINGS else 'Rating not recognized'

# Test cases
cases = [
    (30, "poor"),
    (20, "hi"),
    (107.65, "great"),
    (78, "good"),
    (50, "poor"),
    (125, "excellent"),
]

for case in cases:
    print(f'With score "{case[1]}" and amount {case[0]}, tip: {tip(*case)}')

Try it online!

 

Here is the Python solution:

import math

def calculate_tip(amount, rating):
    ratings = {
        'terrible': 0,
        'poor': 0.05,
        'good': 0.1,
        'great': 0.15,
        'excellent': 0.2,
    }

    rating = rating.lower()

    if rating not in ratings:
        return 'Rating not recognised'

    rating_number = ratings[rating]

    return math.ceil(amount * rating_number)
 

Haskell

module Main (main) where

maybeTip :: Float -> String -> Maybe Int
maybeTip price "poor"       = Just $ ceiling $ price * 0.05
maybeTip price "good"       = Just $ ceiling $ price * 0.1
maybeTip price "great"      = Just $ ceiling $ price * 0.15
maybeTip price "excellent"  = Just $ ceiling $ price * 0.2
maybeTip _ _                = Nothing

main :: IO ()
main = do
    print $ maybeTip 30 "poor"          -- Just 2
    print $ maybeTip 20 "hi"            -- Nothing
    print $ maybeTip 107.65 "great"     -- Just 17
    print $ maybeTip 78 "good"          -- Just 8
    print $ maybeTip 50 "poor"          -- Just 3
    print $ maybeTip 125 "excellent"    -- Just 25
 

Implementation in Frink

// Needs to be in a class as no concept of 'global' variables
class tipCalculator
{
  class var rates = new dict[[["terrible", 0 percent],
                              ["poor", 5 percent],
                              ["good", 10 percent],
                              ["great", 15 percent],
                              ["excellent", 20 percent]]]

  class calc[amount, rating] :=
  {
    r = lc[rating]
    if not rates.containsKey[r]
      return -1
    return ceil[amount * rates@r]
  }
}


println[tipCalculator.calc[30,"poor"]]          // 2
println[tipCalculator.calc[20, "hi"]]           // -1
println[tipCalculator.calc[107.65, "great"]]    // 17

println[tipCalculator.calc[78, "good"]]         // 8
println[tipCalculator.calc[50, "poor"]]         // 3
println[tipCalculator.calc[125, "excellent"]]   // 25