次の http://parametron.blogspot.jp/2015/03/christopher-stracheygpm.html の記事に移って、クリスマスの詩。
"$:" が10番目の引数に置換されるようにM55を改造。文字と文字コードの相互変換は chr と ord という名前の関数とするのが定番ですが、GNU awk のマニュアルにサンプルがあったので https://www.gnu.org/software/gawk/manual/html_node/Ordinal-Functions.html それを参考に実装。
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|9|:| {m55_define|-1|$$$1}}'}{m55_dnl} {m55_define|getn|`{11th|10th|9th|8th|7th|6th|5th|4th|3rd|2nd|1st| {m55_define|11th|$$$1}}'}{m55_dnl} {m55_define|gets|`{11 Pipers |10 Lords |9 Ladies |8 Maids |7 Swans |6 Geese |5 Rings |4 Birds |3 Hens |2 Turtle Doves |a Partridge |{m55_define|11 Pipers |$$$1}}'}{m55_dnl} {m55_define|song|`{$1| {m55_define|$1|`On the {getn|$1} day {gets|$1}$2 {song|{1-|$1}|{gets|$1}$2}'} {m55_define|-1|`On the 12th day 12 Drummers '$2}}'}{m55_dnl} {song|:}{m55_dnl}
色相環はマクロでやるのがそんなに面白そうでもなかったのでRubyで書いた(円の生成法に http://parametron.blogspot.jp/2008/07/blog-post_24.html のものを使っているので、楕円になっている)。
include Math NUM_OF_DIV = 6 def get_rgb sel, i case sel when "f" then 255 when "d" then ((255*(NUM_OF_DIV-i)).to_f / NUM_OF_DIV).round when "0" then 0 when "u" then ((255*i).to_f / NUM_OF_DIV).round else raise end end magic = "fd00uffd00uffd00uf" outer_radius = 125 inner_radius = 25 print <<EOS <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"> <g style="stroke-width:0.1"> EOS eps = PI / (6 * NUM_OF_DIV) p1 = nil old_x, old_y = 1.0, 0.0 (0 ... 6).each {|col| (0 ... NUM_OF_DIV).each {|i| rgb = [get_rgb(magic[col], i), get_rgb(magic[col+4], i), get_rgb(magic[col+2], i)] rgb.map! {|a| "%02x" % [a]} rgb = rgb.join rgb[0, 0] = "#" x1 = old_x - eps * old_y y1 = old_y + eps * x1 unless p1 then p1 = [x1, y1] old_x, old_y = x1, y1 else print %! <g style="color:#{rgb}">\n! x2 = x1 - eps * y1 y2 = y1 + eps * x2 x_1, y_1 = [old_x, old_y].map{|a| 128 + outer_radius * a } x_2, y_2 = [x1, y1].map{|a| 128 + outer_radius * a } x_3, y_3 = [x2, y2].map{|a| 128 + outer_radius * a } x_4, y_4 = [x2, y2].map{|a| 128 + inner_radius * a } x_5, y_5 = [x1, y1].map{|a| 128 + inner_radius * a } x_6, y_6 = [old_x, old_y].map{|a| 128 + inner_radius * a } print %! <path style="stroke:currentColor;fill:currentColor" d="M#{x_1} #{y_1}L#{x_2} #{y_2} #{x_3} #{y_3} #{x_4} #{y_4} #{x_5} #{y_5} #{x_6} #{y_6}"/>\n! print %! </g>\n! old_x, old_y = x2, y2 end } } print %! <g style="color:#ff0000">\n! x_1, y_1 = [old_x, old_y].map{|a| 128 + outer_radius * a } x_2, y_2 = [1.0, 0.0].map{|a| 128 + outer_radius * a } x_3, y_3 = [p1[0], p1[1]].map{|a| 128 + outer_radius * a } x_4, y_4 = [p1[0], p1[1]].map{|a| 128 + inner_radius * a } x_5, y_5 = [1.0, 0.0].map{|a| 128 + inner_radius * a } x_6, y_6 = [old_x, old_y].map{|a| 128 + inner_radius * a } print %! <path style="stroke:currentColor;fill:currentColor" d="M#{x_1} #{y_1}L#{x_2} #{y_2} #{x_3} #{y_3} #{x_4} #{y_4} #{x_5} #{y_5} #{x_6} #{y_6}"/>\n! print %! </g>\n! if false then epsiron = 2.0 * PI / NUM_OF_DIV old_x = 1.0 old_y = 0.0 (0 ... NUM_OF_DIV).each { new_x = old_x - epsiron * old_y new_y = old_y + epsiron * new_x print %! <line x1="#{old_x*100.0}" y1="#{old_y*100.0}" x2="#{new_x*100.0}" y2="#{new_y*100.0}"/>\n! old_x = new_x old_y = new_y } end print <<EOS </g> </svg> EOS