Решение на Пета задача от Димо Станев

Обратно към всички решения

Към профила на Димо Станев

Резултати

  • 8 точки от тестове
  • 0 бонус точки
  • 8 точки общо
  • 56 успешни тест(а)
  • 1 неуспешни тест(а)

Код

class Checker
def is_code? str
/^ .*$/.match str
end
def is_heading? str
/^[\s]*[#]{1,4}[ \t\r\f]+[\S]+.*/.match str
end
def is_quote? str
/^[\s]*>[ \t\r\f]+.*\n?/.match str
end
def is_olist? str
/^[\s]*[\d]+\.[\s].*$/.match str
end
def is_ulist? str
/^[\s]*\*[^\*].*$/.match str
end
def is_empty? str
/^[\s]*$/.match str
end
end
class Replacer
def replace_heading mo
tmp = /([#]+)(.*)/.match mo.to_s
len = tmp.to_a[1].size
text = tmp.to_a[2].to_s.strip
"<h" + len.to_s + ">" + replace_s_s(text) + "</h" + len.to_s + ">\n"
end
def replace_quote mo
text = mo.to_s[1..-1]
"<blockquote>" + replace_s_s(text.strip) + "</blockquote>\n"
end
def replace_par str
"<p>" + replace_s_s(str) + "<\/p>\n"
end
def replace_s_s str
str.strip.gsub(/[&<>"]/,
{ "&" => "&amp;", "<" => "&lt;", ">" => "&gt;", "\"" => "&quot;" })
end
def replace_olist mo
text = mo.to_s.gsub(/[\d]+./, "")
"<ol>\n <li>" + replace_s_s(text.strip) + "<\/li>\n<\/ol>\n"
end
def replace_ulist mo
text = mo.to_s.gsub(/^[\s]*\*/, "")
"<ul>\n <li>" + replace_s_s(text.strip) + "<\/li>\n<\/ul>\n"
end
def replace_code mo
"<pre><code>" + replace_s_s('a' + mo.to_s[4..-1] + 'a')[1..-2] + "</code></pre>\n"
end
def remove str
tmp = str.gsub(/<\/code><\/pre>\n<pre><code>/, "\n")
tmp = tmp.gsub(/<\/blockquote>\n<blockquote>/, "\n")
tmp = tmp.gsub(/<\/ol>\n<ol>\n/, "")
tmp = tmp.gsub(/<\/ul>\n<ul>\n/, "")
tmp = tmp.gsub(/(?<=<blockquote>).+?(?=<\/blockquote>)/m) { |str| make_pars str }
tmp = tmp.gsub(/<\/p>\n<\/blockquote>/, "<\/p><\/blockquote>")
tmp.gsub(/<\/p>\n<p>/, "\n")
end
def make_pars str
str.to_s.each_line.inject("") { |a, b| a +
((/^[\s]*$/.match b) ? b : ("<p>" + b.strip + "<\/p>\n")) }
end
def add_link str
unless /(\[[^\n\]]+\])(\([^\n\)]+\))/.match str
return str
end
a = /(\[[^\n\]]+\])(\([^\n\)]+\))/.match str
tmp = "<a href=\"" + a.to_a[2][1..-2] + "\">" + a.to_a[1][1..-2] + "<\/a>"
str.gsub(/(\[[^\n\]]+\])(\([^\n\)]+\))/, tmp)
end
end
class Font
def make_fonts str
str = str.each_line.inject("") { |a, b| a + strong_line(b) }
str.each_line.inject("") { |a, b| a + em_line(b) }
end
def match_code str
/<pre><code>.*?<\/code><\/pre>/m.match str
end
def strong_line str
if match_code str
return str
end
i = 0
while i < str.size do
if /\*\*.+?\*\*/.match str, i
str = make_strong(str, i)
end
i += 1
end
str
end
def em_line str
if match_code str
return str
end
i = 0
while i < str.size do
if /_.+?_/.match str, i
str = make_em(str, i)
end
i += 1
end
str
end
def make_strong str, i
a = str.match /\*\*.+?\*\*/, i
if(a.pre_match.count("_") % 2 == 1 and a.to_s.include? "_")
return str
end
a.pre_match + "<strong>" + a.to_s[2..-3] + "<\/strong>" + a.post_match
end
def sub_count str, subs
str.each_char.each_cons(subs.size).select {|s| s == subs.split(//)}.count
end
def make_em str, i
a = str.match /_.+?_/, i
if sub_count(a.pre_match, "<strong>") % 2 == 1 and sub_count(a.to_s, "<strong>") > 0
return str
end
a.pre_match + "<em>" + a.to_s[1..-2] + "<\/em>" + a.post_match
end
end
class Formatter
attr_accessor :raw_text, :c, :r, :f
def initialize str
@raw_text = str
@c = Checker.new
@r = Replacer.new
@f = Font.new
end
def to_html
convert @raw_text
end
def to_s
to_html
end
def inspect
@raw_text
end
def convert str
res = f.make_fonts r.remove(str.each_line.inject("") { |a, b| a + convert_line(b) })
res.strip
end
def convert_line str
if c.is_code? str then return r.replace_code c.is_code? str end
if c.is_heading? str then return r.add_link r.replace_heading c.is_heading? str end
if c.is_quote? str then return r.add_link r.replace_quote c.is_quote? str end
if c.is_olist? str then return r.add_link r.replace_olist c.is_olist? str end
if c.is_ulist? str then return r.add_link r.replace_ulist c.is_ulist? str end
if c.is_empty? str then return str
else r.add_link r.replace_par str
end
end
end

Лог от изпълнението

.......................F.................................

Failures:

  1) Formatter links allows multiple links on a single line
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>We have <a href=\"some-url\">a first</a> and <a href=\"another-url\">Second</a>.</p>"
            got: "<p>We have <a href=\"some-url\">a first</a> and <a href=\"some-url\">a first</a>.</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1w4wq0z/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1w4wq0z/spec.rb:286:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.63518 seconds
57 examples, 1 failure

Failed examples:

rspec /tmp/d20111129-16859-1w4wq0z/spec.rb:285 # Formatter links allows multiple links on a single line

История (1 версия и 0 коментара)

Димо обнови решението на 22.11.2011 22:34 (преди над 12 години)

+class Checker
+ def is_code? str
+ /^ .*$/.match str
+ end
+
+ def is_heading? str
+ /^[\s]*[#]{1,4}[ \t\r\f]+[\S]+.*/.match str
+ end
+
+ def is_quote? str
+ /^[\s]*>[ \t\r\f]+.*\n?/.match str
+ end
+
+ def is_olist? str
+ /^[\s]*[\d]+\.[\s].*$/.match str
+ end
+
+ def is_ulist? str
+ /^[\s]*\*[^\*].*$/.match str
+ end
+
+ def is_empty? str
+ /^[\s]*$/.match str
+ end
+end
+
+class Replacer
+ def replace_heading mo
+ tmp = /([#]+)(.*)/.match mo.to_s
+ len = tmp.to_a[1].size
+ text = tmp.to_a[2].to_s.strip
+ "<h" + len.to_s + ">" + replace_s_s(text) + "</h" + len.to_s + ">\n"
+ end
+
+ def replace_quote mo
+ text = mo.to_s[1..-1]
+ "<blockquote>" + replace_s_s(text.strip) + "</blockquote>\n"
+ end
+
+ def replace_par str
+ "<p>" + replace_s_s(str) + "<\/p>\n"
+ end
+
+ def replace_s_s str
+ str.strip.gsub(/[&<>"]/,
+ { "&" => "&amp;", "<" => "&lt;", ">" => "&gt;", "\"" => "&quot;" })
+ end
+
+ def replace_olist mo
+ text = mo.to_s.gsub(/[\d]+./, "")
+ "<ol>\n <li>" + replace_s_s(text.strip) + "<\/li>\n<\/ol>\n"
+ end
+
+ def replace_ulist mo
+ text = mo.to_s.gsub(/^[\s]*\*/, "")
+ "<ul>\n <li>" + replace_s_s(text.strip) + "<\/li>\n<\/ul>\n"
+ end
+
+ def replace_code mo
+ "<pre><code>" + replace_s_s('a' + mo.to_s[4..-1] + 'a')[1..-2] + "</code></pre>\n"
+ end
+
+ def remove str
+ tmp = str.gsub(/<\/code><\/pre>\n<pre><code>/, "\n")
+ tmp = tmp.gsub(/<\/blockquote>\n<blockquote>/, "\n")
+ tmp = tmp.gsub(/<\/ol>\n<ol>\n/, "")
+ tmp = tmp.gsub(/<\/ul>\n<ul>\n/, "")
+ tmp = tmp.gsub(/(?<=<blockquote>).+?(?=<\/blockquote>)/m) { |str| make_pars str }
+ tmp = tmp.gsub(/<\/p>\n<\/blockquote>/, "<\/p><\/blockquote>")
+ tmp.gsub(/<\/p>\n<p>/, "\n")
+ end
+
+ def make_pars str
+ str.to_s.each_line.inject("") { |a, b| a +
+ ((/^[\s]*$/.match b) ? b : ("<p>" + b.strip + "<\/p>\n")) }
+ end
+
+ def add_link str
+ unless /(\[[^\n\]]+\])(\([^\n\)]+\))/.match str
+ return str
+ end
+ a = /(\[[^\n\]]+\])(\([^\n\)]+\))/.match str
+ tmp = "<a href=\"" + a.to_a[2][1..-2] + "\">" + a.to_a[1][1..-2] + "<\/a>"
+ str.gsub(/(\[[^\n\]]+\])(\([^\n\)]+\))/, tmp)
+ end
+end
+
+class Font
+ def make_fonts str
+ str = str.each_line.inject("") { |a, b| a + strong_line(b) }
+ str.each_line.inject("") { |a, b| a + em_line(b) }
+ end
+
+ def match_code str
+ /<pre><code>.*?<\/code><\/pre>/m.match str
+ end
+
+ def strong_line str
+ if match_code str
+ return str
+ end
+ i = 0
+ while i < str.size do
+ if /\*\*.+?\*\*/.match str, i
+ str = make_strong(str, i)
+ end
+ i += 1
+ end
+ str
+ end
+
+ def em_line str
+ if match_code str
+ return str
+ end
+ i = 0
+ while i < str.size do
+ if /_.+?_/.match str, i
+ str = make_em(str, i)
+ end
+ i += 1
+ end
+ str
+ end
+
+ def make_strong str, i
+ a = str.match /\*\*.+?\*\*/, i
+ if(a.pre_match.count("_") % 2 == 1 and a.to_s.include? "_")
+ return str
+ end
+ a.pre_match + "<strong>" + a.to_s[2..-3] + "<\/strong>" + a.post_match
+ end
+
+ def sub_count str, subs
+ str.each_char.each_cons(subs.size).select {|s| s == subs.split(//)}.count
+ end
+
+ def make_em str, i
+ a = str.match /_.+?_/, i
+ if sub_count(a.pre_match, "<strong>") % 2 == 1 and sub_count(a.to_s, "<strong>") > 0
+ return str
+ end
+ a.pre_match + "<em>" + a.to_s[1..-2] + "<\/em>" + a.post_match
+ end
+end
+
+class Formatter
+ attr_accessor :raw_text, :c, :r, :f
+
+ def initialize str
+ @raw_text = str
+ @c = Checker.new
+ @r = Replacer.new
+ @f = Font.new
+ end
+
+ def to_html
+ convert @raw_text
+ end
+
+ def to_s
+ to_html
+ end
+
+ def inspect
+ @raw_text
+ end
+
+ def convert str
+ res = f.make_fonts r.remove(str.each_line.inject("") { |a, b| a + convert_line(b) })
+ res.strip
+ end
+
+ def convert_line str
+ if c.is_code? str then return r.replace_code c.is_code? str end
+ if c.is_heading? str then return r.add_link r.replace_heading c.is_heading? str end
+ if c.is_quote? str then return r.add_link r.replace_quote c.is_quote? str end
+ if c.is_olist? str then return r.add_link r.replace_olist c.is_olist? str end
+ if c.is_ulist? str then return r.add_link r.replace_ulist c.is_ulist? str end
+ if c.is_empty? str then return str
+ else r.add_link r.replace_par str
+ end
+ end
+end