No. 410 「出会い」ショートコード解説
はじめに
yukicoder コンテストで出題された問題 No. 410 「出会い」のショートコード(2016年8月13日現在)の解説です。
問題ページ: http://yukicoder.me/problems/no/410
ショートコード: http://yukicoder.me/submissions/110735
問題の概要
入力:
A B C D
が与えられる(A,B,C,Dは整数)。(abs(A-C)+abs(B-D))*0.5 の値を出力せよ。
私の答案
tr - _|dc -e?sx?sy-d*vlxly-d*v+.5*p
35 bytes です。言語は Bash です。 tr と dc を呼び出しています。 dc は先日 yuki さんにお願いして導入してもらい、使えるようになりました。
dc とは?
「逆ポーランド形式の無限精度の計算が行える卓上計算機」だそうです(出典: http://kazmax.zpp.jp/cmd/d/dc.1.html)。今日では、 Ruby や Python で精度を気にすることなく整数演算ができますが、かつて Perl の時代にはそういうわけにはいきませんでした。なまじっか Perl が使えてしまうせいで Ruby や Python を覚える気になれない私は、 dc にはまだまだお世話になっています。
コードの解説
まず、 tr - _
で、入力に含まれる -
(マイナス)を全て _
(アンダースコア)に変換しています。これは、 dc の入力においては -
(マイナス)は二項演算子であり、負号は _
(アンダースコア)で表すことになっているからです。(一方、出力においては負号は -
(マイナス)です。つまり、 dc は自分が出力する数値を解釈できないという謎仕様です。)
次に、負号を変換した入力を dc に渡しています。 -e は perl や ruby の -e と同じで、スクリプトの直接指定です。そのスクリプトをトークンに分解すると、次のようになります。
? sx ? sy - d * v lx ly - d * v + .5 * p
?
は、入力を1行読んで実行する、です。最初の ?
で入力の A B が読まれ、次の ?
で C D が読まれることになります。読まれた値は、スタックにプッシュされます。
sx
は、スタックをポップして変数 x に格納する、です。最初の ?
の実行後のスタックは A B ですので、 sx
で x には B が入り、スタックは A だけになります。同様に、 sy
で y には D が入り、スタックは A C になります。
- d * v
という一連の命令が2回出てきます。 d
はスタック先頭の値の複製、 v
は(非負の)平方根です。つまり、スタック先頭の2つの値の差を2乗してその平方根を求めていますので、差の絶対値が得られます。
lx ly
は、変数 x と y の値(つまり B と D )をスタックにプッシュします。
+ .5 *
で、これらを足して 0.5 倍しています。 .5 *
は 2 /
のほうが短そうですが、デフォルトで商が整数になってしまうので、ここではうまくいきません。
p
で結果を出力しています。
おわりに
解説の配信のとき、説明が必要っぽい雰囲気だと思ったので、書いてみましたが、いかがだったでしょうか。全く需要がない気もしますが、果たして最後まで読んでくれた人はいるのでしょうか。