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 参考文献

解読

:
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と同じ。今回の| 0intと考えてよい。'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' : ''を実現している。