DEV Community

Discussion on: Daily Challenge #74 - Free Pizza

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.