House that Jack built.
Funny thing about simple programs is that there are too many optimization options available that never lets you feel content.
So here I am trying to solve another problem from exercism.io which is totally a must visit for anyone who wants to learn and practice.
Nursery rhyme
I wrote a couple of version before trying to improvise in a different way what soothes the undying thirst of improving that something, which is still not right.
Beauty lies in the eyes of beholder!
Funny context though
It is still not the best version
, but has brought some peace to my vacillating mind.
The Rhyme
This is the house that Jack built. This is the malt that lay in the house that Jack built. This is the rat that ate the malt that lay in the house that Jack built. This is the cat that killed the rat that ate the malt that lay in the house that Jack built. This is the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built. This is the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built. This is the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built. This is the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built. This is the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built. This is the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built. This is the farmer sowing his corn that kept the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built. This is the horse and the hound and the horn that belonged to the farmer sowing his corn that kept the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.
Logic building
The obvious question I had in mind was, what can help me break it in a way that it has a meaningful structure.
Grammar to the rescue
The subject is the “who” or “what” of the sentence, the predicate is the verb, and the object is any noun or concept that is part of the action of the subject.
Subject, predicate, and objects are the three different components when breaking down a sentence.
This helped me define a structure that I though will help me solve the poem into smaller chunks for each para.
type Predicate struct { character string predicate string } type Character struct { adjective string pred Predicate }
Example: This is the house that Jack built.
In this I was able to Identify house
as the Character
(Subject) and built
is the action
or predicate
and Jack is the character
embedded in predicate who took the action.
Using this as a building block I initialized two maps.
var verses map[int]string = map[int]string{ 1: "house", 2: "malt", 3: "rat", 4: "cat", 5: "dog", 6: "cow", 7: "maiden", 8: "man", 9: "priest", 10: "rooster", 11: "farmer", 12: "horse", } var characters map[string]Character = map[string]Character{ "house": {adjective: "", pred: Predicate{ predicate: "built.", character: "Jack", }, }, "malt": {adjective: "", pred: Predicate{ predicate: "lay in the", character: "house", }, }, "rat": {adjective: "", pred: Predicate{ predicate: "ate the", character: "malt", }, }, "cat": {adjective: "", pred: Predicate{ predicate: "killed the", character: "rat", }, }, "dog": {adjective: "", pred: Predicate{ predicate: "worried the", character: "cat", }, }, "cow": {adjective: "with the crumpled horn", pred: Predicate{ predicate: "tossed the", character: "dog", }, }, "maiden": {adjective: "all forlorn", pred: Predicate{ predicate: "milked the", character: "cow", }, }, "man": {adjective: "all tattered and torn", pred: Predicate{ predicate: "kissed the", character: "maiden", }, }, "priest": {adjective: "all shaven and shorn", pred: Predicate{ predicate: "married the", character: "man", }, }, "rooster": {adjective: "that crowed in the morn", pred: Predicate{ predicate: "woke the", character: "priest", }, }, "farmer": {adjective: "sowing his corn", pred: Predicate{ predicate: "kept the", character: "rooster", }, }, "horse": {adjective: "and the hound and the horn", pred: Predicate{ predicate: "belonged to the", character: "farmer", }, }, }
The problem that was still wasn’t that obvious to me was some subjects had adjectives which were unassumingly borrowed when used in the predicate.
Example: This is the maiden all forlorn that milked the cow with the crumpled horn
Now to write the function to return the verses numerically from 1 to 12, a simple stitcher which uses fmt
‘s Fprintf
method and StringBuilder
from strings
func Verse(stanza int) (verse string) { var v strings.Builder var character string character = verses[stanza] if stanza == 1 { fmt.Fprintf(&v, "%s %s that %s %s", This, character, characters[character].pred.character, characters[character].pred.predicate) } else { for j := stanza; j > 0; j-- { character = verses[j] predChar := characters[character].pred.character if j == stanza { if characters[character].adjective == "" { fmt.Fprintf(&v, "%s %s\nthat %s %s", This, character, characters[character].pred.predicate, characters[character].pred.character) } else { fmt.Fprintf(&v, "%s %s %s\nthat %s %s", This, character, characters[character].adjective, characters[character].pred.predicate, characters[character].pred.character) } } else if j == 1 { fmt.Fprintf(&v, " that %s %s", characters[character].pred.character, characters[character].pred.predicate) } else { fmt.Fprintf(&v, "\nthat %s %s", characters[character].pred.predicate, characters[character].pred.character) } if predChar != "" && characters[predChar].adjective != "" { fmt.Fprintf(&v, " %s", characters[predChar].adjective) } } } verse = strings.TrimSpace(v.String()) return verse }