请帮我解决ruby程序
让我们假设您有三个字符串,例如s1,s2和s3。现在编码F(s1,s2,s3)应该是s1的最短连续子序列,使得它具有s2的所有字符而不具有s3的所有字符。 s2有uniq chars
例如:s1 =" peeeeloisagood",s2 =" le",s3 =" z"。 Ans = el
答案 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
长度2
(s2
的大小)的子字符串。如果我们找到一个包含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"