Skip to content

Instantly share code, notes, and snippets.

@nkhil
Last active April 22, 2022 20:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nkhil/bab532a2f8fcb1d3acf79cd4e0a8309b to your computer and use it in GitHub Desktop.
Save nkhil/bab532a2f8fcb1d3acf79cd4e0a8309b to your computer and use it in GitHub Desktop.
import never from 'never'
type ParsedLogs = Array<[string, string]>
type GroupedLogs = {
[K: string]: Array<string>
}
export default function main(logs: string) {
const parsedLogs = parseAndNormaliseLogs(logs)
const groupedLogs = groupCalls(parsedLogs)
const mostCalledNumber = findMostCalledNumber(groupedLogs)
return calculateTotalBill({
logs: groupedLogs,
mostCalledNumber,
})
}
function calculateTotalBill({
logs,
mostCalledNumber
}: {
logs: GroupedLogs,
mostCalledNumber: string,
}): number {
const FIVE_MINUTES = 5 * 60
return Object.entries(logs).reduce((totalBill, [phoneNumber, timestamps]) => {
if (phoneNumber !== mostCalledNumber) {
totalBill += timestamps.reduce((totalCostOfCall, timestamp) => {
const timeInSeconds = calculateSecondsGivenTimestamp(timestamp)
switch (true) {
case (timeInSeconds < FIVE_MINUTES):
totalCostOfCall += (timeInSeconds * 3)
break;
default:
const startedMinutes = Math.ceil(timeInSeconds / 60)
totalCostOfCall += 150 * startedMinutes
break;
}
return totalCostOfCall
}, 0)
}
return totalBill
}, 0)
}
function parseAndNormaliseLogs(logs: string): ParsedLogs {
const parsed = logs.split('\n').map(log => log.split(',')) as ParsedLogs
return normaliseLogs(parsed)
}
function normaliseLogs(logs: ParsedLogs): ParsedLogs {
const lastElementIndex = logs.length - 1
const lastElement = logs[lastElementIndex] ?? never()
if (lastElement[0] === '') return logs.slice(0, -1)
return logs
}
function groupCalls(logs: ParsedLogs): GroupedLogs {
return logs.reduce((acc, val) => {
const [ timestamp, phoneNumber ] = val
if (!acc.hasOwnProperty(phoneNumber)) {
acc[phoneNumber] = [timestamp]
} else {
(acc[phoneNumber] ?? never()).push(timestamp)
}
return acc
}, {} as GroupedLogs)
}
function calculateSecondsGivenTimestamp(timestamp: string): number {
const [hours, minutes, seconds] = timestamp.split(':')
return Number(hours) * 60 * 60 + Number(minutes) * 60 + Number(seconds)
}
function convertToNumber(phoneNumber: string): number {
return Number(phoneNumber.replace(/-/g, ''))
}
function numberWithSmallestNumericValue(numberOne: string, numberTwo: string): string {
if (convertToNumber(numberOne) < convertToNumber(numberTwo)) return numberOne
return numberTwo
}
function calculateTotalSeconds(timestamps: Array<string>): number {
return timestamps.reduce((acc, timestamp) => {
acc = acc + calculateSecondsGivenTimestamp(timestamp)
return acc
}, 0)
}
function findMostCalledNumber(logs: GroupedLogs): string {
let largestTotal = 0
return Object.keys(logs).reduce((acc, phoneNumber) => {
const totalSeconds = calculateTotalSeconds(logs[phoneNumber] ?? never())
if ((totalSeconds ?? never()) > largestTotal) {
acc = phoneNumber
largestTotal = (totalSeconds ?? never())
} else if ((totalSeconds ?? never()) === largestTotal) {
acc = numberWithSmallestNumericValue(phoneNumber, acc)
}
return acc
}, '')
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment