diff --git a/services/codewars/katas/4_kyu/Human readable duration format/README.md b/services/codewars/katas/4_kyu/Human readable duration format/README.md new file mode 100644 index 0000000..465ffa8 --- /dev/null +++ b/services/codewars/katas/4_kyu/Human readable duration format/README.md @@ -0,0 +1,34 @@ +# Human readable duration format + +Your task in order to complete this Kata is to write a function which formats a duration, given as a number of seconds, in a human-friendly way. + +The function must accept a non-negative integer. If it is zero, it just returns `"now"`. Otherwise, the duration is expressed as a combination of `years`, `days`, `hours`, `minutes` and `seconds`. + +It is much easier to understand with an example: + +``` +* For seconds = 62, your function should return + "1 minute and 2 seconds" +* For seconds = 3662, your function should return + "1 hour, 1 minute and 2 seconds" +``` + +For the purpose of this Kata, a year is 365 days and a day is 24 hours. + +Note that spaces are important. + +Detailed rules + +The resulting expression is made of components like 4 seconds, 1 year, etc. In general, a positive integer and one of the valid units of time, separated by a space. The unit of time is used in plural if the integer is greater than 1. + +The components are separated by a comma and a space (", "). Except the last component, which is separated by " and ", just like it would be written in English. + +A more significant units of time will occur before than a least significant one. Therefore, 1 second and 1 year is not correct, but 1 year and 1 second is. + +Different components have different unit of times. So there is not repeated units like in 5 seconds and 1 second. + +A component will not appear at all if its value happens to be zero. Hence, 1 minute and 0 seconds is not valid, but it should be just 1 minute. + +A unit of time must be used "as much as possible". It means that the function should not return 61 seconds, but 1 minute and 1 second instead. Formally, the duration specified by of a component must not be greater than any valid more significant unit of time. + +[Kata link](https://www.codewars.com/kata/52742f58faf5485cae000b9a) diff --git a/services/codewars/katas/4_kyu/Human readable duration format/src/go.mod b/services/codewars/katas/4_kyu/Human readable duration format/src/go.mod new file mode 100644 index 0000000..4a8c2df --- /dev/null +++ b/services/codewars/katas/4_kyu/Human readable duration format/src/go.mod @@ -0,0 +1,3 @@ +module src + +go 1.21 diff --git a/services/codewars/katas/4_kyu/Human readable duration format/src/solution.go b/services/codewars/katas/4_kyu/Human readable duration format/src/solution.go new file mode 100644 index 0000000..66a215a --- /dev/null +++ b/services/codewars/katas/4_kyu/Human readable duration format/src/solution.go @@ -0,0 +1,61 @@ +package main + +import ( + "fmt" + "strings" +) + +type timeComponent struct { + value int64 + verboseName string + pluralSuffix string +} + +func FormatDuration(seconds int64) string { + if seconds < 0 { + return "now" + } + + const ( + secondsPerYear = 31536000 + secondsPerDay = 86400 + secondsPerHour = 3600 + secondsPerMinute = 60 + ) + years, yearsRemainder := seconds/secondsPerYear, seconds%secondsPerYear + days, hoursRemainder := yearsRemainder/secondsPerDay, yearsRemainder%secondsPerDay + hours, minuteRemainder := hoursRemainder/secondsPerHour, hoursRemainder%secondsPerHour + minutes, secondsRemainder := minuteRemainder/secondsPerMinute, minuteRemainder%secondsPerMinute + + timeComponents := []timeComponent{ + {years, "year", "s"}, + {days, "day", "s"}, + {hours, "hour", "s"}, + {minutes, "minute", "s"}, + {secondsRemainder, "second", "s"}, + } + + var formattedComponents []string + for _, component := range timeComponents { + if formattedValue := formatTimeComponent(component); formattedValue != "" { + formattedComponents = append(formattedComponents, formattedValue) + } + } + + separatedByCommaValues := strings.Join(formattedComponents, ", ") + if lastCommaIndex := strings.LastIndex(separatedByCommaValues, ", "); lastCommaIndex != -1 { + separatedByCommaValues = separatedByCommaValues[:lastCommaIndex] + " and" + separatedByCommaValues[lastCommaIndex+1:] + } + + return separatedByCommaValues +} + +func formatTimeComponent(component timeComponent) string { + if component.value == 0 { + return "" + } else if component.value > 1 { + return fmt.Sprintf("%d %s%s", component.value, component.verboseName, component.pluralSuffix) + } + + return fmt.Sprintf("%d %s", component.value, component.verboseName) +}