I'm working on a Ruby verison of RSG and somehow stuck on the sentence generating process (...)
so I managed to implement all functions like read, convert to hash...,etc. But problem is how to randomly pick values in hash to generate the sentence?
Now I have a hash here:
hash = {"<start>"=>[["The", "<object>", "<verb>", "tonight."]],
"<object>"=>[["waves"], ["big", "yellow", "flowers"], ["slugs"]],
"<verb>"=>[["sigh", "<adverb>"], ["portend", "like", "<object>"],["die", "<adverb>"]],
"<adverb>"=>[["warily"], ["grumpily"]]}
The Objective is to assemble the strings using random values in the hash for example when the function iterates to "<object>"
, it will take it as a key and search in the hash to find matching key then randomly pick the corresponding values (one of the strings in "<object>"=>[["waves"], ["big", "yellow", "flowers"], ["slugs"]]
) and assemble it, then the output would be something like this:
"The waves sigh warily tonight"
My code so far:
hash.each do |_, value|
value.map{|x| x.map{|y| is_non_terminal?(y) ? (puts value.values_at("SomethingToPutInto")) : (puts y)}}
end
Somehow the logics in the code becomes too complicated and I'm stuck on this step.. Using values_at
will cause TypeError: no implicit conversion of String into Integer (TypeError)
For is_non_terminal?(y)
is just a function to check whether the string contains <
and >
:
def is_non_terminal?(s)
s.include?('<' && '>') ? true : false
end
Code
Examples
Explanation
Firstly,
mod_hash
is constructed.Then the initial sentence is obtained.
We now simply replace each word in
sentence
that begins'<'
and ends'>'
with a randomly-selected element of the value of that key inmod_hash
(the value being an array of strings). This continues until there are no more such words insentence
.The question mark in the regex means that one or more characters are to be matched lazily. That means that the match is terminated as soon as the first
'>'
is encountered. If, for example, the sentence were"a <hat> and <cat>!"
, the regex would match both<hat>
and<cat>
. By contrast, if the match were greedy (the default), it would match"<hat> and <cat>"
, which of course is not a key ofmod_hash
.Note that
hash
could have a structure that results in a non-terminating sequence of replacements.See Hash#transform_values.
I assume they're looking for a recursive method, let's call it
generate
.Read the hash at the key and take one randomly using
sample
:Then, for each word, check to see if it's a
<key>
. If so, callgenerate
on it, otherwise save it:Putting it all together:
Notice I used @-variables to make their scope reachable from within the method.
Sample output:
The big yellow flowers sigh grumpily tonight.