Ruby在保持顺序的同时创建带子串的句子

时间:2017-02-28 18:55:57

标签: ruby

我目前正在处理Ruby问题,其中我基本上是在创建自己的语言。下面(名词,动词,文章)可以被认为是单词。但是,为了创建一个有效的句子,我必须有动词,名词或至少2篇文章。

名词:" abcd"," c"," def"," h"," ij,&#34 ; CDE"

动词:&#34; bc&#34;,&#34; fg&#34;,&#34; g&#34;,&#34; hij&#34;,&#34; bcd&#34; < / p>

文章:&#34; a&#34;,&#34; ac&#34;,&#34; e&#34;

所以我要做的就是写一个方法,它接受一个字符串并返回所有可能的有效句子(同时保持字符的顺序相同,并在单词之间插入一个空格)

离。输入= "abcdefg" 返回列表

[ "a bc def g", "a bcd e fg", "abcd e fg"] 

所以我试着解决问题,这就是我到目前为止所做的

alpha = "abcdefg"



nouns = ["abcd", "c", "def", "h", "ij", "cde"]
verbs = ["bc", "fg", "g", "hij", "bcd"]
articles = ["a", "ac", "e"]

verbArray = [];
nounArray = [];
articleArray = [];

nouns.each do |item|
  if alpha.include?(item)
    nounArray << item
  end
end

verbs.each do |item|
  if alpha.include?(item)
    verbArray << item
  end
end

articles.each do |item|
  if alpha.include?(item)
    articleArray << item
  end
end


puts nounArray.inspect => ["abcd", "c", "def", "cde"]
puts verbArray.inspect => ["bc", "fg", "g", "bcd"]
puts articleArray.inspect => ["a", "e"]

我的思维过程是我首先想要为每个单词(名词,动词,文章)获得所有可能的组合。我不确定这是否是解决这个问题的最有效方法,但是除了这一步之外我还没有成功地形成有序的句子。

我一直在搜索堆栈和其他网站以寻找组合/排序技术的类型,而且我正试图避免使用正则表达式。我会诚实地感谢任何方向/反馈如何继续我解决这个问题的旅程。谢谢你的时间!

3 个答案:

答案 0 :(得分:1)

没有正则表达式是可能的,但是在没有递归的情况下你很难写任何东西:

grammar = {
  noun: ["abcd", "c", "def", "h", "ij", "cde"],
  verb: ["bc", "fg", "g", "hij", "bcd"],
  article:  ["a", "ac", "e"]}

def find_sentences(text, grammar, head = [], structure = [])
  if text.empty?
    if structure.include?(:verb) || structure.include?(:noun) || structure.count(:article) > 2
      puts "Sentence found : "
      puts head.join(' ')
      puts structure.join(' ')
      puts
    end
  else
    grammar.each do |type, words|
      words.each do |word|
        if text.start_with?(word)
          find_sentences(text.slice(word.size..-1), grammar, head + [word], structure + [type])
        end
      end
    end
  end
end

find_sentences("abcdefg", grammar)

输出:

Sentence found :
abcd e fg
noun article verb

Sentence found :
a bc def g
article verb noun verb

Sentence found :
a bcd e fg
article verb article verb

答案 1 :(得分:1)

这是编写递归方法的另一种方法。

def all_sentences(str, grammar)
  gram = grammar.each_with_object({}) { |(k,v),h|
    v.select { |s| str.include?(s) }.each { |s| h[s] = k } }
  recurse(str, gram.keys, gram, '')
end

def recurse(str, parts, gram, partial)
  p = partial.delete(' ')
  parts.each_with_object([]) do |part, arr|
    combine = p + part
    next unless str.start_with?(combine)
    s = (partial + ' ' + part).lstrip
    if combine.size == str.size
      arr << s if valid?(s, gram)
    else
      arr.concat(recurse(str, parts, gram, s))
    end
  end
end

def valid?(candidate, gram)
  arr = candidate.split
  arr.any? { |s| [:noun, :verb].include?(gram[s]) } ||
    arr.count { |s| gram[s] == :article } > 1
end

示例

grammar = {
  noun: ["abcd", "c", "def", "h", "ij", "cde"],
  verb: ["bc", "fg", "g", "hij", "bcd"],
  article:  ["a", "ac", "e"]
}

str = "abcdefg"

all_sentences(str, grammar)
  #=> ["abcd e fg", "a bc def g", "a bcd e fg"]

注意

对于该示例,哈希gram计算如下。

gram = grammar.each_with_object({}) { |(k,v),h|
  v.select { |s| str.include?(s) }.each { |s| h[s] = k } }
  #=> {"abcd"=>:noun, "c"=>:noun, "def"=>:noun, "cde"=>:noun,
  #    "bc"=>:verb, "fg"=>:verb, "g"=>:verb, "bcd"=>:verb,
  #    "a"=>:article, "e"=>:article} 

请注意,除了将单词映射到词性之外,我还删除了一些不能成为“句子”str一部分的“单词”。

让我感到震惊

words_to_pos = grammar.each_with_object({}) { |(k,v),h| v.each { |s| h[s] = k } }
  #=> {"abcd"=>:noun, "c"=>:noun, "def"=>:noun, "h"=>:noun, "ij"=>:noun,
  #    "cde"=>:noun, "bc"=>:verb, "fg"=>:verb, "g"=>:verb, "hij"=>:verb,
  #    "bcd"=>:verb, "a"=>:article, "ac"=>:article, "e"=>:article} 

将是比原始grammar(“词性”的“pos”)更方便的数据结构。

答案 2 :(得分:0)

在ruby中使用递归和lambda解决:

@nouns = ["abcd", "c", "def", "h", "ij", "cde"]
@verbs = ["bc", "fg", "g", "hij", "bcd"]
@articles = ["a", "ac", "e"]
@return_arr = []
def solve(idx, hash, ans = [])
    # base case
    if (idx >= $str.length) and  ( hash['vs'] >= 1) and (hash['ns'] >= 1 or hash['as'] >= 2)
        @return_arr << ans.join(" ")
        return
    end
    # define lamda to do common operation
    execute = lambda do |var, i|
        hash[var] += 1
        ans << $str[idx..i]
        solve(i+1, hash, ans)
        ans.pop
        hash[var] -= 1
    end
    #check for nouns, verbs, articles
    $str.each_char.with_index do |c,i|
        next if i < idx
        execute.call('ns', i) if @nouns.include? $str[idx..i]
        execute.call('vs', i) if @verbs.include? $str[idx..i]
        execute.call('as', i)if @articles.include? $str[idx..i]
    end
end

$str = gets.strip
hash = Hash.new(0)
solve(0, hash)
p @return_arr

输入:abcdefg

输出:["a bc def g", "a bcd e fg", "abcd e fg"]