从地图创建字符串

时间:2016-10-30 21:30:53

标签: ruby

我目前正在开展一个项目,通过使用无上下文语法规则,我将生成随机句子。现在,我正在创建一个将接收哈希的函数,并遍历它选择正确的产品来创建一个句子并将其作为字符串返回。

例如,给定以下格式的哈希:

{
"<start>"=>[["The", "<object>", "<verb>", "tonight."]], 
"<object>"=>[["waves"], ["big", "yellow", "flowers"], ["slugs"]], 
"<verb>"=>[["sigh", "<adverb>"], ["portend", "like", "<object>"], ["die", "<adverb>"]], 
"<adverb>"=>[["warily"], ["grumpily"]]
}

我应该能够生成一个随机的句子,例如:&#34;波浪在今晚惨死了#34;。

以下是生成此句子的整个过程:

  1. 它将始终以<start>标签开始生成并继续填写所需的作品。
  2. 通过<start>并添加&#34;&#34;&#34;然后遇到了#34; <object>&#34;所以它进入<object>键并从那里抓取一个随机值,例如["waves"]
  3. 然后它返回并继续遍历并遇到&#34; <verb>&#34;所以它进入<verb>键并从那里抓取一个随机值,例如["die", "<adverb>"]
  4. 因为它遇到了&#34; <adverb>&#34;它必须进入<adverb>键并选择一个随机值,例如[&#34; grumpily&#34;]。
  5. 然后它会回到遍历,然后在今晚加上#34;&#34;。它已到达<start>的末尾,因此它现在可以输出句子。
  6. 如何编写随机生成句子的方法?

4 个答案:

答案 0 :(得分:4)

有趣的运动!

定义String#has_placeholder后?检查&lt;之间的单词和&gt;

只要有占位符,算法就会选择一个起始句并迭代它。如果找到占位符,则将其替换为随机选择的子句。 没有采取任何措施来检查错误。某些占位符可能未定义,或者可能存在无限循环。

它返回一个字符串,它也可以返回一个具有不同深度数组的树。

class String
  def has_placeholder?
    self=~/<\w+>/
  end
end

grammar = {
  "<start>"=>[["The", "<object>", "<verb>", "tonight."]], 
  "<object>"=>[["waves"], ["big", "yellow", "flowers"], ["slugs"]], 
  "<verb>"=>[["sigh", "<adverb>"], ["portend", "like", "<object>"], ["die", "<adverb>"]], 
  "<adverb>"=>[["warily"], ["grumpily"]]
}


sentence = grammar["<start>"].sample.join(' ')

while sentence.has_placeholder? do
  puts sentence
  sentence.sub!(/(<\w+>)/){grammar[$1].sample.join(' ')}
end

puts sentence

输出:

The <object> <verb> tonight.
The slugs <verb> tonight.
The slugs portend like <object> tonight.
The slugs portend like slugs tonight.

The <object> <verb> tonight.
The big yellow flowers <verb> tonight.
The big yellow flowers portend like <object> tonight.
The big yellow flowers portend like slugs tonight.

编辑:

您想要的方法如下所示:

def expand(grammar, nonterm = "<start>")
  sentence = grammar[nonterm].sample.join(' ')
  while sentence.has_placeholder? do
    sentence.sub!(/(<\w+>)/){grammar[$1].sample.join(' ')}
  end
  sentence
end

答案 1 :(得分:2)

这是一个快速实现,我使用symbols代替<>字符串但您可以更改它以便在需要时轻松处理。

$grammar = {
  :start   =>  [["The", :object, :verb, "tonight."]],
  :object  =>  [["waves"], ["big", "yellow", "flowers"], ["slugs"]],
  :verb    =>  [["sigh", :adverb], ["portend", "like", :object],
                 ["die", :adverb]],
  :adverb  =>  [["warily"], ["grumpily"]]
}

def generate_sentence key
  return key if key.class == String
  $grammar[key].sample.map {|word| generate_sentence word}.flatten
end

3.times do
  puts generate_sentence(:start).join(" ")
end

输出:

The big yellow flowers sigh warily tonight.
The slugs die warily tonight.
The big yellow flowers portend like slugs tonight.

答案 2 :(得分:2)

我的理解是所有哈希值都是数组,并且随机选择这些数组的元素。如果随机选择的元素是一个数组,则该数组中包含的所有单词都将在句子中使用,该数组中的任何散列键都将被该散列键值的随机选择元素替换,依此类推。

<强>代码

def random_words(h, key)
  h[key].map { |obj| recurse(h,obj) }.join(' ')
end

def recurse(h, obj)
  case obj
  when Array
    obj.map { |o| recurse(h, o) }
  when /\<.+?\>/
    recurse(h, h[obj].sample)
  else
    [obj]
  end
end

<强>实施例

示例1

h = { "<start>" =>[["The", "<object>", "<verb>", "tonight."]],
      "<object>"=>[["waves"], ["big", "yellow", "flowers"], ["slugs"]],
      "<verb>"  =>[["sigh", "<adverb>"], ["portend", "like", "<object>"],
                   ["die", "<adverb>"]],
      "<adverb>"=>[["warily"], ["grumpily"]]
}

random_words(h, "<start>")
  #=> "The waves portend like slugs tonight."
random_words(h, "<start>")
  #=> "The big yellow flowers sigh warily tonight." 
random_words(h, "<start>")
  #=> "The slugs die warily tonight." 

random_words(h, "<object>")
  #=> "waves big yellow flowers slugs" 
random_words(h, "<verb>")
  #=> "sigh warily portend like waves die warily" 
random_words(h, "<adverb>")
  #=> "warily grumpily" 

示例2

h = { "<start>" =>[["The", "<object>", "<verb>", "tonight."]],
      "<object>"=>[["waves"], ["big", "<verb>", "yellow", "flowers"], ["slugs"]],
      "<verb>"  =>[["sigh", "<adverb>"], ["portend", "like", "<object>"],
                   ["die", "<start>", "<adverb>"]],
      "<adverb>"=>[["warily", "<object>"], ["grumpily"]]
}

random_words(h, "<start>")
  #=> "The big sigh grumpily yellow flowers die The waves sigh grumpily \
  #    tonight. grumpily tonight." 
random_words(h, "<start>")
  #=> "The big die The big die The slugs sigh grumpily tonight. grumpily \
  #    yellow flowers die The big sigh warily slugs yellow flowers die The \
  #    slugs die The slugs portend like big portend like big sigh grumpily \
  #    yellow flowers yellow flowers tonight. grumpily tonight. grumpily \
  #    tonight. warily waves tonight. warily big die The slugs sigh warily \
  #    big sigh grumpily yellow flowers tonight. warily big portend like big \
  #    portend like waves yellow flowers yellow flowers yellow flowers yellow  \
  #    flowers sigh warily waves tonight." 

示例3

h = { "<g1>"=>[["It", "<g2>", "<g3>", "..."]],
      "<g2>"=>[["of"], ["waves"], ["was the", "<g3>", "<g4>", "<g3>"],
               ["wisdom,"], ["foolishness,"]],
      "<g3>"=>[["<g4>", "of", "<g2>"], ["it", "<g2>"]],
      "<g4>"=>[["best"], ["worst"], ["age"], ["times,"]]
}

random_words(h, "<g1>")
  #=> "It of it was the it was the it was the times, of foolishness, times, \
  #    it wisdom, best best of was the it of times, it was the times, of of \
  #    best it waves worst age of waves ..."
random_words(h, "<g1>")
  #=> "It was the best of times, it was the worst of times, it was the age of  \
  #    wisdom, it was the age of foolishness...

答案 3 :(得分:1)

def sentence_generator(hash)
  verby = hash["<verb>"].sample.map do |string|
    string = hash[string].nil? ? string : hash[string].sample.sample
  end.join(" ")

  hash["<start>"][0][0] + " " + hash["<object>"].sample.sample + " " +  verby + " " + hash["<start>"][0][3]
end

此方法应该为您完成工作。它可以使用一些小的重构,所以你可以调查一下。我希望它有所帮助