Haiku Formatting

From programming_contest
(Redirected from Haiku)
Jump to navigation Jump to search

This problem asks us to make a "haiku bot" which takes input text and outputs it as a haiku.

This is not hard algorithmically, but tricky to implement if one is not familiar with regex. To simplify this problem, counting syllables amounts to counting vowels after all the rules have been applied. For simplicity, we will simply convert all the vowels to a's and then count them. We apply the rules from most general to most specific. Note that the original text must be maintained as well for output purposes.

  1. make everything lower case
  2. remove all punctuation characters
  3. change "qu" to some consonant which won't cause other issues....like k
  4. change y followed by a vowel to some consonant
  5. apply the "end of word rules
    1. deal with words ending with e....removing the e if it won't be a syllable in the end
    2. deal with es, removing it if it won't end up counting as an extra syllable
  6. convert any remaining vowels to 'a'
  7. count them

Making the haiku is thus easy. We walk the input words, counting their syllables. If we hit the right syllable count at a word end (5 or 7) print an continue. If we don't hit the appropriate count, the haiku fails. Implementation note here: We can eliminate a bunch of duplicate code by having a static array {5,7,5} and just having a pointer to the number of syllables we're currently trying to hit.

import java.util.*;
public class h {
	static Scanner in2=new Scanner(System.in);
	static int[] count= {5,7,5};
	public static void main(String[] args) {
		String unm=in2.nextLine();
		Scanner in=new Scanner(unm);
		ArrayList<String>al=new ArrayList<>();
		while(in.hasNext())al.add(in.next());
		String[] work=new String[al.size()];
		int[] syllables=new int[al.size()];
		for(int i=0;i<al.size();i++) {//count syllables in each word
			work[i]=al.get(i).toLowerCase().replaceAll("[^a-z]", "").replaceAll("qu", "k").replaceAll("y[aeiou]", "k");
			if(work[i].endsWith("e"))work[i]=work[i].replaceAll("([^l]|[aeiouy]l)e$", "$1");//need to split these out so we don't accidently apply both!
			else if(work[i].endsWith("es"))work[i]=work[i].replaceAll("([aeiouy]|[aeiouy][^aeiouy])es$","$1");
			work[i]=work[i].replaceAll("[aeiouy]+", "a");
			for(char c:work[i].toCharArray())if(c=='a')syllables[i]++;
			syllables[i]=Math.max(1, syllables[i]);
		}
		int sum=0,j=0;//see if it makes a haiku
		boolean works=true;
		StringBuilder out=new StringBuilder("");
		for(int i:count) {
			for(sum=0;j<al.size()&&sum<i;j++) {
				sum+=syllables[j];
				out.append(al.get(j)+" ");
			}
			if(sum!=i)works=false;
			out.deleteCharAt(out.length()-1).append("\n");//remove the extra space and add the newline
		}
		if(j==al.size()&&works)System.out.print(out);
		else System.out.println(unm);
	}
}