Skip to content

[Hacker Rank] Interview Preparation Kit: Greedy Algorithms: Greedy Fl… #350

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# [Greedy Algorithms: Greedy Florist](https://www.hackerrank.com/challenges/greedy-florist)

- Difficulty: `#medium`
- Category: `#ProblemSolvingBasic` `#greedyalgorithms`

## About the problem statement

At first it seems a bit confusing. Due the problem statement tends to
make us believe that the most convenient thing is to start with the highest
numbers, but the examples doesn't not present a logical descending order.

## Way of thinking

After rereading the problem several times it can be determined that:

- It does not matter who the buyers are, nor in what order they buy,
nor how much each one buys.
The important thing is how many people are organized
into a group to minimize the purchase price.

- If the number of people in the group is greater than or equal to
the number of different flowers, then the price is the lowest possible,
because they can all be purchased "in a single pass",
making each person in the group (or less) buy 1 unit.

- The price of flowers does matter, therefore it is more convenient to buy
the most expensive ones first.
Each "round" of purchasing makes the flowers more expensive,
therefore it is better to buy the cheapest ones in the last "round."

## Deductions

- It seems convenient to sort the flower price list entry in descending order
(or in ascending order, traversing the new sorted list in reverse).

- The number of passes depends on how many "groups" of "k - people"
fit in the list of flowers, that is:
$ \textbf{\#(c) / k}$ (integer division)

- At first I assumed that the order in which the traversal is done in
the examples was a suggestion of the criteria in which the list of flowers
should be traversed to reach the solution.

Finally, realizing that the price calculation in descending order
(and "the round" in which the purchase is made)
and the example were equivalent, made me consider the idea that the order of
the examples might just be a distractor,
introduced on purpose to make deducing the solution a little more difficult.
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# [Greedy Algorithms: Greedy Florist](https://www.hackerrank.com/challenges/greedy-florist)

- Difficulty: `#medium`
- Category: `#ProblemSolvingBasic` `#greedyalgorithms`

A group of friends want to buy a bouquet of flowers.
The florist wants to maximize his number of new customers and the money he makes.
To do this, he decides he'll multiply the price of each flower by the number
of that customer's previously purchased flowers plus `1`.
The first flower will be original price, $(0 + 1) \times \text{original price}$,
the next will be $(1 + 1) \times \text{original price}$ and so on.

Given the size of the group of friends, the number of flowers they want
to purchase and the original prices of the flowers, determine the minimum cost
to purchase all of the flowers.
The number of flowers they want equals the length of the array.

## Example

`c = [1, 2, 3, 4]`
`k = 3`

The length of `c = 4`, so they want to buy `4` flowers total.
Each will buy one of the flowers priced `[2, 3, 4]` at the original price.
Having each purchased `x = 1` flower,
the first flower in the list, `c[0]`, will now cost
$ (
\textsf{\textbf{current purchase}}
+
\textsf{\textbf{previous purchase}}
) \times
\textsf{\textbf{c[0]}} $.
The total cost is `2 + 3 + 4 + 2 = 11`.

## Function Description

Complete the getMinimumCost function in the editor below.

getMinimumCost has the following parameter(s):

- `int c[n]`: the original price of each flower
- `int k`: the number of friends

## Returns

- `int`: the minimum cost to purchase all flowers

## Input Format

The first line contains two space-separated integers `n` and `k`,
the number of flowers and the number of friends.
The second line contains `n` space-separated positive integers `c[i]`,
the original price of each flower.

## Constraints

- $ 1 \leq n, k \leq 100 $
- $ 1 \leq c[i] \leq 10^5 $
- $ answer < 2^31 $
- $ 0 \leq i \leq n $

## Sample Input 0

```text
3 3
2 5 6
```

## Sample Output 0

```text
13
```

## Explanation 0

There are `n = 3` flowers with costs `c = [2, 5, ,6]` and `k = 3` people in the group.
If each person buys one flower,
the total cost of prices paid is `2 + 5 + 6 = 13` dollars.
Thus, we print `13` as our answer.

## Sample Input 1

```text
3 2
2 5 6
```

## Sample Output 1

```text
15
```

## Explanation 1

There are `n = 3` flowers with costs `c = [2, 5, 6]` and `k = 2`
people in the group.
We can minimize the total purchase cost like so:

1. The first person purchases 2 flowers in order of decreasing price;
this means they buy the more expensive flower ($ c_1 = 5 $) first at price
$
p_1 = (0 + 1) \times 5 = 5
$
dollars and the less expensive flower ($ c_0 = 5 $) second at price
$
p_0 = (1 + 1) \times 2 = 4
$
dollars.
2. The second person buys the most expensive flower at price
$
p_2 = (0 + 1) \times 6 = 6
$
dollars.

We then print the sum of these purchases, which is `5 + 4 + 6 = 15`, as our answer.

## Sample Input 2

```text
5 3
1 3 5 7 9
```

## Sample Output 2

```text
29
```

## Explanation 2

The friends buy flowers for `9, 7`, and `3, 5`, and `1` for a cost of
`9 + 7 + 3 * (1 + 1) + 5 + 1 * (1 + 1) = 29`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @link Problem definition [[docs/hackerrank/interview_preparation_kit/greedy_algorithms/greedy-florist.md]]
* @see Solution notes [[docs/hackerrank/interview_preparation_kit/greedy_algorithms/greedy-florist-solution-notes.md]]
*/

package hackerrank

import (
"slices"
)

func getMinimumCost(k int32, c []int32) int32 {
// Sort the array
flowers := make([]int32, len(c))
copy(flowers, c)
slices.Sort(flowers)
slices.Reverse(flowers)

total := int32(0)
k_customers := int(k)

for i, flower_cost := range flowers {
var position = int32(i / k_customers)
total += int32(position+1) * int32(flower_cost)
}

return total
}

func GetMinimumCost(k int32, c []int32) int32 {
return getMinimumCost(k, c)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
{
"title": "Sample Test case 0",
"k": 3,
"c": [2, 5, 6],
"expected": 13
},
{
"title": "Sample Test case 1",
"k": 2,
"c": [2, 5, 6],
"expected": 15
},
{
"title": "Sample Test case 2",
"k": 3,
"c": [1, 3, 5, 7, 9],
"expected": 29
},
{
"title": "Test case 1",
"k": 3,
"c": [390225, 426456, 688267, 800389, 990107, 439248, 240638, 15991, 874479, 568754, 729927, 980985, 132244, 488186, 5037, 721765, 251885, 28458, 23710, 281490, 30935, 897665, 768945, 337228, 533277, 959855, 927447, 941485, 24242, 684459, 312855, 716170, 512600, 608266, 779912, 950103, 211756, 665028, 642996, 262173, 789020, 932421, 390745, 433434, 350262, 463568, 668809, 305781, 815771, 550800],
"expected": 163578911
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package hackerrank

import (
"fmt"
"os"
"testing"

"github.com/stretchr/testify/assert"
"gon.cl/algorithms/utils"
)

type GreedyFloristTestCase struct {
C []int32 `json:"c"`
K int32 `json:"k"`
Expected int32 `json:"expected"`
}

var GreedyFloristTestCases []GreedyFloristTestCase

// You can use testing.T, if you want to test the code without benchmarking
func GreedyFloristSetupSuite(t testing.TB) {
wd, _ := os.Getwd()
filepath := wd + "/greedy_florist.testcases.json"
t.Log("Setup test cases from JSON: ", filepath)

var _, err = utils.LoadJSON(filepath, &GreedyFloristTestCases)
if err != nil {
t.Log(err)
}
}

func TestGreedyFlorist(t *testing.T) {

GreedyFloristSetupSuite(t)

for _, tt := range GreedyFloristTestCases {
testname := fmt.Sprintf("getMinimumCost(%v, %v) => %v \n", tt.K, tt.C, tt.Expected)
t.Run(testname, func(t *testing.T) {
ans := GetMinimumCost(tt.K, tt.C)
assert.Equal(t, tt.Expected, ans)
})
}
}