Home > Archives > 2010年07月

2010年07月

改行のみは空だった

毎日朝から wake golf.納豆と味噌汁が美味い.でも流石に納豆ネコまんまはやりたくない.

そして,改行のみは空パターンにマッチ可能であったことに今更ながら気づいた.

-:\n \n
:"Hello"

の出力は HelloHello になる.改行のみは空文字列だと思いたいことが時々あるので,これは便利かもしれない.first match なマッチング戦略なので,改行のみを空と思いたくなければその上にパターン用意しとけばいいし.

wake で golf して wake up な

起きて朝飯食いながら wake golf して楽しく頭の体操.

最近気づいた wake golf で大事なこと:投げっぱなしジャーマン.

Haskell golf でも同じなのだけど,必要な出力が終わったらエラーで停止しても問題ないので,最後のエラー回避のためのコードは必要ない.エラーは投げっぱなしで.例えば,最後には空文字列になってしまうようなものはエラー回避に":"だけの行が必要となるが,こんなのは書くだけ無駄であると.

それに連動して,エラーで停止する前に必要な出力を負えなければならないので,string literal をアクションの前に置くようなスタイルにしておかないと投げっぱなしジャーマンできない(今のインタプリタがアクション部分を前方から処理してるから&多分make的にそういうセマンティクスだからだけど).

ということで,投げっぱなし Smileys Triangle.

:":\n:-":-)
.{1,65}:"\n$&"$&))

そして,sed の y コマンドのありがたみを感じる今日この頃.y のおかげで物事の大小比較が非常にコンパクトに書けていた気がする.今のところ wake で大小比較をコンパクトに実現する方法が思いついていないので,その辺をもっと修業しないとなかなかソート系に手が出ない.頑張ろう.

wake で(ry その2

wake がバージョンアップしてアクション部分でのエスケープが許可された.これは空白とか改行と入れるのに有効かなと.

ということで,ゴルフしたコードを書き換えた.ついでに,PCRE(ないしperl)の正規表現で^と$が文字列中のnewlineにどこでもマッチできることに気がついたので,それ関連で\nを置換しまくる.

char pyramid.前のは無駄ばかりだったけどだいぶすっきりした感じ.

:$<
([^ ]+)([^ ].*):$1\ $2
( *)\S(.*):$1$2\  "$&\n"
 +:

swap lines.アクションのエスケープと正規表現の^とで縮めた結果,murky-satyrさんに追いついた.

-:$<\n
(.+?)(^.+?\n)(.*):"$2$1"$3

追いつく前のは\nを付けるの面倒だなぁとかやってごちゃごちゃと:

-:$<
(.*?\n)(.*?)(\n|\Z)(.*):"$2\n$1"$4

あとはもう少し複雑そうなのをということで Half Sierpinski をば.なんとなく同じパターンがたくさん現れるので(下のl関数とu関数)… そろそろ foldr とか map とかの高階関数が欲しくなってくるかなぁと思いつつ,実現すんのは(要素への区切り方というかリストの表現とかが結局)面倒だなぁとか思ってみたり.

-:$(x)
x:"#~"
c(.*?) *~(.*):"$1\n"c$2
.* {16}.:c$&
u(.*?)~(.*):"$1$(U$1)~"u$2
l(.*?)~(.*):"$1$1~"l$2
U.(.*):" "U$1
[A-z]*:
.+:$(l$&)$(u$&)

wake で(ry

eval を使うようにしてみた.

char pyramid.eval 使って空白入れられるのね.

:$<
~:" "
([^ ]+)([^ ].*):$1$(~)$2
(.*)%:"$1\n"
( *)[^ ](.*):$1$2$(~) $&%
 +:

palindromize.eval を使うと評価位置を限定できるのでプログラムがすっきりする.

-:$<
(.*)#.?\1(.*):"$2"
(.)(.*#)(.*):$2$1$3
:
([^\n]+)(\n(.*))?:"$1$($1#)\n"$3

とりあえず,空白入れたり評価位置を特定するのにevalを使うということは理解した.

wake で遊び続けている

なんか大昔に Makefile だけで n回Hello, world! をやった時を思い出すなぁ(make から呼べるコマンドは echo と make のみという縛りで,コマンドライン引数に n が指定される).

char pyramid.右辺で空白入りのトークンをどうやって作ればいいかわからず,とりあえずチルダをセパレータにしておいて最後に空白化している.無駄だ…

-:$<
([^~]+)([^~].*):$1~$2
(~*)[^~%]([^%]*):$1$2~ $&%
~+:
~(.*%):" "$1
(.)(.*%):"$1"$2
%:"\n"

Permutations.昨日のと同じ.これも最後の空白挿入の操作がお馬鹿なのでどうにかしたい.

:!012345%
(.*)(!.*)(.)%(.*):$1$2%$3$4 $1$3$2$4%
.*!%.+:
(.)(.+!%):"$1 "$2
(.)!%:"$1\n"

palindromize.sed バージョンの移植.正規表現にターゲット全体をマッチさせるというのに慣れない.s コマンドののりで一部にマッチするパタンを書いてしまう.一度別のターゲットに分解してしまうと他のターゲットの情報を使えないので(evalを使えば結合できるから問題ない気がする),自分のプログラムだと全体をひとつのターゲットとして保持したまま一部を書き換えるということが多い.そこで前後の文脈部分のマッチを忘れて動かないとか叫ぶことしばしば.うーむ.eval の使い方を考えるか.

-:$<
([^\n%]+)(\n(.*))?:$1%$1# $3
(.*)%(.*)#.?\2(.*):"$1$3\n"
(.*)%(.)(.*#)(.*):$1%$3$2$4

意外と仕様に合わせた出力のフォーマッティングが面倒な気がする.何かが分かっていないだけかもしれなけれど.

そして,さっき気づいたけど wake って googlability 低い名前だなぁ…

TODO: eval を使ったプログラミング作法を考える.

wake で遊ぶ

shinhさんの作った言語 wake がゴルフ場に入ったので遊んでみたのだけど… まだ言語の癖が分かっておらずプログラム書くのが難しい.

とりあえず最初の方の問題の permutator を sed のプログラムから移植してみた.

元のsedプログラムはこんな感じ:

s/.*/:&%/
:
s/\(.*\)\(:.*\)\(.\)%\(.*\)/\1\2%\3\4\n\1\3\2\4%/gm
s/\(.*\):%$\|.*:%.\+\n/\1/gm
t

で,移植したwake のプログラムはこんな感じ:

:!$<%
(.*)(!.*)(.)%(.*):$1$2%$3$4 $1$3$2$4%
.*!%.+:
(.*)!%:"$1\n"

元のプログラムが s コマンドしか使っておらず,かつ,置換ができなくなるまで繰り返すだけなので,wake プログラムもほとんど同じ構造.s コマンドを明記しない分とエスケープが多く無いことなどによりコードサイズも縮んだ.

sed だとレコードの切れ目を改行で表現して m オプションで一気に処理するけれど,wake だと右辺のスペースでレコードぶった切って処理してあげる形になるのね.これに気づかず右辺に空白入れないとこうなる:

:!$<%~
([^~]*)(![^~]*)([^~])%([^~]*)(.*):$1$2%$3$4~$1$3$2$4%$5
[^~]*!%[^~]+~(.*):$1
([^~]*)!%~(.*):"$1\n"$2

全部に付いている (.*) が明らかに無駄.ここは別処理なのでスペースで切っておくべし.

嵌りどころ:空文字列をマッチしたグループを右辺にそのまま使用する場合,最初のルールに":$<"とか書いておくと無限ループする.

さて,次は何をやろうかね.

Home > Archives > 2010年07月

Search
Feeds

Page Top