From 9a19785e04c812c265cbc6f739174883e1c51c6f Mon Sep 17 00:00:00 2001 From: Gonzalo Diaz Date: Mon, 8 Jul 2024 01:26:41 -0400 Subject: [PATCH] =?UTF-8?q?[Hacker=20Rank]=20Interview=20Preparation=20Kit?= =?UTF-8?q?:=20Greedy=20Algorithms:=20Luck=20Balance.=20Solved=20=E2=9C=85?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../greedy_algorithms/luck-balance.md | 97 +++++++++++++++++++ .../greedy_algorithms/luck-balance.test.ts | 63 ++++++++++++ .../greedy_algorithms/luck-balance.ts | 83 ++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 docs/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.md create mode 100644 src/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.test.ts create mode 100644 src/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.ts diff --git a/docs/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.md b/docs/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.md new file mode 100644 index 00000000..5794a5a6 --- /dev/null +++ b/docs/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.md @@ -0,0 +1,97 @@ +# [Greedy Algorithms: Luck Balance](https://www.hackerrank.com/challenges/luck-balance) + +- Difficulty: `#easy` +- Category: `#ProblemSolvingBasic` + +Lena is preparing for an important coding competition that is preceded +by a number of sequential preliminary contests. +Initially, her luck balance is 0. +She believes in "saving luck", and wants to check her theory. +Each contest is described by two integers, `L[i]` and `T[i]`: + +- `L[i]` is the amount of luck associated with a contest. +If Lena wins the contest, her luck balance will decrease by `L[i]`; +if she loses it, her luck balance will increase by `L[i]`. + +- `T[i]` denotes the contest's importance rating. +It's equal to `1` if the contest is important, and it's equal to `0` if it's unimportant. + +If Lena loses no more than `k` important contests, what is the maximum amount +of luck she can have after competing in all the preliminary contests? +This value may be negative. + +## Example + +```text +Contest L[i] T[i] +1 5 1 +2 1 1 +3 4 0 +``` + +If Lena loses all of the contests, her will be `5 + 1 +4 = 10`. +Since she is allowed to lose important contests, +and there are only `2` important contests, +she can lose all three contests to maximize her luck at `10`. + +If `k = 1`, she has to win at least of the important contests. +She would choose to win the lowest value important contest worth `1`. +Her final luck will be `5 + 4 - 1 = 8`. + +## Function Description + +Complete the luckBalance function in the editor below. + +luckBalance has the following parameter(s): + +- `int k`: the number of important contests Lena can lose +- `int contests[n][2]`: a 2D array of integers where each `contests[i]` +contains two integers that represent the luck balance and importance of the contest + +## Returns + +- `int`: the maximum luck balance achievable + +## Input Format + +The first line contains two space-separated integers `n` and `k`, +the number of preliminary contests and the maximum number +of important contests Lena can lose. + +Each of the next lines contains two space-separated integers, +`L[i]` and `T[i]`, the contest's luck balance and its importance rating. + +## Constraints + +- $ 1 \leq n \leq 100 $ +- $ 0 \leq k \leq N $ +- $ 1 \leq L[i] \leq 10^4 $ +- $ T[i] \isin \{0,1\} $ + +## Sample Input + +```text +STDIN Function +----- -------- +6 3 n = 6, k = 3 +5 1 contests = [[5, 1], [2, 1], [1, 1], [8, 1], [10, 0], [5, 0]] +2 1 +1 1 +8 1 +10 0 +5 0 +``` + +## Sample Output + +```text +29 +``` + +## Explanation + +There are `n = 6` contests. Of these contests, `4` are important +and she cannot lose more than of them. +Lena maximizes her luck if she wins the $ 3^{rd} $ important contest +(where `L[i] = 1`) and loses all of the other five contests for a total +luck balance of `5 + 2 + 8 + 10 + 5 - 1 = 29`. diff --git a/src/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.test.ts b/src/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.test.ts new file mode 100644 index 00000000..5db8903d --- /dev/null +++ b/src/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.test.ts @@ -0,0 +1,63 @@ +import { describe, expect, it } from '@jest/globals'; +import { logger as console } from '../../../logger'; + +import { luckBalance } from './luck-balance'; + +const TEST_CASES = [ + { + title: 'Sample Test case 0', + k: 3, + contests: [ + [5, 1], + [2, 1], + [1, 1], + [8, 1], + [10, 0], + [5, 0] + ], + expected: 29 + }, + { + title: 'Sample Test case 1', + k: 5, + contests: [ + [13, 1], + [10, 1], + [9, 1], + [8, 1], + [13, 1], + [12, 1], + [18, 1], + [13, 1] + ], + expected: 42 + }, + { + title: 'Sample Test case 1', + k: 2, + contests: [ + [5, 1], + [4, 0], + [6, 1], + [2, 1], + [8, 0] + ], + expected: 21 + } +]; + +describe('luck-balance', () => { + it('luckBalance test cases', () => { + expect.assertions(3); + + TEST_CASES.forEach((test) => { + const answer = luckBalance(test.k, test.contests); + + console.debug( + `luckBalance(${test.k}, ${test.contests}) solution found: ${answer}` + ); + + expect(answer).toStrictEqual(test.expected); + }); + }); +}); diff --git a/src/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.ts b/src/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.ts new file mode 100644 index 00000000..264e575f --- /dev/null +++ b/src/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.ts @@ -0,0 +1,83 @@ +/** + * @link Problem definition [[docs/hackerrank/interview_preparation_kit/greedy_algorithms/luck-balance.md]] + */ + +class Contest { + luck: number; + important: number; + + constructor(luck: number, important: number) { + this.luck = luck; + this.important = important; + } +} + +type SortOrder = 'asc' | 'desc'; + +interface SortBy { + property: keyof T; + order?: SortOrder; +} + +function dynamicSort(array: T[], sortBy: SortBy[]): T[] { + const initialValue = 0; + return array.sort((a, b) => + sortBy.reduce((_, current) => { + const { property, order = 'asc' } = current; + + let comparison = 0; + if (a[property] > b[property]) { + comparison = 1; + } else if (a[property] < b[property]) { + comparison = -1; + } + + if (order === 'desc') { + comparison *= -1; + } + + return comparison; + }, initialValue) + ); +} + +export function luckBalance(k: number, contests: number[][]): number { + let importantContests: Contest[] = []; + const nonimportantContests: Contest[] = []; + + contests.forEach((contest) => { + const [luck, important] = [...contest]; + const theContest = new Contest(luck, important); + + if (important === 1) { + importantContests.push(theContest); + } else { + nonimportantContests.push(theContest); + } + }); + + importantContests = dynamicSort(importantContests, [ + { property: 'important', order: 'desc' }, + { property: 'luck', order: 'desc' } + ]); + + let total = 0; + const size = importantContests.length; + const cut = Math.min(k, size); + + for (let i = 0; i < cut; i++) { + total += importantContests[i].luck; + } + + for (let i = cut; i < size; i++) { + total -= importantContests[i].luck; + } + + nonimportantContests.forEach((contest) => { + total += contest.luck; + }); + + return total; +} + +export default { luckBalance };