DEV Community

dev.to staff
dev.to staff

Posted on

Daily Challenge #74 - Free Pizza

In an attempt to boost sales, the manager of the pizzeria you work at has devised a new pizza rewards system. Although, he isn't exactly sure what he wants the variables to be. The rewards system may change in the future. Your manager wants you to implement a function that, given a dictionary of customers, a minimum number of orders, and a minimum order value, returns a set of the customers who are eligible for a reward.

Customers in the dictionary are represented as:
{ 'customerName' : [list_of_order_values_as_integers] }

Test 1:
Make at least 5 orders of at least 20$ each and get a free pizza!

min_orders = 5
min_price = 20
customers = {
'John Doe' : [22, 30, 11, 17, 15, 52, 27, 12], 
'Jane Doe' : [5, 17, 30, 33, 40, 22, 26, 10, 11, 45]
}

Test 2:
Make at least 2 orders of at least 50$ each and get a free pizza!

min_orders = 2
min_price = 50
customers = {
'Joey Bonzo' : [22, 67, 53, 29],
'Jennifer Bonzo' : [51, 19]
}

Test 3:
Make at least 3 orders of at least 15$ each and get a free pizza!

min_orders = 3
min_price = 15
customers = {
'Natsumi Sakamoto' : [15, 15, 14],
'Gorou Hironaka' : [15, 15, 15],
'Shinju Tanabe' : [120, 240]
}

This challenge comes from kingcobra 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!

Top comments (9)

Collapse
 
aminnairi profile image
Amin • Edited

Elm

module FreePizza exposing (Customer, freePizza)


type alias Customer =
    { name : String
    , purchases : List Int
    }


isEligible : Int -> Int -> Customer -> Bool
isEligible minimumOrders minimumPrice =
    .purchases
        >> List.filter ((<=) minimumPrice)
        >> List.length
        >> (<=) minimumOrders


freePizza : Int -> Int -> List Customer -> List Customer
freePizza minimumOrders minimumPrice =
    List.filter <| isEligible minimumOrders minimumPrice

Explainations

module FreePizza exposing (Customer, freePizza)

This will define anything that we choose to export to the outside world importing our module. In this case, we only want to expose our Customer type alias & freePizza function for our tests (see below).

type alias Customer =
    { name : String
    , purchases : List Int
    }

This will define a customer in our application. Note that I choosed to use a name field for the name of the customer and a purchases field for the total record of the customer's purchases.

isEligible : Int -> Int -> Customer -> Bool
isEligible minimumOrders minimumPrice =
    .purchases
        >> List.filter ((<=) minimumPrice)
        >> List.length
        >> (<=) minimumOrders

This will define the inner logic of the challenge. Basically what it does is:

  1. Grab the purchases out of the current iterated object (customer). Almost anything in Elm is a function, so is .purchases which is a function that accepts a customer and returns a list of integers (the purchases). .purchases : Customer -> List Int. It is equivalent to this in JavaScript: const { purchases } = customer;.
  2. Filter out all the customer's purchases that are not above or equal to the minimum order's price defined by our free pizza's policy. The ((<=) minimumPrice) part is equivalent to (\purchase -> purchase >= minimumPrice)
  3. Calculate the length of the filtered list.
  4. Check whether the length of the list is at least equal or above the minimum orders, which means that it will return true when the customer has made enough purchases.
freePizza : Int -> Int -> List Customer -> List Customer
freePizza minimumOrders minimumPrice =
    List.filter <| isEligible minimumOrders minimumPrice

This will filter out all the customer that are non-eligible to our current free pizza's policy.

Tests

module FreePizzaTest exposing (suite)

import Expect exposing (equal)
import FreePizza exposing (Customer, freePizza)
import Test exposing (Test, describe, test)


suite : Test
suite =
    describe "Free Pizza"
        [ test "it should return a set of customers who are eligible for a reward #1" <|
            \_ ->
                let
                    minimumOrders : Int
                    minimumOrders =
                        5

                    minimumPrice : Int
                    minimumPrice =
                        20

                    customers : List Customer
                    customers =
                        [ { name = "John Doe"
                          , purchases = [ 22, 30, 11, 17, 15, 52, 27, 12 ]
                          }
                        , { name = "Jane Doe"
                          , purchases = [ 5, 17, 30, 33, 40, 22, 26, 10, 11, 45 ]
                          }
                        ]

                    expectations : List Customer
                    expectations =
                        [ { name = "Jane Doe"
                          , purchases = [ 5, 17, 30, 33, 40, 22, 26, 10, 11, 45 ]
                          }
                        ]
                in
                equal expectations <| freePizza minimumOrders minimumPrice customers
        , test "it should return a set of customers who are eligible for a reward #2" <|
            \_ ->
                let
                    minimumOrders : Int
                    minimumOrders =
                        2

                    minimumPrice : Int
                    minimumPrice =
                        50

                    customers : List Customer
                    customers =
                        [ { name = "Joey Bonzo"
                          , purchases = [ 22, 67, 53, 29 ]
                          }
                        , { name = "Jennifer Bonzo"
                          , purchases = [ 51, 19 ]
                          }
                        ]

                    expectations : List Customer
                    expectations =
                        [ { name = "Joey Bonzo"
                          , purchases = [ 22, 67, 53, 29 ]
                          }
                        ]
                in
                equal expectations <| freePizza minimumOrders minimumPrice customers
        , test "it should return a set of customers who are eligible for a reward #3" <|
            \_ ->
                let
                    minimumOrders : Int
                    minimumOrders =
                        3

                    minimumPrice : Int
                    minimumPrice =
                        15

                    customers : List Customer
                    customers =
                        [ { name = "Natsumi Sakamoto"
                          , purchases = [ 15, 15, 14 ]
                          }
                        , { name = "Gorou Hironaka"
                          , purchases = [ 15, 15, 15 ]
                          }
                        , { name = "Shinju Tanabe"
                          , purchases = [ 120, 240 ]
                          }
                        ]

                    expectations : List Customer
                    expectations =
                        [ { name = "Gorou Hironaka"
                          , purchases = [ 15, 15, 15 ]
                          }
                        ]
                in
                equal expectations <| freePizza minimumOrders minimumPrice customers
        ]

Playground

Test it online here.

Collapse
 
andre000 profile image
André Adriano

Javascript

function promo(order, price, customers) {
    return Object.keys(customers).filter(c => customers[c].filter(p => p >= price).length >= order);
}

// Test 1
promo(min_orders, min_price, customers)
// ["Jane Doe"]

// Test 2
promo(min_orders, min_price, customers)
// ["Joey Bonzo"]

// Test 3
promo(min_orders, min_price, customers)
// ["Gorou Hironaka"]
Collapse
 
brightone profile image
Oleksii Filonenko

Elixir:

defmodule Day74 do
  def eligible(customers, min_orders, min_price) do
    for customer = {_, orders} <- customers,
        Enum.count(orders, &(&1 >= min_price)) >= min_orders,
        into: %{},
        do: customer
  end
end

Tests:

defmodule Day74Test do
  use ExUnit.Case

  test "5 of $20" do
    customers = %{
      "John Doe" => [22, 30, 11, 17, 15, 52, 27, 12],
      "Jane Doe" => [5, 17, 30, 33, 40, 22, 26, 10, 11, 45]
    }

    assert %{"Jane Doe" => _} = Day74.eligible(customers, 5, 20)
  end

  test "2 of $50" do
    customers = %{
      "Joey Bonzo" => [22, 67, 53, 29],
      "Jennifer Bonzo" => [51, 19]
    }

    assert %{"Joey Bonzo" => _} = Day74.eligible(customers, 2, 50)
  end

  test "3 of $15" do
    customers = %{
      "Natsumi Sakamoto" => [15, 15, 14],
      "Gorou Hironaka" => [15, 15, 15],
      "Shinju Tanabe" => [120, 240]
    }

    assert %{"Gorou Hironaka" => _} = Day74.eligible(customers, 3, 15)
  end
end
Collapse
 
willsmart profile image
willsmart

Here's one in TypeScript

My preferred way of passing bags of arguments to functions in JS is by destructuring an object, which gets around the whole lets-just-remember-the-second-argument-was-minOrders thing.

The hacky embedded test harness is just there to make this portable.


hmm, I think I found a bug in the codepen plugin, where the template string at the bottom is being styled like it never got closed.
Will find the repo and pop in a bug report.

Collapse
 
kvharish profile image
K.V.Harish

My solution in js

const rewardsSystem = (minOrders = 0, minPrice = 0, customers = {}) => Object.keys(customers).filter((customer) => customers[customer].filter((value) => value >= minPrice).length >= minOrders);
Collapse
 
lordapple profile image
LordApple

c++, hope it's correct.

#include <iostream>
#include <unordered_set>
#include <utility>
#include <vector>

struct Customer{
    Customer(std::string t_name, std::vector<int> t_orders) : name(std::move(t_name)), orders(std::move(t_orders)){
    };

    std::string name;
    std::vector<int> orders;
};

auto freePizza(const std::vector<Customer>& customers, const int& minPrice, const int& minOrders){
    std::vector<Customer> returnValue{};

    for(const auto& customer : customers){
        if(customer.orders.size() < minOrders)
            continue;

        int count = 0;

        for(const auto& item : customer.orders){
            if(item >= minPrice)
                ++count;
        }

        if(count >= minOrders)
            returnValue.push_back(customer);
    }
    return returnValue;
}
Collapse
 
teaglebuilt profile image
dillan teagle

Python solution

def rewarder(customers, orders, price):
    eligible = set()
    for key, value in customers.items():
        number_of_occurences = sum(num > price for num in value)
        if number_of_occurences >= orders:
            eligible.add(key)

    return eligible


x = rewarder(customers, min_orders, min_price)
print(x)
Collapse
 
mbaas2 profile image
Michael Baas

APL - Solution 1 (using Dyalog APL)

I'm passing the argument in a suitable array-format for convenience and brevity:

promo←{(⊂'')~⍨(⊂⍵){(⍺[1]≤+/⍺[2]≤2⊃⍵)/1⊃⍵}¨3⊃⍵}

Output:

      promo 5 20(('John Doe'(22 30 11 17 15 15 52 27 12))('Jane Doe'(5 17 30 33 40 22 26 10 11 45)))
┌────────┐
│Jane Doe│
└────────┘
      promo 2 50 (('Joey Bonzo'(22 67 53 29))('Jennifer Bonzo'(51 19)))
┌──────────┐
│Joey Bonzo│
└──────────┘
      promo 3 15 (('Natsumi Sakamoto'(15 15 14))('Gorou Hironaka'(15 15 15))('Shinju Tanabe'(120 40)))
┌──────────────┐
│Gorou Hironaka│
└──────────────┘

APL - Solution 2

Since the task was shown with JSON-Data, I want to also show how to tackle this with JSON-Data in APL.

promo2←{(⊂'')~⍨(⊂⍵.(min_orders min_price)){(⍺[1]≤+/⍺[2]≤⍵.hist)/⍵.id}¨⍵.customers}

Testing

      Test1←⎕JSON'{"min_orders":5,"min_price":20,"customers":[{"id":"John Doe","hist":[22, 30, 11 ,17 ,15 ,52, 27 ,12]},{"id":"Jane Doe","hist":[5 ,17 ,30 ,33, 40, 22, 26, 10, 11 ,45]}]}'
      promo2 Test1
┌────────┐
│Jane Doe│
└────────┘

      Test2←⎕JSON'{"min_orders":2,"min_price":50,"customers":[{"id":"Joey Bonzo","hist":[22,67,53,29]},{"id":"Jennifer Bonzo","hist": [51,19]}]}'
      promo2 Test2
┌──────────┐
│Joey Bonzo│
└──────────┘

      Test3←⎕JSON'{"min_orders":3,"min_price":15,"customers":[{"id":"Natsumi Sakamoto","hist":[15,15,14]},{"id":"Gorou Hironaka","hist": [15,15,15]},{"id":"Shinju Tanabe","hist":[120,40]}]}'
      promo2 Test3
┌──────────────┐
│Gorou Hironaka│
└──────────────┘

Feel free to experiment and Try it online! ;)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.