丁稚な日々 - apprenticeship days

Rubyで遊んだ日々の記録。あくまで著者視点の私的な記録なので、正確さを求めないように。
Rubyと関係ない話題にはその旨注記しているはず。なので、一見関係無いように見える話題もどこかで関係あるのかもしれません。または、注記の書き忘れかもしれません...

[直前] [最新] [直後] [Top]

Dec.11,2015 (Fri)

Revision: 1.4 (Dec.11,2015 20:16)

TRICK2015で審査員賞を頂きました

_ 表題の通りです。ありがとうございました。

_ 受賞プログラムはこんなの。

lines = Array.new
open(__FILE__) do |fl|
  fl.each_line{|line|
    lines.push(line)
  }
  m=15+15
  n=62
  $e = lines.
   map do|ln|
    sz = ln.size
;
    (sz<5?sz+m:sz+n).
     chr().swapcase
  end.join
  $e
  eval "#$e"
end

_ さて、今回は、「見た目はふつーのRubyスクリプト、なんだけど」を自分なりのテーマとしました。
というのは、TRICKには見た目でインパクトのあるプログラムが多数登場することはわかっていたので、その辺のセンスがないぼくとしては逆張りしたほうがいいかな、と。
その上で、幾つか温めていたアイデアのうち、プログラム自体をデータとして利用する、という手法を使うことにしました。
長いプログラムを書くのは面倒だし、TRICK自体もあまり長いのは推奨されない(守るかどうかは別として、4096バイトまで、という規定もある)ので、今回は単純に短い文字列を出力するだけのプログラムにすることにしました。
なので、最終的に実行される真のプログラムは、puts"..."となります。
で、このプログラム(最終プログラム)をどう元のプログラム(元プログラム)に埋め込むか、なんですが、今回は単純にASCIIコードとして埋め込むことにしました。
具体的には、最終プログラムの各1文字を元プログラムの各行に対応させ、その長さを利用するようにしています。

_ ただ、単純にASCIIコード分の長さの行を書くと長いので(例えばpのASCIIコードは112)、適当に変換をかましてもうちょっと実用的な数値になるようにしています。
この変換についてですが、endを元プログラム末尾に置くことは決めていたので、最後の行の長さはendの3文字と改行文字を合わせて4文字となります。
最終プログラムの末尾の文字は"ですので、これが4となる、という基準で変換をかけています。
具体的には、"のASCIIコードは34なので、単に30を引いているわけです。
上に上げた元プログラムの6行目にm=15+15とありますが、これがそれですね。
また、このままだと、先頭のpが112-30で82となり、最初の行がいきなり81文字+改行文字という長いものになってしまいます。
1行の長さが80文字を超えるのはぼくの美意識に反したので、String#swapcaseを使って大文字と小文字を入れ替えることによって、必要な長さを短くするようにしています。

_ で、以上を踏まえて適当に行の長さを調整しながら実行プログラムを書き下ろしていったわけですが、この方法だと、途中に現れる空白文字(スペース)のASCIIコードが32であるため、1文字+改行文字という行を唐突に仕込む必要があることが判明しました。
空白文字は別の文字(,とか)に変えるか、とか、変換式を変えるか、とかいろいろ考えたのですが、ま、謎の行が一つくらい入ってた方が「あれ?」と思わせる効果があるかもな、とか考えて、敢えてそのまま残すことにしました。
どっちかというと、その次の2行が怪しい途中改行を含む変なインデントになってるので、そっちをどうにかしたかったのですが、うまく処理できないままで終わってしまい、「なかだるみ」というご指摘を受けることとなってしまいました。
あと$eしかない行もひどいですね。

_ あと、実はtrunkでしか実行できないコードになっていると指摘を受けたのですが、今確認すると確かにそうですね。すみませんすみません。
投稿直前までは別のコードだったので通ったのですが、最後にぐにょぐにょ微調整した結果がまずかったようです。

_ そんなわけで、いろいろ不備の多い作品となってしまいましたが、意外にも賞をいただくことができました。
審査員の皆様、どうもありがとうございました。

_ (追記)
書き忘れたことが2点ありました。

_ まず、大文字小文字変換をしてもまだアルファベットは1行の長さとしては長いので(今回登場する最短のeでも39になる)、アルファベットの場合は大文字小文字変換した上で30ではなく62を引いています。これでeは7文字(改行文字含む)で表現できるようになりました。
具体的にはまさにそのn=62の行がeに該当します。

_ また、当初はDATAを使ってスクリプトを読もうと考えていたのですが、DATA__END__のないスクリプトでは定義されず、さりとてこんな長い識別子をコードの末尾につけると、必然的に他の行も何文字かずつ長くする必要が発生するので、今回はDATAの使用は諦めました。


被捕捉アンテナ類
[Ant] [Antenna-Julia] [Rabbit's Antenna] [Ruby hotlinks]