How to Replace Noun Phrases With Pronouns in Golang


The challenge

A Noun Phrase is a phrase that can be replaced by a pronoun [he/she/it].

For example, in the sentence:

a girl ate the cookie

“A girl” is a Noun Phrase, so we can say “she ate the cookie.” “The cookie” is also a Noun Phrase, so we can even say “she ate it.”

Both of these Noun Phrases are made up of an auxialliary (aux) [the/a] followed by a Noun (N) [girl/cookie].

More complicated Noun Phrases can also include an arbitrary number of adjectives (adj). For example:

a big tall scary girl ate the cookie

where “big”, “tall”, and “scary” are all adjectives.

For our simplified model, we will define a Noun Phrase as an auxiliary, followed by 0 or more adjectives, followed by a Noun.

Write a function that takes a sentence (as a string of words separated by spaces), a list of pronouns, and a dictionary (maping words to the grammatical categories aux, adj, and N). Return the sentcnce with all Noun Phrases replaced by pronouns, in the order given.

Assume:

  • sentences will contain only lower-case letters and spaces (no puctuation)
  • any words not inlcuded in the dictionary are not auxilliaries, adjectives, or nouns
  • the number of pronouns provided will be equal to the number of Noun Phrases in the sentence

The solution in Golang

Option 1:

package solution
import "strings"
func ReplaceNounPhrases(str string, pro []string, dict map[string]string) string{
  words, phrase := strings.Fields(str), ""
  state, noun := 0, 0
  if len(pro) < 1 {return str}
  for _, word := range words {
    if _, ok := dict[word]; !ok {state = 0; continue}
    if state == 0 && dict[word] != "aux" {continue}
    if state == 1 {
      if dict[word] == "adj" {phrase += " " + word}
      if dict[word] == "N" {
        phrase += " " + word
        str = strings.Replace(str, phrase, pro[noun], 1)
        if noun < len(pro) - 1 {noun++}
        state = 0
      }
    }
    if dict[word] == "aux" {state, phrase = 1, word}
  }
  return str
}

Option 2:

package solution
import "strings"
func ReplaceNounPhrases(sentence string, pronouns []string, dictionary map[string]string) string {
  words, grams, res := strings.Split(sentence, " "), []string{}, []string{}  
  for _, word := range words { grams = append(grams, dictionary[word]) }
  n, i, j, k := len(words), 0, 0, 0
  for i<n {
    word:=words[i]
    if i<n-1 && grams[i]=="aux" {
      j = i+1
      for j<n && grams[j]=="adj" { j++ }
      if j<n && grams[j]=="N" { word = pronouns[k]; k++; i = j+1 } else { i++ }  
    } else { i++ }
    res = append(res, word)
  }
  return strings.Join(res, " ")
}

Option 3:

package solution
import "strings"
func ReplaceNounPhrases(sentence string, pronouns []string, dictionary map[string]string) string {
  words := strings.Split(sentence, " ")
  aux := -1
  var pronoun int
  for i := 0; i < len(words); i++ {
    if _, ok := dictionary[words[i]]; !ok {
      aux = -1
    } else if dictionary[words[i]] == "aux" {
      aux = i
    } else if dictionary[words[i]] == "N" && aux != -1 {
      left := append(words[:aux], pronouns[pronoun])
      right := words[aux+i-aux+1:]
      words = append(left, right...)
      pronoun++
      aux = -1
      i = aux
    }
  }
  return strings.Join(words, " ")
}

Test cases to validate our solution

package solution_test
import (
  . "github.com/onsi/ginkgo"
  . "github.com/onsi/gomega"
)

var dictionary = map[string]string{
  "a": "aux",
  "the": "aux",
  "girl" : "N",
  "cookie" : "N",
  "big" : "adj",
  "tall" : "adj",
  "scary" : "adj",
}

var _ = Describe("Test Example", func() {
  It("#1", func() {
    Expect(ReplaceNounPhrases("a girl", []string{"she"}, dictionary)).To(Equal("she"))
  })
  
   It("#2", func() {
    Expect(ReplaceNounPhrases("a girl ate the cookie", []string{"she", "it"}, dictionary)).To(Equal("she ate it"))
  })
  
  It("#3", func() {
    Expect(ReplaceNounPhrases("a a a big big a cookie", []string{"it"}, dictionary)).To(Equal("a a a big big it"))
  })
  
  It("#4", func() {
    Expect(ReplaceNounPhrases("a scary girl", []string{"she"}, dictionary)).To(Equal("she"))
  })
  
  It("#5", func() {
    Expect(ReplaceNounPhrases("a big tall scary girl ate the big cookie", []string{"she", "it"}, dictionary)).To(Equal("she ate it"))
  })
  
})