Ad
Algorithms
Logic
Formats
Strings
Data Types
Formatting

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();
		}
	}

}

Not quite sure if this is actually more eficient, but by using lambdas I managed to reduce the line count a bit more.

Code
Diff
  • 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();
    • }
    • }