Macr055でクリスマスの詩

次の 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

Macr055でアッカーマン関数他

次の http://parametron.blogspot.jp/2015/02/christopher-stracheygpm_22.html の記事に移って、アッカーマン関数他。

アッカーマン関数

{m55_define|1+|`{1|2|3|4|5|6|7|8|9|10|
  {m55_define|1|$$$1}}'}{m55_dnl}
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|a|`{$1|
  {m55_define|$1|`{$2|
    {m55_define|$2|`{a|{1-|$1}|{a|$1|{1-|$2}}}'}
    {m55_define|0|`{a|{1-|$1}|1}'}}'}
  {m55_define|0|`{1+|$2}'}}'}{m55_dnl}
{a|0|0}, {a|0|1}, {a|0|2}, {a|0|3}, {a|0|4}, {a|0|5}, {a|0|6}, {a|0|7}, {a|0|8}
{a|1|0}, {a|1|1}, {a|1|2}, {a|1|3}, {a|1|4}, {a|1|5}, {a|1|6}, {a|1|7}
{a|2|0}, {a|2|1}, {a|2|2}, {a|2|3}
{a|3|0}

カタラン三角形

{m55_define|1+|`{1|2|3|4|5|6|7|8|9|10|
  {m55_define|1|$$$1}}'}{m55_dnl}
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|+|`{$1|
  {m55_define|$1|`{1+|{+|{1-|$1}|$2}}'}
  {m55_define|0|$2}}'}{m55_dnl}
{m55_define|lt|`{$1|
  {m55_define|$1|`{p|$1|$2|{m55_define|p|`{lt|{1-|$1}|$2}'}}'}
  {m55_define|-1|t}
  {m55_define|$2|f}}'}{m55_dnl}
{m55_define|or|`{$1|
  {m55_define|$1|t}
  {m55_define|f|$2}}'}{m55_dnl}
{m55_define|c|`{$1$2|
  {m55_define|$1$2|`{{or|{lt|$1|0}|{lt|$2|$1}}|
    {m55_define|t|0}
    {m55_define|f|`{+|{c|$1|{1-|$2}}|{c|{1-|$1}|$2}}'}}'}
  {m55_define|00|1}}'}{m55_dnl}
{c|0|0}
{c|0|1}, {c|1|1}
{c|0|2}, {c|1|2}, {c|2|2}
{c|0|3}, {c|1|3}, {c|2|3}, {c|3|3}
{c|0|4}, {c|1|4}, {c|2|4}
{c|0|5}, {c|1|5}
{c|0|6}, {c|1|6}
{c|0|7}, {c|1|7}
{c|0|8}, {c|1|8}
{c|0|9}, {c|1|9}

論理演算

縦棒をマクロの記法で使っている都合で、記号ではなく名前で定義。XORについては先生のブログにある定義と違っていて、直截な定義にしてある。

{m55_define|and|`{$1|
  {m55_define|$1|f}
  {m55_define|t|$2}}'}{m55_dnl}
{m55_define|or|`{$1|
  {m55_define|$1|t}
  {m55_define|f|$2}}'}{m55_dnl}
{m55_define|not|`{$1|
  {m55_define|t|f}
  {m55_define|f|t}}'}{m55_dnl}
{m55_define|xor|`{$1|
  {m55_define|$1|t}
  {m55_define|$2|f}}'}{m55_dnl}
{m55_define|maj|`{or|{or|{and|$1|$2}|{and|$2|$3}}|{and|$3|$1}}'}{m55_dnl}
{maj|f|f|f}, {maj|f|f|t}, {maj|f|t|f}, {maj|f|t|t}
{maj|t|f|f}, {maj|t|f|t}, {maj|t|t|f}, {maj|t|t|t}

ヒルベルト曲線

SVGのpath要素のd属性を生成する。SVGのhコマンドとvコマンドを使って表現を圧縮している。SVGは左上原点だがそれの調整をしてないので、先生のPostScriptによる生成結果とは上下逆になる。

{m55_define|1+|`{1|2|3|4|5|6|7|8|9|10|
  {m55_define|1|$$$1}}'}{m55_dnl}
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|+|`{$1|
  {m55_define|$1|`{1+|{+|{1-|$1}|$2}}'}
  {m55_define|0|$2}}'}{m55_dnl}
{m55_define|-|`{$2|
  {m55_define|$2|`{-|{1-|$1}|{1-|$2}}'}
  {m55_define|0|$1}}'}{m55_dnl}
{m55_define|lt|`{$1|
  {m55_define|$1|`{p|$1|$2|
    {m55_define|p|`{lt|{1-|$1}|$2}'}}'}
  {m55_define|-1|t}
  {m55_define|$2|f}}'}{m55_dnl}
{m55_define|r|`{{lt|$1|$2}|
  {m55_define|t|$1}
  {m55_define|f|`{r|{-|$1|$2}|$2}'}}'}{m55_dnl}
{m55_define|^|`{r|{1+|$1}|4}'}{m55_dnl}
{m55_define|_|`{r|{1-|{+|4|$1}}|4}'}{m55_dnl}
{m55_define|f|`{$1|
  {m55_define|0|h20}
  {m55_define|1|v20}
  {m55_define|2|h-20}
  {m55_define|3|v-20}}{$2|
  {m55_define|$2|
}
  {m55_define|1}}'}{m55_dnl}
{m55_define|p|`{$1|
  {m55_define|$1|`{q|{1-|$1}|{^|$2}}{f|{^|$2}|$1}{p|{1-|$1}|$2}{f|$2|$1}{p|{1-|$1}|$2}{f|{_|$2}|$1}{q|{1-|$1}|{_|$2}}'}
  {m55_define|0}}'}{m55_dnl}
{m55_define|q|`{$1|
  {m55_define|$1|`{p|{1-|$1}|{_|$2}}{f|{_|$2}|$1}{q|{1-|$1}|$2}{f|$2|$1}{q|{1-|$1}|$2}{f|{^|$2}|$1}{p|{1-|$1}|{^|$2}}'}
  {m55_define|0}}'}{m55_dnl}
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240">
  <g fill="none">
    <g stroke="#000">
      <path d="m50 50
{p|3|0}{m55_dnl}
"/>
    </g>
  </g>
</svg>

Macr055で二進化他

次の http://parametron.blogspot.jp/2015/02/christopher-stracheygpm_8.html の記事に移って、二進化他。

二進化

{m55_define|1+|`{1|2|3|4|5|6|7|8|9|10|
  {m55_define|1|$$$1}}'}{m55_dnl}
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|lt|`{$1|
  {m55_define|$1|`{p|$1|$2|
    {m55_define|p|`{lt|{1-|$1}|$2}'}}'}
    {m55_define|-1|t}
    {m55_define|$2|f}}'}{m55_dnl}
{m55_define|b|`{{lt|$1|2}|
  {m55_define|t|`{$2|
    {m55_define|$2|`{b|$2|0}$1'}
    {m55_define|0|$1}}'}
  {m55_define|f|`{b|{1-|{1-|$1}}|{1+|$2}}'}}'}{m55_dnl}
{b|0|0}, {b|1|0}, {b|2|0}, {b|3|0}, {b|4|0}
{b|5|0}, {b|6|0}, {b|7|0}, {b|8|0}, {b|9|0}

2項係数

(現状の)M55ではローカル定義のマクロでは再帰的に展開できないため(最初の展開が終わった時点でローカル定義が消えてしまうため)bb というマクロはトップレベルで定義している。

{m55_define|1+|`{1|2|3|4|5|6|7|8|9|10|
  {m55_define|1|$$$1}}'}{m55_dnl}
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|+|`{$1|
  {m55_define|$1|`{1+|{+|{1-|$1}|$2}}'}
  {m55_define|0|$2}}'}{m55_dnl}
{m55_define|b|`{$2|
  {m55_define|$2|`{+|{b|{1-|$1}|$2}|{b|{1-|$1}|{1-|$2}}}'}
  {m55_define|0|1}
  {m55_define|$1|1}}'}{m55_dnl}
{m55_define|binom|`{bb|$1|0}'}{m55_dnl}
{m55_define|bb|`{$2|
  {m55_define|$2|`{b|$1|$2}, {bb|$1|{1+|$2}}'}
  {m55_define|$1|1}}'}{m55_dnl}
#{b|4|0}, {b|4|1}, {b|4|2}, {b|4|3}, {b|4|4}
{binom|0}
{binom|1}
{binom|2}
{binom|3}
{binom|4}
{binom|5}

素数テスト

{m55_define|1+|`{1|2|3|4|5|6|7|8|9|10|
  {m55_define|1|$$$1}}'}{m55_dnl}
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|-|`{$2|
  {m55_define|$2|`{-|{1-|$1}|{1-|$2}}'}
  {m55_define|0|$1}}'}{m55_dnl}
{m55_define|lt|`{$1|
  {m55_define|$1|`{p|$1|$2|
    {m55_define|p|`{lt|{1-|$1}|$2}'}}'}
  {m55_define|-1|t}
  {m55_define|$2|f}}'}{m55_dnl}
{m55_define|r|`{{lt|$1|$2}|
  {m55_define|t|$1}
  {m55_define|f|`{r|{-|$1|$2}|$2}'}}'}{m55_dnl}
{m55_define|p?|`{p|2|$1}'}{m55_dnl}
{m55_define|p|`{$1|
  {m55_define|$1|`{{r|$2|$1}|
    {m55_define|{r|$2|$1}|`{p|{1+|$1}|$2}'}
    {m55_define|0|f}}'}
  {m55_define|$2|t}}'}{m55_dnl}
{p?|2}
{p?|3}
{p?|4}
{p?|5}
{p?|6}
{p?|7}
{p?|8}
{p?|9}

tarai

途中経過を確認するために、マクロ展開するのではなく出力に直接書き出す特殊マクロ m55_write をM55に追加した。tarai 8 4 0 にするとすぐには待っていられないぐらい時間が掛かるので 6 3 0 としている。

{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|lt|`{$1|
  {m55_define|$1|`{p|$1|$2|
    {m55_define|p|`{lt|{1-|$1}|$2}'}}'}
  {m55_define|-1|t}
  {m55_define|$2|f}}'}{m55_dnl}
{m55_define|tarai|`{m55_write|tarai $1 $2 $3
}{{lt|$2|$1}|
  {m55_define|f|$2}
  {m55_define|t|`{tarai|{tarai|{1-|$1}|$2|$3}|{tarai|{1-|$2}|$3|$1}|{tarai|{1-|$3}|$1|$2}}'}}'}{m55_dnl}
{tarai|6|3|0}

不要な空白類をstripする手段は現状無いため詰め詰めに書いているが、もし対処するとしたら、どういう仕様の特殊マクロが良いだろうか。

Macr055でフィボナッチ他

次の http://parametron.blogspot.jp/2015/02/christopher-stracheygpm.html の記事に移って、フィボナッチ他。

フィボナッチ数

{m55_define|1+|`{1|2|3|4|5|6|7|8|9|10|
  {m55_define|1|$$$1}}'}{m55_dnl}
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|+|`{$1|
  {m55_define|$1|`{1+|{+|{1-|$1}|$2}}'}
  {m55_define|0|$2}}'}{m55_dnl}
{m55_define|fib|`{$1|
  {m55_define|$1|`{+|{fib|{1-|$1}}|{fib|{1-|{1-|$1}}}}'}
  {m55_define|1|1}
  {m55_define|0|0}}'}{m55_dnl}
{fib|0}, {fib|1}, {fib|2}, {fib|3}, {fib|4}, {fib|5}, {fib|6}

階乗

{m55_define|1+|`{1|2|3|4|5|6|7|8|9|10|
  {m55_define|1|$$$1}}'}{m55_dnl}
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|+|`{$1|
  {m55_define|$1|`{1+|{+|{1-|$1}|$2}}'}
  {m55_define|0|$2}}'}{m55_dnl}
{m55_define|*|`{$1|
  {m55_define|$1|`{+|{*|{1-|$1}|$2}|$2}'}
  {m55_define|0|0}}'}{m55_dnl}
{m55_define|!|`{$1|
  {m55_define|$1|`{*|$1|{!|{1-|$1}}}'}
  {m55_define|0|1}}'}{m55_dnl}
{!|0}
{!|1}
{!|2}
{!|3}

中央値、というか3要素の「場合分けによるソート」までですが、{m55_define|snd|$2} というようなマクロを使って2番目を取り出すようにするのはトリビアルな改造でしょう。

{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|lt|`{$1|
  {m55_define|$1|`{p|$1|$2|
    {m55_define|p|`{lt|{1-|$1}|$2}'}}'}
  {m55_define|-1|t}
  {m55_define|$2|f}}'}{m55_dnl}
{m55_define|med|`{{lt|$2|$1}|
  {m55_define|t|`{{lt|$3|$1}|
    {m55_define|t|`{{lt|$3|$2}|
      {m55_define|t|$3,$2,$1}
      {m55_define|f|$2,$3,$1}}'}
    {m55_define|f|$2,$1,$3}}'}
  {m55_define|f|`{{lt|$3|$2}|
    {m55_define|t|`{{lt|$3|$1}|
      {m55_define|t|$3,$1,$2}
      {m55_define|f|$1,$3,$2}}'}
    {m55_define|f|$1,$2,$3}}'}}'}{m55_dnl}
{med|0|0|0}
{med|0|0|1}
{med|0|0|2}
{med|0|1|0}
{med|0|1|1}
{med|0|1|2}
{med|0|2|0}
{med|0|2|1}
{med|0|2|2}
{med|1|0|0}
{med|1|0|1}
{med|1|0|2}
{med|1|1|0}
{med|1|1|1}
{med|1|1|2}
{med|1|2|0}
{med|1|2|1}
{med|1|2|2}
{med|2|0|0}
{med|2|0|1}
{med|2|0|2}
{med|2|1|0}
{med|2|1|1}
{med|2|1|2}
{med|2|2|0}
{med|2|2|1}
{med|2|2|2}

GCD

{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|-|`{$2|
  {m55_define|$2|`{-|{1-|$1}|{1-|$2}}'}
  {m55_define|0|$1}}'}{m55_dnl}
{m55_define|lt|`{$1|
  {m55_define|$1|`{p|$1|$2|
    {m55_define|p|`{lt|{1-|$1}|$2}'}}'}
  {m55_define|-1|t}
  {m55_define|$2|f}}'}{m55_dnl}
{m55_define|gcd|`{$2|
  {m55_define|$2|`{{lt|$1|$2}|
    {m55_define|f|`{gcd|{-|$1|$2}|$2}'}
    {m55_define|t|`{gcd|$1|{-|$2|$1}}'}}'}
  {m55_define|$1|$1}}'}{m55_dnl}
{gcd|2|4}, {gcd|5|3}, {gcd|6|3}

Macr055でハノイの塔

引き続いて http://parametron.blogspot.jp/2015/01/cristopher-stracheygpm.html にある「ハノイの塔」。(ハノイの塔は高機能テキストマクロプロセッサの標準課題らしく m4 にも hanoi.m4 というテストサンプルが付いています)

{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|hanoi|`{$4|
  {m55_define|$4|`{hanoi|$1|$3|$2|{1-|$4}}$1 ==> $3
{hanoi|$2|$1|$3|{1-|$4}}'}
  {m55_define|0|$1 ==> $3
}}'}{m55_dnl}
{hanoi|a|b|c|0}{m55_dnl}
--
{hanoi|a|b|c|1}{m55_dnl}
--
{hanoi|a|b|c|2}{m55_dnl}
--
{hanoi|a|b|c|3}{m55_dnl}
--
{hanoi|a|b|c|4}{m55_dnl}

Macr055で基本演算

拙作のテキストベースマクロプロセッサMacr055( https://github.com/metanest/macr055 )で、和田先生のブログにあるマクロの例題( http://parametron.blogspot.jp/search/label/Christopher StracheyのGPM )をやってみたので、情報共有などのため記録として載せます。

まず http://parametron.blogspot.jp/2015/01/cristopher-stracheygpm.html にある「基本演算」から。

{m55_define|1+|`{1|2|3|4|5|6|7|8|9|10|
  {m55_define|1|$$$1}}'}{m55_dnl}
{m55_define|1-|`{-1|0|1|2|3|4|5|6|7|8|
  {m55_define|-1|$$$1}}'}{m55_dnl}
{m55_define|+|`{$1|
  {m55_define|$1|`{1+|{+|{1-|$1}|$2}}'}
  {m55_define|0|$2}}'}{m55_dnl}
{m55_define|-|`{$2|
  {m55_define|$2|`{-|{1-|$1}|{1-|$2}}'}
  {m55_define|0|$1}}'}{m55_dnl}
{m55_define|*|`{$1|
  {m55_define|$1|`{+|{*|{1-|$1}|$2}|$2}'}
  {m55_define|0|0}}'}{m55_dnl}
{m55_define|lt|`{$1|
  {m55_define|$1|`{p|$1|$2|{m55_define|p|`{lt|{1-|$1}|$2}'}}'}
  {m55_define|-1|t}
  {m55_define|$2|f}}'}{m55_dnl}
{m55_define|r|`{{lt|$1|$2}|
  {m55_define|t|$1}
  {m55_define|f|`{r|{-|$1|$2}|$2}'}}'}{m55_dnl}

本家GPM、あるいは和田先生の手元の実装と、m55ではクウォートの掛かりかたが違っていて、m55ではm4と同様に、どれだけ深いクウォートの中であっても変数の $1 などは置換されるため、この程度のマクロの場合は、一部で$$$のように多重エスケープが必要になるものの、全体的には記述が単純になる傾向があるようです(もっと後で出てくる複雑なマクロになると、どちらが有利か、だいぶわからなくなってきます)。

『アポロ計画でプログラムコードを開発した女性エンジニア「マーガレット・ハミルトン」がソースコードの隣に立っている写真』について

「コーディング教育」とか言われるようになってきたためか、最近時々バズるこの話題について。

マーガレット・ハミルトンさんが、グレース・ホッパーさんやフラン・アレンさんとともに、偉大なコンピュータ黎明期のパイオニアのお一人であることは確かですし、この記事は、おとしめる意図ではありません。しかし、話題になっている写真にはいくつか疑問点等があるので、それらについてメモとして残します。

この話題がネット上で見られるようになったのはいつからか?

threefingeredfox 氏のブログ Three Fingered Fox の、こちらの Margaret Hamilton, lead software engineer, Project Apollo | Three Fingered Fox ブログエントリ、およびそれのミラーである、Medium のこちら Margaret Hamilton, lead software engineer, Project Apollo — Medium の記事が初出のようです(2014年12月上旬。もしこれより古く、この写真について話題になっていた場がありましたら、お教えいただければ幸いです)。

また、このエントリを受けて取材をされ、同月末に公開された、こちら Margaret Hamilton, the Engineer Who Took the Apollo to the Moon — Medium の記事により、この写真は Here, Margaret is shown standing beside listings of the software developed by the team she was in charge of, the LM and CM on-board flight software team. である、とオーソライズされたという感じ、になっています。

この写真のソースと、ネットに現れるまでの経緯はどうか?

前述の取材中に Taken by the Draper Lab photographer in 1969 (during Apollo 11). とあるので、ソースはそういう(ドレイパー研究所の写真家が撮ったもの。当時はMITの関連組織ということになるはず)ことになります。

しかしその後、どういうルートでネットに出たのかはよくわかりません。threefingeredfox 氏のブログエントリには単に I just ran across on the internets. としかありません。ウィキメディアコモンズhttps://commons.wikimedia.org/wiki/File:Margaret_Hamilton.gif ではNASAの画像として自由であるというカテゴリ付けがされています。しかし、NASAの画像サービスなどをあたってみても、関連する写真(アポロの操縦システムの操作を検討しているっぽい写真や、後年にパソコンの前に座っている写真)は出てきますが、この写真は見つけられていません(やはりこちらも見つけられた方がおられましたら、ご連絡ください)。

この紙の山が全て、Apollo Guidance Computer (AGC) のソースコードなのか?

詳細は水城徹さんによる、『宇宙の傑作機 No.10 アポロ誘導コンピュータ』にありますが、AGCは1ワードが16ビットで、RAMが2キビワード、ROMが4万ワード弱、というコンピュータでした(ひところは「アポロはファミコンと同程度のコンピュータで月に行った」とバズったものでしたが、そういえば最近あまり耳にしなくなった気もします)。

もちろん時代が20年も後の、6502(ファミコンの石。正確にはファミコンはそれのカスタム版を搭載している)のように整理されたアーキテクチャではなく、また開発環境も当時のマシンだったわけですから、その開発工数は、たとえば http://web.mit.edu/aeroastro/news/magazine/aeroastro6/mit-apollo.html には 1400 man-years というおそろしい数字が挙げられています。そのチーフというのが猛烈な仕事であっただろうことは想像を絶します。

前述のように、ROMが4万ワード弱のコンピュータという定量的事実はあります。しかし、アポロ宇宙船が月に行くのを支えたコンピュータはAGCだけでもありませんし、ソースコード以外にも、AGCの設計・運用のための資料は膨大であることは想像されます(『電子立国』において、シャープのエンジニアがロックウェル流の設計手法を伝授されるくだりで、現代で言う論理シミュレータのようなものが60年代にはもうあったというような話があったと思います)。

従ってこの写真について、アポロ宇宙船、あるいは特にAGC関連のプリントアウトや書類類であろうというのは確かとしてよいと思いますが、この写真の書類の山を、「ソースコードを頭から尻尾まで一通り出力したもの」と解するのは問題があり(たとえば、当時はフルスクリーンエディタなんてものは夢のまた夢でしたから、それだけハードコピーを取ることも頻繁だったはずです)、ましてや「1人で書いたもの」というような誤解をミスリードするような文言はダメということになるかと思います。