Anarchy golf 51. Bracket Matching
最短の解答の1.5倍以内には入っているので、今回はそこそこ戦えたかなあという印象。
Bracket Matching
拙作 perl 119byte
$e='[])}>]';for(<>){chop;s/.$e// while/.($e)/&chr(2-(')'eq$1)+ord$&)eq$1;print$_?'failed at: '.(/$e/?$&.$':EOL):yes,$/}
今回初めて知った-l
を使ったところ111byteに縮んだ。
#!perl -pl
$e='[])}>]';s/.$e// while/.($e)/&chr(2-(')'eq$1)+ord$&)eq$1;$_=$_?'failed at: '.(/$e/?$&.$':EOL):yes
shinh氏 ruby1 93byte
#!ruby -pl
$_=/.([]})>](.+)?)/&&7>$1[0]^$&[0]?$2?$`+$2:'yes':"failed at: #{$1||:EOL}"until/e/
テストケース多めで嘘は付けないなあと思っていたが、それでも平然と嘘を複数個仕込んでくるのすごい。
解読
#!/usr/bin/ruby -pl
until /e/
$_ = (/.([]})>](.+)?)/ && (7 > ($1[0] ^ $&[0]))) ?
($2 ?
$` + $2 :
'yes') :
"failed at: #{$1 || :EOL}"
end
#!/usr/bin/ruby -pl
1行目。shebang。-l
はnewlineを上手くやるoption。
Enables automatic line-ending processing, which means to firstly set $\ to the value of $/, and secondly chops every line read using chop!.
until /e/
2行目。$_
にyes
あるいはfailed at:
が入るまでのloop。
$_ = (/.([]})>](.+)?)/ && (7 > ($1[0] ^ $&[0]))) ?
3行目。captureと判定。
/.([]})>](.+)?)/
でもっとも左の閉じ括弧を中心にcaptureし、7 > ($1[0] ^ $&[0]))
で閉じ括弧$1[0]
とその左の括弧$&[0]
の種類が同じかどうかを判定。
以下のような対応より、排他的論理和をとって下位3bit以外が一致していれば種類は同じとなる。よって比較は7
でなくて8
でもよい。
基本的に最も左の括弧をcaptureするので、種類が同じであることの判定だけで十分である。
ただし))
のような入力にyes
を返す。
( |
0b0101000 |
) |
0b0101001 |
[ |
0b1011011 |
] |
0b1011101 |
{ |
0b1111011 |
} |
0b1111101 |
< |
0b0111100 |
> |
0b0111110 |
($2 ?
$` + $2 :
'yes') :
4,5,6行目。balancedな括弧の対があったとき。
その対より後ろになにもなければyes
。
$
には対の手前、
$2には対の後ろが入っている。
三項条件演算子の条件部
$2に関して、
(()のような入力と
()(のような入力には共に
failed at: EOLを返すべきだが、これは前者に
yesを返す。しかし前者のような入力が存在しないため、
$2`のみを判定すればよい。
irori氏 sed 84byte
:
s/^\([[({<]*\)\(()\|\[]\|{}\|<>\)/\1/
t
/^$/cyes
s/[[({<]*/failed at: /
s/ $/ EOL/
sedには以前から興味があったが、遂に手をだす時がきたっぽい。 やはり好きな感じの言語だった。
sed 参考文献
- sed ってなんなの?, 2006-10-10 - 兼雑記
- code golf - Tips for golfing in sed - Programming Puzzles & Code Golf Stack Exchange
- https://www.gnu.org/software/sed/manual/sed.html
- Sed - An Introduction and Tutorial
解読
:
s/^\([[({<]*\)\(()\|\[]\|{}\|<>\)/\1/
t
1,2,3行目。
消去可能な対が存在しかつ最も左側である間、それを消し続けるloop。
/^$/cyes
3行目。
整形すると/^$/ c yes
。行をyes
で置換。
shinh氏 perl 85byte
#!perl -pl
$_=/.([]})>])/&&$+^$&^'3'|0?$`.$'||yes:"failed at: $+".($+?$':EOL)until/e/
解読
#!/usr/bin/perl -pl
until (/e/) {
$_ = /.([]})>])/ && ($+ ^ $& ^ '3' | 0)
? ($` . $') || yes
: "failed at: $+" . ($+ ? $' : EOL)
}
$_ = /.([]})>])/ && ($+ ^ $& ^ '3' | 0)
3行目。
$+
は
The text matched by the last bracket of the last successful search pattern.
であり、この行の$+
は$1
と同じ。今回の| 0
はint
と考えてよい。'3'
は'0'
とかでも動く。
ySas氏 perl 82byte
#!perl -pl
$_=3x/.([]})>])/^$+^$&|0?$`.$'||yes:"failed at: $+".($+?$':EOL)until/e/
解読
整形。
#!/usr/bin/perl -pl
until (/e/) {
$_ = (3 x /.([]})>])/) ^ $+ ^ $& | 0
? $` . $' || yes
: "failed at: $+" . ($+ ? $' : EOL)
}
変更点は3行目の
$_ = (3 x /.([]})>])/) ^ $+ ^ $& | 0
x
演算子は左辺を文字列として右辺回繰り返したものを作るが、これにより/.../ ? '3' : ''
を実現している。