Skip to content

Instantly share code, notes, and snippets.

@jenyayel
Last active August 3, 2021 07:47
Show Gist options
  • Save jenyayel/8492ad460bbae57e244fa299b4bcd0c9 to your computer and use it in GitHub Desktop.
Save jenyayel/8492ad460bbae57e244fa299b4bcd0c9 to your computer and use it in GitHub Desktop.
Coding challenge
/**
* Calculates the balance in a specific category within the specified time period.
*/
const getBalanceByCategoryInPeriod = (
transactions,
categories,
start,
end
) => {
// Implementation notes:
// The complexitiy is O(n), where `n` is amount of transactions
// We make single traversal where for each transaction we check
// that it falls into date range, belongs to relevant category and
// perform addition of the transaction to the total of category.
// normilize all dates to epoch time, so we can compare
const startEpoch = start.getTime();
const endEpoch = end.getTime();
// convert array of categories into hastable for faster access
const categoriesResult = categories.reduce((acc, curr) => Object.assign(acc, {[curr]: 0}), {});
transactions
.forEach((tr) => {
const trEpoch = new Date(tr.time).getTime();
if (trEpoch >= startEpoch && trEpoch < endEpoch && typeof categoriesResult[tr.category] === 'number') {
// transaction is in range and belongs to the specified category
categoriesResult[tr.category] += tr.amount;
}
});
return categoriesResult;
};
module.exports = getBalanceByCategoryInPeriod;
const getBalanceByCategoryInPeriod = require('./getBalanceByCategoryInPeriod.js')
describe('getBalanceByCategoryInPeriod()', () => {
it('returns the correct balance matching a category in specified period', () => {
expect(
getBalanceByCategoryInPeriod(
[
{
id: '11ff73b5-e771-441c-886a-498d93b5093d',
sourceAccount: 'my_account',
targetAccount: 'restaurant',
amount: -9600,
currency: 'EUR',
category: 'eating_out',
time: '2021-04-08T05:15:56.905Z',
},
{
id: '8c3ec38d-1821-4d49-aef1-2385cb3c2b1b',
sourceAccount: 'my_account',
targetAccount: 'cinema',
amount: -5700,
currency: 'EUR',
category: 'entertainment',
time: '2021-04-07T21:16:57.819Z',
},
{
id: 'd1c77d7c-ccda-453c-ac01-444e9d5abca3',
sourceAccount: 'my_account',
targetAccount: 'book_store',
amount: -7400,
currency: 'EUR',
category: 'entertainment',
time: '2021-04-07T22:46:44.071Z',
},
{
id: '837127ab-f523-4b11-bed3-ae488be4545d',
sourceAccount: 'my_account',
targetAccount: 'fitness_club',
amount: -9200,
currency: 'EUR',
category: 'sports',
time: '2021-04-05T01:55:16.646Z',
},
],
['sports', 'entertainment'],
new Date('2021-04-01'),
new Date('2021-04-30')
)
).toEqual({ sports: -9200, entertainment: -13100 });
});
});
const transactions = [
{
id: 3,
sourceAccount: 'A',
targetAccount: 'B',
amount: 100,
category: 'eating_out',
time: '2018-03-02T10:34:30.000Z'
},
{
id: 1,
sourceAccount: 'A',
targetAccount: 'B',
amount: 100,
category: 'eating_out',
time: '2018-03-02T10:33:00.000Z'
},
{
id: 6,
sourceAccount: 'A',
targetAccount: 'C',
amount: 250,
category: 'other',
time: '2018-03-02T10:33:05.000Z'
},
{
id: 4,
sourceAccount: 'A',
targetAccount: 'B',
amount: 100,
category: 'eating_out',
time: '2018-03-02T10:36:00.000Z'
},
{
id: 2,
sourceAccount: 'A',
targetAccount: 'B',
amount: 100,
category: 'eating_out',
time: '2018-03-02T10:33:50.000Z'
},
{
id: 5,
sourceAccount: 'A',
targetAccount: 'C',
amount: 250,
category: 'other',
time: '2018-03-02T10:33:00.000Z'
}
];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment