文字列の反転(括弧の対応を保存)
Posted feedbacks - Ruby
全般に無難なコードとおもいますが stk.popのところはちょっと感じ悪いかも。 つーかelsifでいろいろやりすぎ感がいやなのかなあ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | K = [['(', ')'], ['[', ']'], ['{', '}']]
OPN, CLS = K.transpose
def reverseString2(org)
str = org.split(//)
stk = []
str.each_with_index{|c, i|
if ki = OPN.index(c)
stk.push([i, ki])
elsif ki = CLS.index(c) and (j, kj = stk.pop) and ki == kj
str[j] = CLS[ki]
str[i] = OPN[kj]
end
}
str.reverse.join
end
if __FILE__ == $0
def test(a,b)
p a, reverseString2(a), b, reverseString2(a) == b
end
test("文字列(もじれつ)の反転(はんてん)", "(んてんは)転反の(つれじも)列字文")
test("対応[の{とれている(さまざまな)括弧}の(例)]です。", "。すで[(例)の{弧括(なまざまさ)るいてれと}の]応対")
test("これ(は(対応のとれていない)括弧がある例です。", "。すで例るあが弧括(いないてれとの応対)は(れこ")
test("これ(も{対応の)とれていない}括弧の例です。", "。すで例の弧括}いないてれと)の応対{も(れこ")
end
|
自動で括弧の対応にマッチしてくれるライブラリはあると結構便利かもしれないと感じました。(括弧の対応はもちろんカスタマイズ可能) 。探せば既にあるような気もするけど
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | def reverse_string2 str
match_pairs = {
'(' => ')',
'{' => '}',
'[' => ']',
}
match_pairs.each do |key,val|
str = str.gsub(/(#{Regexp.escape(key)})([^#{Regexp.escape(key)}]*?)(#{Regexp.escape(val)})/) {|str| "#{$3}#{$2}#{$1}" };
end
str.split(//).reverse.join
end
if $PROGRAM_NAME == __FILE__
$KCODE = 'u'
require 'rubygems'
require 'spec'
describe "reverse_string2" do
it "は文字列を反転させること" do
reverse_string2("文字列の反転").should == "転反の列字文"
end
it "は()の対応を保存すること" do
reverse_string2("文字列(もじれつ)の反転(はんてん)").should == "(んてんは)転反の(つれじも)列字文"
end
it "は{}の対応を保存すること" do
reverse_string2("文字列{もじれつ}の反転{はんてん}").should ==
"{んてんは}転反の{つれじも}列字文"
end
it "は[]の対応を保存すること" do
reverse_string2("文字列[もじれつ]の反転[はんてん]").should == "[んてんは]転反の[つれじも]列字文"
end
it "対応の取れている括弧にのみ対応すること" do
reverse_string2("これ(は(対応のとれていない)括弧がある例です。").should == "。すで例るあが弧括(いないてれとの応対)は(れこ"
end
end
end
|
Rubyで書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | def reverse_string2(str)
ca = [['(',')'],['{','}'],['[',']']]
ca.each { |c|
reg = "\\" + c[0] +"([^\\" + c[0] + "\\" + c[1] + "]*)\\" + c[1]
str.gsub!(/#{reg}/) { |x|
r = $1; s = $&
t = ca.clone
t.delete(c)
if r.count(t[0][0]) == r.count(t[0][1]) \
and r.count(t[1][0]) == r.count(t[1][1])
c[1] + r + c[0]
else
s
end
}
}
str.scan(/./).reverse.join
end
res = reverse_string2("対応[の{とれている(さまざまな)括弧}の(例)]です。")
puts res # => "。すで[(例)の{弧括(なまざまさ)るいてれと}の]応対"
res = reverse_string2("これ(は(対応のとれていない)括弧がある例です。")
puts res # => "。すで例るあが弧括(いないてれとの応対)は(れこ"
res = reverse_string2("これ(も{対応の)とれていない}括弧の例です。")
puts res # => "。すで例の弧括}いないてれと)の応対{も(れこ"
|
副作用無しで
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | $KCODE = 'u'
PARENS = {
'(' => ')',
'{' => '}',
'[' => ']',
}
RPARENS = PARENS.invert
def reverseString2_(str, acc, paren)
if str.empty?
[acc, []]
else
ch, *rest = str
if PARENS.keys.include?(ch)
str_, rest_ = reverseString2_(rest, [], ch)
ch_ = if str_.first == ch
PARENS[ch]
else
ch
end
reverseString2_(rest_, [str_, ch_, acc], paren)
elsif paren and RPARENS.keys.include?(ch)
ch_ = if ch == PARENS[paren]
RPARENS[ch]
else
ch
end
[[ch_, acc], rest]
else
reverseString2_(rest, [ch, acc], paren)
end
end
end
def reverseString2(str)
str_ = str.split(//)
reversed, _ = reverseString2_(str_, [], nil)
reversed.flatten.join
end
SAMPLE = [
["文字列(もじれつ)の反転(はんてん)",
"(んてんは)転反の(つれじも)列字文"],
["対応[の{とれている(さまざまな)括弧}の(例)]です。",
"。すで[(例)の{弧括(なまざまさ)るいてれと}の]応対"],
["これ(は(対応のとれていない)括弧がある例です。",
"。すで例るあが弧括(いないてれとの応対)は(れこ"],
["これ(も{対応の)とれていない}括弧の例です。",
"。すで例の弧括}いないてれと)の応対{も(れこ"],
]
def test_reverseString2
SAMPLE.each do |input,expected|
cond = if expected == (result = reverseString2(input)) then :OK else :NG end
puts "reverseString2(#{input.inspect})"
puts " expected: #{expected.inspect}"
print " result: #{result.inspect}"
puts " ... #{cond}"
end
end
if __FILE__ == $0 then test_reverseString2() end
|



nobsun
#3450()
Rating-1/1=-1.00
与えられた文字列を前後反転する関数 reverseString2 を書いてください。 ただし、reverseString2 は単純に文字列を反転するのではなく、括弧の対応 を保存するようにしてください。 以前のお題で作成した単純に与えられた文字列を単純に前後反転したもの返す reverseString では reverseString("文字列(もじれつ)の反転(はんてん)") → ")んてんは(転反の)つれじも(列字文" のように括弧の対応は保存されませんが、reverseString2 では reverseString2("文字列(もじれつ)の反転(はんてん)") → "(んてんは)転反の(つれじも)列字文" のように括弧の対応が保存されます。 括弧文字は、'('と')'、'{'と'}'、'['と']'で、それぞれASCII文字と仮定し てください。 reverseString2("対応[の{とれている(さまざまな)括弧}の(例)]です。") → "。すで[(例)の{弧括(なまざまさ)るいてれと}の]応対" 入力文字列では対応の取れている括弧の内側には対応の取れない括弧文字はな いと解釈してください。たとえば、 reverseString2("これ(は(対応のとれていない)括弧がある例です。") → "。すで例るあが弧括(いないてれとの応対)は(れこ" 次のような場合は対応のとれている括弧はないという解釈になります。 reverseString2("これ(も{対応の)とれていない}括弧の例です") → "。すで例の弧括}いないてれと)の応対{も(れこ" 日本語対応にする場合の文字のエンコーディングは実装側で都合のよいように 仮定してください。日本語対応であることは望ましいですが、必須ではありま せん。 --- このお題はnobsunさんに投稿いただきました。ご協力ありがとうございます。[ reply ]