I just did the 4 kyu Human readable duration format Kata, and Although I managed to answer correctly, I feel like my code is unpolished.
I want to see the best approaches to this, and if possible, the explanation of what I did wrong.
Thanks.
RULES (taken straight out of the page):
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.
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.
public class TimeFormatter {
private final static int YEAROFSECONDS = 31536000;
private final static int DAYOFSECONDS = 86400;
private final static int HOUROFSECONDS = 3600;
private final static int MINUTEOFSECONDS = 60;
public static String formatDuration(int seconds) {
int[] counter = new int[5];
int componentCounter = 0;
StringBuilder sb = new StringBuilder();
while(seconds / YEAROFSECONDS >= 1) {
counter[0]++;
seconds = seconds - YEAROFSECONDS;
}
while(seconds / DAYOFSECONDS >= 1) {
counter[1]++;
seconds = seconds - DAYOFSECONDS;
}
while(seconds / HOUROFSECONDS >= 1) {
counter[2]++;
seconds = seconds - HOUROFSECONDS;
}
while(seconds / MINUTEOFSECONDS >= 1) {
counter[3]++;
seconds = seconds - MINUTEOFSECONDS;
}
counter[4] = seconds;
if(counter[0] == 0 && counter[1] == 0 && counter[2] == 0 && counter[3] == 0 && counter[4] == 0) {
return "now";
} else {
for(int i:counter) {
if(i != 0) {
componentCounter++;
}
}
int index = 0;
String toAdd = "error";
for(int i:counter) {
if(i != 0) {
switch(index) {
case 0:
if(i == 1) {
toAdd = "year";
} else {
toAdd = "years";
}
index++;
componentCounter--;
break;
case 1:
if(i == 1) {
toAdd = "day";
} else {
toAdd = "days";
}
index++;
componentCounter--;
break;
case 2:
if(i == 1) {
toAdd = "hour";
} else {
toAdd = "hours";
}
index++;
componentCounter--;
break;
case 3:
if(i == 1) {
toAdd = "minute";
} else {
toAdd = "minutes";
}
index++;
componentCounter--;
break;
case 4:
if(i == 1) {
toAdd = "second";
} else {
toAdd = "seconds";
}
index++;
componentCounter--;
break;
}
if(componentCounter == 1) {
sb.append(i);
sb.append(" ");
sb.append(toAdd);
sb.append(" and ");
} else {
sb.append(i);
sb.append(" ");
sb.append(toAdd);
if(componentCounter !=0){
sb.append(", ");
}
}
} else {
index++;
}
}
return sb.toString();
}
}
}
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;
// TODO: Replace examples and use TDD development by writing your own tests
public class SolutionTest {
@Test
public void testSomething() {
assertEquals("1 second", TimeFormatter.formatDuration(1));
assertEquals("1 minute and 2 seconds", TimeFormatter.formatDuration(62));
assertEquals("2 minutes", TimeFormatter.formatDuration(120));
assertEquals("1 hour", TimeFormatter.formatDuration(3600));
assertEquals("1 hour, 1 minute and 2 seconds", TimeFormatter.formatDuration(3662));
}
}
Not quite sure if this is actually more eficient, but by using lambdas I managed to reduce the line count a bit more.
import java.util.Arrays; public class Kata { public static int findShort(String s) { String[] split = s.split(" "); Arrays.sort(split,(String o1,String o2) -> o1.length() - o2.length()); return split[0].length(); } }
- import java.util.Arrays;
- public class Kata {
- public static int findShort(String s) {
int shortest = Integer.MAX_VALUE;for(String word : s.split(" ")) {int current = word.length();shortest = current < shortest ? current : shortest;}return shortest;- String[] split = s.split(" ");
- Arrays.sort(split,(String o1,String o2) -> o1.length() - o2.length());
- return split[0].length();
- }
- }