20
\$\begingroup\$

So you want to create a haiku, but you're not sure if it follows the syllable rules for a haiku.

I couldn't be bothered to write a proper blurb like I usually do, so you'll have to make do with this. Let's get stuck right in.

Finding a haiku out in the wild

For the purposes of this challenge, we will be checking if the given poem satisfies these criteria:

  • There are three lines.
  • The first line has 5 syllables.
  • The second line has 7 syllables.
  • The third line has 5 syllables.

Each line is composed of one or more words, separated by groups of spaces. These words are not necessarily valid English words.

Each word is split up into syllables, and then those syllables are counted to get the total syllable count of the line.

A syllable has either 2 or 3 parts to it: the beginning, the end, and possibly the middle. Each part is either a group of consonsants (also known as a consonant cluster, such as s, sk or spl) or a group of vowels (such as i, ea or oui).

If the beginning is a group of consonants, the middle will be a group of vowels and the end will be a group of consonants. If the beginning is a group of vowels, the end will be a group of consonants and there will be no middle.

For example, the word example is made up of three syllables, ex, am and ple. ple has no ending as it was cut short by the end of the word.

As another example, the word syllable also has three syllables, syll, abl and e, which also has no ending.

For one final example, the word word has one syllable, word, which ends with a group of consonants.

The challenge

Given a string, list of strings, list of lists or any other reasonable format representing a poem with at least one line, determine if it meets the criteria of a haiku outlined above and return the result.

You may return the result in any of these formats:

  • A truthy value if the poem is a haiku and a falsy one otherwise.
  • A falsy value if the poem is a haiku and a truthy one otherwise.
  • A value from a finite range of values specified in the submission if the poem is a haiku and a value from a mutually exclusive finite range of values also specified in the submission.

You may also assume the poem contains no non-alphabetical characters, but you may not assume that it is entirely in uppercase or lowercase.

For the purposes of this challenge, Y is a vowel.

Test cases

Truthy

This is a haiku
Yes it truly is one
See what I did man

I am so tired
of writing this already
when can I stop this

Writing another
Of these horrific things
Come on please

Consonant only
Counts as one syllable
ghjk tgh knmb wrts vbc

Falsy

oh boy writing non haiku is so much easier

This is
so good
on my
poor dear brain

The syllables do not match
at least I do not think so
I have not checked

It does not really matter
these test cases will help
At least I think they will

I am done here
This is enough
Goodbye

Scoring

Since this is
The shortest answer will win
Good luck to you all

\$\endgroup\$
2
  • \$\begingroup\$ Sandbox \$\endgroup\$
    – LyricLy
    Dec 31, 2017 at 21:53
  • \$\begingroup\$ Related \$\endgroup\$
    – LyricLy
    Dec 31, 2017 at 21:53

7 Answers 7

4
\$\begingroup\$

Jelly,  25  23 bytes

-2 thanks to Erik the Outgolfer (use a list of lines as input)

e€Øy0;ŒgP€
ḲLÐfÇ€ḣ8µ€ḣ4

A monadic link taking a list of lists of characters (the lines) and returning a list of lists of lists of zeros and ones. Valid haiku will be length 3 and once any of the deepest lists that are a single zero are replaced by a single one the sum of the flattened lists will be 5, 7, and 5 respectively. The formation (whether runs of letters are consonants and only taking the first 8 words of each of up to only 4 lines) ensures there are only finite of each of the valid and invalid ranges.

Try it online! or see the (even more confusing!) test-suite


Here is a much easier to use  32  30 byte version, simply outputting 1 or 0:

e€Øy0;ŒgP€SȯL$
ḲLÐfÇ€Sµ€⁼5,7,5

Try this one or see its test-suite.

\$\endgroup\$
4
  • \$\begingroup\$ I don't think the "range" of non-Haiku possibilities is finite - you can have an unbounded number of words/lines in those. \$\endgroup\$ Jan 1, 2018 at 0:35
  • \$\begingroup\$ Oh damn when the change was made I thought it was only the haiku range that need be finite. That puts it back to the 32 byter I think. \$\endgroup\$ Jan 1, 2018 at 0:42
  • \$\begingroup\$ OK addressed for four bytes by limiting words per line to eight and lines to four. \$\endgroup\$ Jan 1, 2018 at 0:48
  • \$\begingroup\$ I think you can remove Ỵµ, as you can take a list of lines. \$\endgroup\$ Jan 1, 2018 at 16:14
3
\$\begingroup\$

JavaScript (ES6), 84 75 bytes

Takes input as a list of lists of words. Returns true for haiku or false for non-haiku.

a=>a.map(s=>(s.map(w=>w.match(/[aeiouy]+/gi))+'').split`,`.length)=='5,7,5'

Test cases

let f =

a=>a.map(s=>(s.map(w=>w.match(/[aeiouy]+/gi))+'').split`,`.length)=='5,7,5'

console.log('[Truthy]');

console.log(f([
  ["This","is","a","haiku"],
  ["Yes","it","truly","is","one"],
  ["See","what","I","did","man"]
]));
console.log(f([
  ["I","am","so","tired"],
  ["of","writing","this","already"],
  ["when","can","I","stop","this"]
]));
console.log(f([
  ["Writing","another"],
  ["Of","these","horrific","things"],
  ["Come","on","please"]
]));
console.log(f([
  ["Consonant","only"],
  ["Counts","as","one","syllable"],
  ["ghjk","tgh","knmb","wrts","vbc"]
]));

console.log('[Falsy]');

console.log(f([
  ["oh","boy","writing","non","haiku","is","so","much","easier"]
]));
console.log(f([
  ["This","is"],
  ["so","good"],
  ["on","my"],
  ["poor","dear","brain"]
]));
console.log(f([
  ["The","syllables","do","not","match"],
  ["at","least","I","do","not","think","so"],
  ["I","have","not","checked"]
]));
console.log(f([
  ["It","does","not","really","matter"],
  ["these","test","cases","will","help"],
  ["At","least","I","think","they","will"]
]));
console.log(f([
  ["I","am","done","here"],
  ["This","is","enough"],
  ["Goodbye"]
]));

\$\endgroup\$
2
\$\begingroup\$

Retina, 49 bytes

i`[aeiouy]+
1
T`lL`2
2*12+
3
[12]+
3
%M`3
^5¶7¶5$

Try it online!

Outputs 1 for haiku,0 for non-haiku.

\$\endgroup\$
2
  • \$\begingroup\$ @FryAmTheEggman That worked, except I had to add ^ and $ because x haikus in a row would give x as a string. \$\endgroup\$ Jan 1, 2018 at 0:14
  • 1
    \$\begingroup\$ I think this might work for 45 bytes. \$\endgroup\$
    – Neil
    Jan 1, 2018 at 15:36
2
\$\begingroup\$

Python 2, 126 125 120 121 bytes

lambda s:[len(split('\s+',sub('[aeiouy][^aeiouy ]+','X ',t,0,I).strip()))for t in s.split('\n')]==[5,7,5]
from re import*

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ Your last edit broke the requirement that consonant-only words count as 1 syllable. \$\endgroup\$ Jan 1, 2018 at 1:39
  • \$\begingroup\$ @Ørjan Johansen: Fixed; thx! \$\endgroup\$
    – Chas Brown
    Jan 1, 2018 at 1:43
  • \$\begingroup\$ in 116B \$\endgroup\$
    – Traut
    Jan 1, 2018 at 12:32
  • 1
    \$\begingroup\$ You can golf some easy bytes off by taking input as a list of lines, and replacing s.split() with just s \$\endgroup\$
    – Riker
    Jan 1, 2018 at 16:33
2
\$\begingroup\$

Perl 5, 63 + 1 (-p) = 64 bytes

$a[$.]=()=/([aeiouy]+|\b[^aeiouy ]+\b)\s*/ig}{$\="@a"eq" 5 7 5"

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Clean, 162 ... 115 bytes

import StdEnv,StdLib
@t=[sum[max(sum(map hd(group[sum[1\\v<-:"AaEeIiOoUuYy"|c==v]\\c<-w])))1\\w<-l]\\l<-t]==[5,7,5]

Defines the function @, taking [[[Char]]] (list of list of words), and giving Bool.
Returns True when the input is a haiku, False otherwise.

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Seems to fail on the consonant-only word corner case. \$\endgroup\$ Jan 2, 2018 at 1:01
  • \$\begingroup\$ @ØrjanJohansen fixed \$\endgroup\$
    – Οurous
    Jan 2, 2018 at 1:13
1
\$\begingroup\$

Mathematica 119 Bytes

Here is a version that conforms to the given rules for syllables:

Tr/@Map[Length@StringCases[#,("a"|"e"|"i"|"o"|"u"|"y")..]/. 0->1&,(s=StringSplit)/@s[ToLowerCase@#,"\n"],{2}]=={5,7,5}&

Here is an 83 byte version that actually counts syllables:

Tr/@Map[Length@WordData[#,"Hyphenation"]&,(s=StringSplit)/@s[#,"\n"],{2}]=={5,7,5}&

e.g.

%@"This is a haiku
Yes it truly is one
See what I did man"

returns False since the second line has six syllables rather than the required seven.

\$\endgroup\$
6
  • \$\begingroup\$ This fails because the challenge explicitly defines its own syllable count, which does not use ordinary English rules. \$\endgroup\$ Jan 5, 2018 at 17:39
  • \$\begingroup\$ Well thanks for not downvoting. I see an attempt at a definition of a syllable, but it's not clear. I'm guessing "one" has two syllables by this definition. Looks like people are just counting contiguous vowels. \$\endgroup\$ Jan 5, 2018 at 18:10
  • \$\begingroup\$ Almost, but words with no vowels count as one syllable. See the question comments. I suppose it's just confusing about what to do about consonant groups, but that doesn't actually affect the final count. \$\endgroup\$ Jan 5, 2018 at 18:15
  • \$\begingroup\$ "one" has two vowels, and they aren't contiguous. \$\endgroup\$ Jan 5, 2018 at 18:18
  • \$\begingroup\$ Right, so they count as two syllables. \$\endgroup\$ Jan 5, 2018 at 18:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.