Created
May 20, 2022 15:35
-
-
Save vvgomes/4a15346c4a2cac00cdb77020cd0c4969 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| The goal of this exercise is to render an org chart | |
| in your terminal output based on a list of manager- | |
| employee relationships. | |
| Given the following relationships: | |
| [ | |
| { managerId: 1, employeeId: 2 }, | |
| { managerId: 0, employeeId: 3 }, | |
| { managerId: 0, employeeId: 1 }, | |
| { managerId: 0, employeeId: 0 }, | |
| ] | |
| We expect the following output: | |
| 0 | |
| |_1 | |
| |_2 | |
| |_3 | |
| The solution below is based on a tree datastructure | |
| as an intermediate representation for the org chart | |
| and the aggregation algorithm follows a recursive | |
| approach combined with the Resequencer pattern as | |
| described here: | |
| https://www.enterpriseintegrationpatterns.com/patterns/messaging/Resequencer.html | |
| */ | |
| const relationships = [ | |
| { managerId: 1, employeeId: 11 }, | |
| { managerId: 0, employeeId: 2 }, | |
| { managerId: 1, employeeId: 12 }, | |
| { managerId: 0, employeeId: 0 }, | |
| { managerId: 2, employeeId: 21 }, | |
| { managerId: 0, employeeId: 1 }, | |
| { managerId: 2, employeeId: 22 }, | |
| ]; | |
| function findEmployee(id, root) { | |
| if (!Object.keys(root).length) return; | |
| if (id === root.id) return root; | |
| return root.reports.find(e => findEmployee(id, e)); | |
| } | |
| function findInBuffer(id, buffer) { | |
| return buffer.find(e => e.id === id); | |
| } | |
| function addToBuffer(e, buffer) { | |
| return buffer.concat(e); | |
| } | |
| function removeFromBuffer(id, buffer) { | |
| return buffer.filter(e => e.id !== id); | |
| } | |
| function createEmployee(id, reports = []) { | |
| return { id, reports }; | |
| } | |
| function consume(input, index = 0, output = {}, buffer = []) { | |
| if (index > input.length - 1) return output; | |
| let updatedBuffer; | |
| const { managerId, employeeId } = input[index]; | |
| // finding employee | |
| const employeeFromBuffer = findInBuffer(employeeId, buffer); | |
| if (employeeFromBuffer) updatedBuffer = removeFromBuffer(employeeId, buffer); | |
| const employee = employeeFromBuffer || createEmployee(employeeId); | |
| // it's the ceo | |
| if (employeeId === managerId) | |
| return consume(input, index + 1, employee, updatedBuffer || buffer); | |
| // it's not the ceo | |
| const existingManager = findEmployee(managerId, output) || findInBuffer(managerId, buffer); | |
| const manager = existingManager || createEmployee(managerId); | |
| manager.reports.push(employee); | |
| if (!existingManager) updatedBuffer = addToBuffer(manager, updatedBuffer || buffer); | |
| return consume(input, index + 1, output, updatedBuffer || buffer); | |
| } | |
| function renderOffset(level) { | |
| if (level === 0) return ""; | |
| return Array(level - 1) | |
| .fill(" ", 0, level - 1) | |
| .join("") | |
| .concat("|_"); | |
| } | |
| function renderOrgChart(root, level = 0) { | |
| const offset = renderOffset(level); | |
| const id = offset.concat(root.id); | |
| const reports = root.reports.map(report => renderOrgChart(report, level + 1)); | |
| return [id].concat(reports).join("\n"); | |
| } | |
| console.log(renderOrgChart(consume(relationships))); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment