Ruby编程测验

时间:2014-08-25 16:49:48

标签: algorithm

请帮我解决ruby程序

让我们假设您有三个字符串,例如s1,s2和s3。现在编码F(s1,s2,s3)应该是s1的最短连续子序列,使得它具有s2的所有字符而不具有s3的所有字符。 s2有uniq chars

例如:s1 =" peeeeloisagood",s2 =" le",s3 =" z"。 Ans = el

2 个答案:

答案 0 :(得分:3)

这应该这样做。 (不要被我在@AFaderDarkly之前发布的事实所迷惑。@AFaderDarkly有一个类似的答案。我的原始答案有一个缺陷。当我注意到它时,我删除了我的答案并着手修复。在我完成之前黑暗地发布了修复,但我不知道,直到我取消修改后的答案。)

<强>代码

def find_it(s1,s2,s3)
  arr = s1.chars
  good = s2.chars
  bad = s3.chars    
  (good.size..arr.size).each { |n| arr.each_cons(n) { |c|
    return c.join if (good-c).empty? && (c-bad) == c } }
  nil
end

<强>实施例

find_it("peeeeloisagood", "le", "z") #=> "el"
find_it("abcdezfherdzn", "def", "z") #=> "fherd"

<强>解释

设s1,s2和s3与上面的第二个例子相同:

s1 = "abcdezfherdzn"
s2 = "def"
s3 = "z"

我们将首先查看s1长度2s2的大小)的子字符串。如果我们找到一个包含s2所有字母的字母,我们就完成了(因为它不能包含s3的任何字母)。如果我们找不到匹配项,则会查看s1长度为3的子字符串。如果我们找到包含s2的所有字母而不包含s3的所有字母的子字符串,我们就完成了,依此类推。如果任何长度的s1的子字符串都不包含s2的所有字母,而且s3的所有字母都不包含,则会返回nil

arr = s1.chars
  #=> ["a", "b", "c", "d", "e", "z", "f", "h", "e", "r", "d", "z", "n"]
good = s2.chars
  #=> ["d", "e", "f"]
bad = s3.chars    
  #=> ["z"]

enum1 = (good.size..arr.size).each
  #=>   (3..13).each
  #=>   #<Enumerator: 3..13:each>

我们可以将一个枚举器转换为一个数组,将它传递给它的块:

enum1.to_a
  #=> [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

此枚举器首先将3传递到其块中,并将其分配给块变量:

n = 3

enum2 = arr.each_cons(n)
  #=>   #<Enumerator: ["a", "b", "c", "d", "e", "z", "f", "h",
  #                    "e", "r", "d", "z", "n"]:each_cons(3)> 
enum2.to_a
  #=> [["a", "b", "c"], ["b", "c", "d"], ["c", "d", "e"], ["d", "e", "z"],
  #    ["e", "z", "f"], ["z", "f", "h"], ["f", "h", "e"], ["h", "e", "r"],
  #    ["e", "r", "d"], ["r", "d", "z"], ["d", "z", "n"]]

首先将["a", "b", "c"]传递给块并将其分配给块变量:

c = ["a", "b", "c"]

并执行

return c.join if (good-c).empty? && (c-bad) == c 
  #=> return "abc" if (["d", "e", "f"]-["a", "b", "c"]).empty? &&
  #                   (["a", "b", "c"] - ["z"]) == ["a", "b", "c"]
  #=> return "abc" if (["d", "e", "f"]).empty? && 
                      (["a", "b", "c"]) == ["a", "b", "c"]
  #=> return "abc" if false and true
  #=> false

这一直持续到数组["d", "e", "z", "f"]出现,此时我们得到:

return c.join if (good-c).empty? && (c-bad) == c 
  #=> return "dezf" if (["d", "e", "f"]-["d", "e", "z", "f"]).empty? &&
                       (["d", "e", "z", "f"]-["z"]) == ["d", "e", "z", "f"]
  #=> return "dezf" if [].empty? && ["d", "e", "f"] == ["d", "e", "z", "f"]
  #=> return "dezf" if true && false
  #=> false

所以我们也拒绝那个子字符串,这次是因为存在z

当我们到达

c = ["f", "h", "e", "r", "d"]

我们获得:

 return c.join if (good-c).empty? && (c-bad) == c 
   #=> return "fherd" if (["d", "e", "f"]-["f", "h", "e", "r", "d"]).empty? &&
                (["f", "h", "e", "r", "d"]-["z"]) == ["f", "h", "e", "r", "d"]
   #=> return "fherd" if [].empty? &&
                 ["f", "h", "e", "r", "d"] == ["f", "h", "e", "r", "d"]
   #=>return "fherd" if true && true

因此返回"fherd"

答案 1 :(得分:1)

search_string = s1.gsub(/^[^#{s2}]+|[^#{s2}]+$/, '')

包含所有s2的最短字符串将始终以s2中的字符开头和结尾,因此这会缩小搜索空间。

included = s2.chars.to_a.uniq
excluded = s3.chars.to_a.uniq
input = search_string.chars.to_a

这使事情变得更容易处理 - 所有都转换为数组。我们对包含和排除的数组运行uniq以捕获边缘情况并优化算法。

现在我们可以扫描字符串,蛮力风格:

(included.length..search_string.length).each do |l|

最短的字符串只能与包含的字符集一样短,所以我们设置一个在字符串中移动的搜索窗口,从这个长度开始并向上移动到字符串的整个长度。 l是窗口长度。

    input.each_cons(l) do |s|

通过输入数组移动窗口。

      if (included - s).length == 0 && excluded == excluded - s

通过减去数组来检查字符串是否匹配。

      puts s.join

这将显示所有比赛,最短的比赛。

    end
  end
end

全部放在一起:

def find_string(s1, s2, s3)
  search_string = s1.gsub(/^[^#{s2}]+|[^#{s2}]+$/, '')
  included = s2.chars.to_a.uniq
  excluded = s3.chars.to_a.uniq
  input = search_string.chars.to_a

  (included.length..search_string.length).each do |l|
    input.each_cons(l) do |s|
      if (included - s).length == 0 && excluded == excluded - s
        return s.join
      end
    end
  end
  ""
end   

find_string  "pleeeesoisalzesgood", "les", "z"
# => "leeees"

find_string  "pleeeesoisalesgood", "les", "z"
# => "les"

find_string  "pleeeesoisalesgood", "lees", "z" # Without the .uniq on included this would return 'sale'
# => "les" 

find_string  "peeeeloisagood", "le", "z"
# => "el"