名前¶
Acme::EyeDrops - Perlにおけるビジュアル・プログラミング(Visual Programming)
概要¶
use Acme::EyeDrops qw(sightly);
print sightly( { Shape => 'camel',
SourceFile => 'eyesore.pl' } );
説明¶
Acme::EyeDrops
は、同等の、それでいて見苦しい文字や数字が一切ない ものに変換します。
ビジュアル・プログラミング(Visual Programming)によるブレークスルーにおいて、 EyeDropsにより作成されたプログラムをUMLダイアグラムのような様々な形に 吐き出させることにより、その新しく改良された視覚的表現を一目見るだけで、 そのプログラムがどのように機能するかをすぐに理解できるようにします。
Acme::Smirch
には似ていますが、Acme::Bleach
や Acme::Buffy
とは 違い、生成されたプログラムはターゲット・システムにAcme::EyeDrops
を インストールすることを必要としないで走ります。
利用例¶
以下のようなコードが入っている、helloworld.plというプログラムを 持っているとします:
print "hello world\n";
以下のようにすることで、このプログラムをラクダに見えるようにすることが できます:
print sightly( { Shape => 'camel',
SourceFile => 'helloworld.pl',
Regex => 1 } );
上記のAPIを使う代わりに、demoディレクトリにあるsightly.plコマンドを 使うほうが便利だと思うかもしれません:
sightly.pl -h (ヘルプ)
sightly.pl -s camel -f helloworld.pl -r >new.pl
cat new.pl (ラクダのようにみえるはず)
perl new.pl (前と同じように"hello world"と出力)
'camel'
という形は、EyeDrops.pmと同じディレクトリにある ファイルcamel.eyeであるということに注意してください。そのため 必要に合わせて、あなた独自の形を追加することもできます。
あなたのプログラムをわかりやすくする¶
あなたの上司があなたのプログラムを説明するUML図を指示したならば、 彼に、これを提出することが出来ます:
print sightly( { Shape => 'uml',
SourceFile => 'helloworld.pl',
Regex => 1 } );
もし、それがWindowsプログラムであれば、図形を組み合わせる ことにより、それも示すことができます:
print sightly( { Shape => 'uml,window',
Gap => 1,
SourceFile => 'helloworld.pl',
Regex => 1 } );
これは改造された視覚的表現を生成します:
''=~('('.'?'.'{'.('`'|'%').('['^'-').(
( (
( (
( (
( (
( (
'`'))))))))))|'!').('`'|',').'"'.('['^
(
( (
( (
'+'))))
)
)
.('['^')').('`'|')').('`'|'.').(('[')^
( (
( (
'/'))))).('{'^'[').'\\'.('"').( '`'|'(').('`'|'%').('`'|"\,").(
( ( ( (
( ( ( (
( ( ( (
( ( ( (
( ( ( (
'`'))))))))))))))))))))|"\,").( '`'|'/').('{'^'[').('['^"\,").(
'`'|'/').('['^')').('`'|',').('`'|'$').'\\'.'\\'
.('`'|'.').'\\'.'"'.';'.('!'^'+').'"'.'}'."\)");
$:='.'^'~';$~='@'|'(';$^=')'^'[';$/='`'|"\.";$_=
"\("^ (( '}'))
;($,) =( '`')|
"\!"; $\ =')'^
"\}"; $: ='.'^
"\~"; $~ ='@'|
"\("; $^ =')'^
"\["; $/ ='`'|
"\."; $_ ='('^
"\}"; $, ='`'|
"\!"; $\ =')'^
"\}"; $: ='.'^
'~';$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='('^'}';
($,)= (( '`'))
|'!'; $\ =')'^
"\}"; $: ='.'^
"\~"; $~ ='@'|
"\("; $^ =')'^
"\["; $/ ='`'|
"\."; $_ ='('^
"\}"; $, ='`'|
"\!"; $\ =')'^
"\}"; $: ='.'^
"\~"; $~ ='@'|
'(';$^=')'^'[';$/='`'|'.';$_='('^'}';$,='`'|'!';
$\=')'^'}';$:='.'^'~';$~='@'|'(';$^=')'^"\[";$/=
'`'|'.';$_='('^'}';$,='`'|'!';$\=')'^'}';$:='.';
コードを一目見ただけで、それがWindowsプログラムであることが わかり、そのUML構造も見ることが出来る、これがビジュアル・ プログラミングによるブレークスルーなのです。
Linuxにのみ、その/usr/games/bannerコマンドを プログラムのソーステキストに適用することができます:
print sightly( { Shape => 'srcbanner',
Width => 70,
SourceFile => 'helloworld.pl',
Regex => 1 } );
その文字が大きく、読みやすくなるので、生成されたプログラムは 元のものよりも理解しやすくなります。
簡略化されたPerl6の歴史¶
これはこれまでのPerl6開発作業の概要です:
print sightly( { Shape => 'jon,larry,damian,simon,parrot',
Gap => 3,
Regex => 1,
Print => 1,
SourceString => <<'END_HAIKU' } );
Coffee mug shatters
Larry Apocalyptic
Parrot not a hoax
END_HAIKU
生成されるもの:
''=~(
'('."\?".
'{'.('['^'+'
).('['^"\)").(
'`'|')').('`'|
'.').('['^'/').
'"'.('`'^'#').(
'`'|'/').(('`')|
'&').('`'|'&').(
'`'|'%').("\`"|
'%').('{'^'[').
('`'|('-')).(
'['^"\.").(
'`'|"'").(
'{'^'[').('['^'(')
.('`'|'(').('`'|'!')
.('['^'/').('['^"\/").(
'`'|'%').('['^')').('['^"\(").(
'!'^'+').('`'^',').('`'|'!').('['^')').(
'['^')').('['^'"').('{'^'[').('`'^'!').('['^'+')
.('`'|'/').('`'|'#').('`'|'!').('`'|',').('['^'"').
('['^'+').('['^'/').('`'|')').("\`"| "\#").(
'!'^'+').('{'^'+').('`'|('!')).( '['
^')').('['^')').('`'|"\/").(
'['^'/').('{'^'[').('`'|'.')
.('`'|'/').('['^'/').(('{')^
'[').('`'|'!').('{'^'[').('`'
|'(').('`'|'/').('`'|('!')).(
'['^'#').('!'^'+').'"'.'}'.')'
);$:='.'^'~';$~='@'|'(';$^=')'
^'[';$/='`'|'.';$_='('^'}';$,=
'`'|'!';$\=')'^'}';$:='.'^'~';
$~='@'|'(';$^=')'^'[';$/=('`')|
'.';$_='('^'}';$,='`'|'!';$\=')'
^(( '}'));$:='.'^'~';$~='@'|"\(";$^=
')'^'[';$/ ='`'|'.';$_='('^'}';$,='`'|"\!";
$\=')'^'}';$: ='.'^'~';$~='@'|'(';$^=')'^"\["; $/
='`'|'.';$_='('^'}';$,='`'|'!';$\=')'^"\}";$:= ( (
'.'))^'~';$~='@'|'(';$^=')'^'[';$/='`'|('.');$_= ( (
'('))^'}';$,='`'|'!';$\=')'^'}';$:='.'^'~';$~="\@"| '(';$^=
')'^'[';$/='`'|'.';$_='('^'}';$,='`'|'!';$\=')'^'}'; $:='.'^'~'
;$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='('^'}';$,='`'|'!';$\=')'^
'}';$:='.'^'~';$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='('^"\}";$,=
'`'|'!';$\=')'^'}';$:='.'^'~';$~='@'|'(';$^=')'^'[';$/='`'|"\.";
$_='('^ "\}"; $,='`'|'!';$\=')'^'}';$:='.'^'~';$~='@'|'(';$^
=( ')')^'[';$/='`'|'.';$_='('^'}';$,='`'|'!';$\=
')'^'}';$:='.'^'~';$~='@'|'(';$^=')'^'[';$/=
'`'|'.';$_='('^'}';$,='`'|('!');$\= "\)"^
'}';$:='.'^'~';$~='@'|'(';$^=')'^'[';
$/='`'|'.';$_='('^'}';$,='`'|('!');$\=
')'^'}';$:='.'^'~';$~='@'|'(';$^=(')')^
'[';$/='`'|'.';$_='('^'}';$,='`'|"\!";$\=
')'^'}';$:='.'^'~';$~='@'|'(';$^=')'^'[';
$/='`'|'.';$_='('^'}' ;$,='`'|'!';$\="\)"^
'}';$:='.'^'~';$~='@' |'(';$^=')'^'[';$/=
'`'|'.';$_='('^'}';$, ='`'|'!';$\=(')')^
'}';$:='.'^"\~";
$~='@'|'(';$^=')'^"\[";
$/='`'|'.';$_='('^'}';$,="\`"|
"\!"; ($\)
=')' ^((
'}') );(
$:)= ( '.'
)^(( ( '~'
))); $~ = '@'
|'(' ; ( $^)
=(( (( (( ')'
))) )) ) ^((
'[' ));( ( $/)
)=( '`') | '.'
;$_ ='(' ^ '}'
;$, ='`'|'!'; ( $\)
=(( (( ( ((
')' )) ) ))
))^ ( ( ((
'}' ) )));(
$:) = ((
'.' ) )^'~';$~='@'|'(';$^=')'^'[';$/='`'|'.'
;$_ ='('^'}';$,= '`'|'!' ; ( $\)=')' ^
'}' ; ( $:) =(( (( ( ( (( '.' ))) )
))) ) ^ '~';$~="\@"| ( ( '('));$^=')' ^
'[' ; ( ( ( (
$/ ))) ) = ( (( (
(( ( '`')) ) ) )) )
|+ ( ( ( ( ( (
(( ( '.' )))))))));($_)= ( '(')^'}';$,=
(( ( ( ( (
( ( ( ( (
( ( ( '`' ) )
) ))) )) )
) ) )))|'!';$\=')'^'}';$: =
( ( '.'))^'~';$~='@'|'(';$^= (
( ( ')')))^'[';$/='`'|"\.";$_= (
( ( '(')) )^'}';$,="\`"| '!'; (
( ( $\)) ) = ')' ^
(( '}' ));$:='.'^'~';$~ =((
( (
( (
( (
( ( (
( ( (
( ( (
( ( (
( ( ( (
( ( ( (
( '@' )) )
) ))))))))))) )
)))))))))))))|+
'(';$^=')'^('[');$/=
'`'|'.';$_='('^'}';$,='`'
|'!' ;$\=
')'^ '}';
($:) ='.'
^'~' ;$~=
'@'| '(';
($^) =')'
^'[' ;$/=
'`'| '.'
;$_= '('^
'}'; $,='`' |'!'
;$\= ')'^ ( '}'
);( $:) ='.'^'~' ; $~=
'@' | '('; $^= ( ')'
)^+ ( '[');$/='`' | '.'
;$_ = ( '('
)^+ ( ( '}'
)); ( ( $,)
)=( ( ( '`'
))) | ( '!'
); ( ( $\)
) =( ( ( ((
( (( ( ( ((
( ')') ))))))))) )))^(( '}'
) );( $:) =(( '.' ))^ '~'
; $~ =( '@')|'(' ;$^=')' ^+
( ( (( (( '[') )) ) )) ;$/= (( (
( ( '`' )))))|'.'; ( $_)='('^'}' ;
( ( $, ) )
= (( ( ((
( '`' ) ))
) ))| ( '!'
);($\)= ( ')'
)^'}' ; ( ( $:)
)='.' ^ ( ( '~'
));$~= '@'|"\(";$^= ')'^
'[';$/ ='`'
|'.';$_ ='('^'}';$,='`'|'!' ;$\=
')'^'}'; $:='.'^'~';$~='@'|'(';$^ =')'
^'[';$/= (( "\`"))|
'.';$_="\("^ '}';$,='`'|'!';$\= (')')^
'}';$:='.' ^'~';$~="\@"| "\(";
$^=')'^'[' ;($/)=
'`'|('.');$_= '('^"\}";
$,='`'|'!';$\=')'^'}';$:='.'^'~'
;$~='@'|'(';$^=')'^'[';$/=('`')|
'.';$_='('^'}';$,='`'|('!');$\=
')'^'}';$:='.'^'~';$~='@'|'(';
$^=')'^'[';$/='`'|'.';$_='('
^'}';$,='`'|'!';$\=(')')^
'}';$:='.'^'~';$~="\@"|
'(';$^=')'^('[');$/=
'`'|'.';$_=('(')^
'}';$,='`'|
'!';$\=')'^"\}";
$:='.'^'~'; $~=('@')|
'(';$^=')'^'[' ;$/='`'|'.'
;$_='('^"\}";$,= '`'|"\!";$\=
')'^'}';$:='.'^'~' ;$~='@'|"\(";
$^=')'^'[';$/='`'|'.' ;$_='('^"\}";
$,='`'|'!';$\=')'^"\}"; $:='.'^'~';$~
='@'|'(';$^=')'^"\[";$/= '`'|'.';$_='('
^'}';$,='`'|'!';$\=')'^'}' ;$:='.'^'~';$~
='@'|'(';$^=')'^'[';$/='`'| '.';$_='('^'}';
$,='`'|'!';$\=(')')^ '}' ;$: ='.'^'~'
;$~='@'|'(';$^=')' ^'[';$/
='`'|'.';$_=('(')^ '}';$,=
'`'|'!';$\=')'^'}' ;($:)=
'.'^'~';$~='@'|'('; $^=')'
^'[';$/='`'|'.';$_= "\("^
'}';$,='`'|"\!";$\= ( ')')
^'}';$:='.'^'~';$~ = '@'
|'(';$^=')'^'[';$/ = ((
'`'))|'.';$_="\("^ ( ((
'}')));$,='`'|'!'; ( ( ( ( ( ( (
$\)))))))=')'^"\}"; ( ( ( ( (
$:)))))='.'^'~';$~ ='@'| '(' ; (
( $^))=')'^'[';$/ ='`'|'.' ;($_) = (
( '('))^'}';$, = (
'`')|"\!"; ( $\)
= ')' ^ (
( ( (
( ( (
( ( (
( ( ( ( ( ( (
( ( ( ( (
( ( ( (
( (
( (
( ( '}')))))) )
) ) )))))))))))))
) ) )))))))) ;
( ( $:))='.'^'~';
( ( ( (
( ( ( (
( ( (
( ( ( ( (
( (
( (
( (
( ( (
( (
( ( ( (
$~)))))))
))))))))))))))
))))))))))='@'|"\(";
$^=')'^'[';$/='`'|'.';$_=
'('^'}';$,=('`')| '!';$\=
')'^'}';$:='.'^'~';$~ ='@'|'('
;$^=')'^'[';$/='`'|'.';$_='('^'}';$,
='`'|'!';$\=')'^'}';$:='.'^'~';$~="\@"|
'(';$^=')'^'[';$/='`'|'.';$_='('^('}');$,=
'`'|'!';$\=')'^'}';$:='.'^'~';$~='@'|'(';$^=
')'^'[';$/='`'|'.';$_='('^'}';$,='`'|"\!";$\=
')'^'}';$:='.'^'~';$~='@'|'(';$^=')'^ '['
;$/='`'|'.';$_='('^'}';$,='`'|'!';$\= ')'
^'}';$:='.'^'~';$~='@'|'(';$^=')'^'['
;$/='`'|'.';$_='('^'}';$,='`'|'!';$\=
')'^'}';$:='.'^'~';$~='@'|'(';$^="\)"^
'[';$/='`'|'.';$_='('^'}';$,='`'|"\!";
$\=')'^'}';$:='.'^'~';$~='@'|('(');$^=
')'^'[';$/='`'|'.';$_='('^'}';$,="\`"|
'!';$\=')'^'}';$:='.'^'~';$~='@'|'(';
$^=')'^'[';$/='`'|'.';$_='('^"\}";$,=
'`'|'!';$\=')'^'}';$:='.'^('~');$~=
'@'|'(';$^=')'^'[';$/='`'|"\.";$_=
'('^'}';$,='`'|'!';$\=')'^"\}";$:=
'.'^'~';$~='@'|'(';$^=')'^('[');$/=
'`'|'.';$_='('^'}';$,='`'|"\!";$\=
')'^'}';$:='.'^'~';$~='@'|('(');$^=
')'^'[';$/='`'|'.';$_='('^"\}";$,=
'`'|'!';$\=')'^'}';$:='.'^"\~";$~= '@'
|'(';$^=')'^'[';$/='`'|'.';$_='('^ (
'}');$,='`'|'!';$\=')'^('}');$:= '.'^
'~';$~='@'|'(';$^=')'^('[');$/= '`'|'.'
;$_='('^'}';$,='`'|'!';$\=')'^ '}';$:='.'^
'~';$~='@'|'(';$^=')'^'[';$/= '`'|'.';$_='('
^'}';$,='`'|"\!";$\= (( ')'))^'}';$:='.'^
'~';$~='@'|('(');$^= ( ')')^'[';$/='`'|'.'
;$_='('^'}';$,="\`"| ( ( '!'));$\=')'^'}';
$:='.'^'~';$~='@'|'(' ; $^=')'^'[';$/=
'`'|'.';$_='('^'}';$, ='`'|"\!";
($\) =')'^'}';$:='.' ^'~';$~
=(( '@'))|('(');$^= ')'
^+ '[';$/='`'|"\.";
( $_)='('^"\}";$,=
'`'|'!';$\="\)"^
'}';$:='.'^"\~";
もしあなたが心からLarryを偶像視するのであれば、彼の周りに 枠をつけるかもしれません:
print sightly( { Shape => 'larry2',
BorderGap => 3,
BorderWidth => 2,
SourceFile => 'helloworld.pl',
Regex => 1 } );
larry2
という形は、Ryan Kingにより寄稿されたマンガです:
''=~('('.'?'.'{'.('`'|'%').('['^'-').('`'|'!').("\`"|
',').'"'.('['^'+').('['^')').('`'|')').('`'|'.').('['
^+ ((
(( ((
(( ((
(( '/'))))))))))) ))
.( '{'^'[').'\\'.'"'.('`' |+
(( '('))).('`'|'%').('`'|',' ).
+( '`'|(',')).( '`'|'/'). ('{'^ ((
(( '['))))).('[' ^',').( (( '`' ))
|+ '/' ).('['^')') .("\`"| ( ',' ))
.( '`' |"\$").'\\'. '\\'. ( '`' |+
(( '.' ))).('\\'). '"'. ( (( ((
(( ';') )))))).''. ('!' ^ ((
(( '+'))) )). '"' . ( (( ((
(( '}')))))) ) . ( ( ( (( ((
(( ')')))))) )))); $:='.'^'~';$~=('@')| ((
(( '(')))); $^ ="\)"^ (( (( ( (( ((
(( '['))))) ))) ) ) ) ;( $/
)= '`'|'.'; $_ = ( ( ( ( (( ((
(( '(')))) )) ) ) ) )^ ((
(( '}'))) ); $, =( '`' )|
(( "\!")); ( $\)=')'^ '}'; $: =(
(( '.')))^ ( '~'); ($~)= ( (( ((
(( '@')))))) )|"\("; $^=')'^'[' ;(
$/ )="\`"| '.';$_='(' ^'}';$,='`' |+
(( '!')) ; $\=(')')^ ( "\}"); $:
=( ( '.')) ^'~' ; ($~) =(
(( ( ( '@' ) ))) )|
(( '(' ) ); ( ( $^ ))
=( (( ( ( "\)")))))^ ( ((
(( '[' )) ) ))
;( ( $/ )) =(
(( ( (( ( ( ((
(( '`'))))) ) ))
)) ))
|+ ((
(( ((
'.'))))));$_='('^'}';$,='`'|'!';$\=')'^'}';$:='.'^'~'
;$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='('^'}';$,="\`";
Just another Perl hacker¶
より意欲的にして、大きく自分自身を出力するJAPHを作ってみましょう。
my $src = <<'FLAMING_OSTRICHES';
open 0;
$/ = undef;
$x = <0>;
close 0;
$x =~ tr/!-~/#/;
print $x;
FLAMING_OSTRICHES
print sightly( { Shape => 'japh',
SourceString => $src,
Regex => 1 } );
これは動きます。しかし以下のものを:
$x =~ tr/!-~/#/;
を以下のように変更すると:
$x =~ s/\S/#/g;
生成されたプログラムは奇妙な動きをして、うまく動きません。というのも それが正規表現の内側で走り、Perlの正規表現エンジンが再入可能(reentrant) ではないからです。この場合、以下のようにして逃げなければなりません:
print sightly( { Shape => 'japh',
SourceString => $src,
Regex => 0 } );
これは生成された見た目の良いプログラムを代わりにeval
を通して実行します。 Regex => 1を使いたいのであれば、変換されるプログラムが、正規表現と$_
の 使い方に注意していることを確実にしてください。
元のJust another Perl hacker,、別名Randal L Schwartzに似ている JAPHを生成するためには、以下のようにしてください:
print sightly( { Shape => 'merlyn',
SourceString => 'Just another Perl hacker,',
Regex => 1,
Print => 1 } );
生成されるもの:
''=~('('.'?'.'{'.('['
^'+').('['^')').('`'|')').(
'`'|'.').('['^'/').'"'.('`'^'*')
.('[' ^'.')
.('[' ^'(')
.('[' ^'/')
.('{'^ '[').(
"\`"| '!').(
'`'| '.').(
'`'| ( ( '/'))).
('[' ^ ( ( '/'))).(
'`'| ( ( ( ( '('))))).
('`'| ( ( ( ( '%'))))).
('['^ ( ( ( ( ')'))))).
('{'^ '[') .( ( (( ('{'))))^
'+'). ( '`'|'%' ).("\["^ ')').('`'
|',').('{'^ '[').('`'
|'(').('`' |"\!").(
'`'|'#').( ('`')| '+').( '`'|'%')
.('['^')') .(( ',' )). '"' .('}').
"\)");$:= ('.')^ ( "\~"); $~='@'|
('(');$^= (( ')' )) ^ (( '[' )) ;($/)=
'`'|'.'; $_='('^'}' ; $,='`'|'!' ;($\)
=(')')^ ( '}'
);($:) = '.'
^'~'; ( ( ( $~)
) )= ( ( ( '@'
) ) ) | ( ( ( '('
) ) ) ; ( ( ( $^
) ) ) =
( ( ( (
( ( ( (
( ')')))))))))^'[' ; # ;
# ; # ; # ;#
; # ; # ; #;
# ; #; #; # ;
# ; # ;# ; #
; # ;#;#; # ;
# ; # ;
# ; # ;
# ; #
; # ;
# ; #
; # ;
# ;
# ;
#;# ;#
;#;#;#;#;
鏡で見るBuffy¶
見た目のよいエンコードはコンパクトではないため、あなたは時折、 Perl Golfの超現実的な形式を楽しんでいることがわかるかもしれません。 そこでの勝者は以下のような最も小さいf.tmpを持ったものです:
sightly.pl -r -f program_to_be_converted >f.tmp
(キー)ストロークの数を減らすことを別にすれば、正規表現を避け、 英数字を見た目のよいもので置き換えるべきです。それは見た目のよい エンコーディングを必要としません。
説明するために、鏡で見るBuffy(=Buffy looking in the mirror)を 作成する、面白い問題を考えてみましょう。k.plから始めましょう:
open$[;chop,($==y===c)>$-&&($-=$=)for@:=<0>;
print$"x-(y---c-$-).reverse.$/for@:
EyeDropsが生成するプログラムには後ろに空白が入っていないことに 注意してください。それが、上記のプログラムをおかしくします。
鏡で見るBuffyは、これで以下のように作成することができます:
sightly.pl -r -f k.pl -s buffy2 >b.pl
cat b.pl (Buffyの顔を表示します)
perl b.pl (鏡で見るBuffyを表示します)
チィッ。これはbuffy2の図形を2つ必要とします。何をするべきでしょうか? あなたは必要とされる数の空白を追加するため、各行に追加するための ポスト・プロセッサ・プログラム、ここではpp.plを 書く事が出来ます:
chop,$==y===c,$=<$-or$-=$=for@a=<>;
print$_.($"x($--length)).$/for@a
このプログラムがあれば、kk.plをより短く書く事が出来ます:
open$%;chop,print+reverse.$/for<0>
そして最後に、以下のようにして鏡で見るBuffy を生成します:
sightly.pl -r -f kk.pl -s buffy2 >b.pl
perl pp.pl b.pl >bb.pl
この例では、しかしながら、Compact
属性(sightly.plでは-m
スイッチ)が、後ろの空白を必要とすることなく、より直接的な解決方法を 提供します:
sightly.pl -mr -f k.pl -s buffy2 >buffy.pl
cat buffy.pl (Buffyの顔を表示)
perl buffy.pl (鏡で見たBuffyを表示)
生成される buffy.pl:
''=~('(?{'.(
'`'|'%').('['^'-'
).('`'|'!').('`'|','
).+ ( '"'
).( ( '`'
)|+ ( '/'
)). ( '['
^(( ( '+'
))) ).('`' |((
'%' ))). ( '`'
|(( '.') ) ).+
((( (( ( (((
((( ( ( (((
((( ( '\\')))
))) ) ) ) )
) )))) )))))) .'$[;' . (
( ( (( ( (
( ( ( (( ( ( (( ( ( (
( ( '`') )))) ) )
) ) ))) )
) ))) ) )
)| ( ( ( ( ((
'#' ) ) ) )))
).(('`')| ('(')).(
'`'|'/'). ('['^'+') .',(\\$'
.'=='.('[' ^'"') . '==='.+(
'`'|'#').')' . '>\\$-'
.'&&(\\$-=\\' . '$=)'.(
'`'|'&').('`' | ( '/')).(
'['^')').'\\' . '@:=<' .
('^'^(('`')| "\.")). (
'>').(';').( '!'^'+' )
.('['^'+'). ('['^')' ).('`'|
')').("\`"| "\.").( ( ('['))^
"\/").'\\$\\"'.( ( "\[")^ ( (
( ( "\#"))))). ( ( '-')) . (
( ( ('(')))).( ( ( '[')) ^ (
( '"'))).'--' . '-'. ( (
( '`'))|'#'). ( ( (
( '-')))). ( ( (
( ( '\\' ) )
) ) ) .
( ( ( (
( ( ( ( (
( ( ( ( (
( ( ( ( (
( ( ( ( (
( '$'))))))))))))))))))))))))).'-).'.('['^ ( (
( ')')))).('`'|'%').('['^'-').('`'|'%').(('[')^ (
( ')'))).('['^'(').('`'|'%').'.\\$/'.('`'|'&').( (
( '`'))|'/').('['^')').'\\@:'.('!'^'+').'"})');$:= (
( '.'))^'~';$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='(' ;
しかし人によっては目に、プレインな見た目のよいエンコーディングの ほうが楽しいと思うかもしれませんが、これはおそらくよりキレイな 解決法でしょう。
面白いことに、鏡像ではなく、顔を上下逆さまに表示することは、 以下の様にして、より簡単に解決されます:
open$%;print+reverse<0>
そして自分自身を表示したり:
open$%;print<0>
あるいは空白以外を'#'
で置き換えて自分を表示することも簡単です:
open$%;print+map{y;!-~;#;;$_}<0>
ラクダの宙返り¶
前の章のBuffyの例を、実行したときに画面を宙返りするような能力を持った ラクダの形をしたプログラムを生成するように拡張しましょう。
生成するプログラム、gencamel.plから始めます:
use Acme::EyeDrops qw(sightly);
my $src = <<'END_SRC_STR';
$~=pop||'';open$%;
y,!-~,#,,s,(.).,$+,gs,$~&&($_=reverse)for@~=grep$|--,('')x18,<0>;
@;=map~~reverse,reverse@~;
map{system$^O=~Win?CLS:'clear';
($-=$_%3)||(--$|,map$_=reverse,@~,@;);
print$"x($=/3*abs$|*2-$-),$_,$/for$-&1?@;:@~;
sleep!$%}$%..11
END_SRC_STR
$src =~ tr/\n//d;
my $prog = sightly( { Regex => 1,
Compact => 1,
Shape => 'camel',
SourceString => $src } );
my @a = split(/\n/, $prog);
my $max = 0; length > $max and $max = length for @a;
$_ .= ' ' x ($max - length) for @a;
print " $_ \n" for @a;
Compact属性の使い方について注意してください。ここでの必要なのは 上記のプログラムを1つのラクダの形に絞るためです。
これを実行すると:
perl gencamel.pl >camel.pl
camel.plを生成します:
''=~('(?{'.(
('`')| '%').('['^'-').
('`'|'!'). ('`'|',').'"\\$~='
.('['^'+') .('`'| '/').('['^'+').'||'.
"'"."'".';'.('`'|'/' ).('['^'+').('`'|'%').
('`'|'.').('\\$%;').( '['^'"').(',!-~,#,,').(
'['^'(').',(.).,\\' .'$+,'.('`'|"'").('['^'(')
.',\\$~&&(\\$' .'_='.('['^')').('`'|('%')).(
'['^'-').('`'| '%').('['^')').('['^'(').(('`')|
'%').')'.("\`"| '&').('`'|'/').('['^"\)").'\\@~='.(
'`'|"'").("\["^ ')').('`'|'%').('['^'+').('\\$|--,(').
"'"."'".(')').( '['^'#').('^'^('`'|'/')).(':'&'=').',<'.
('^'^('`'|'.') ).'>;\\@;='.('`'|'-').('`'|'!').('['^'+')
.'~~'.('['^')' ).('`'|'%').('['^'-').('`'|'%').('['^')').
('['^'(').('`'|'%').','.('['^')').('`'|'%').('['^'-').('`'
|'%').('['^')').('['^'(').('`'|'%').'\\@~;'.('`'|'-').('`'|
'!').('['^'+').'\\{'.('['^'(').('['^'"').('['^'(').(('[')^
'/').('`'|'%').('`'|'-').'\\$^'.('`'^'/').'=~'.('{'^"\,").(
'`'|')').('`'|'.').'?'.('`'^'#').('`'^',').('{'^'(').(':').
"'".('`'|'#').('`'|',').('`'|'%').('`'|'!').('['^')')."'".
';(\\$-=\\$_%'.('^'^('`'|'-')).')||(--\\$|,'.('`'|'-' ).(
'`'|'!').('['^'+').'\\$_='.('['^')').('`'|'%').('[' ^((
'-'))).('`'|'%').('['^')').('['^'(').('`' |('%')). ','
.'\\@~,\\@;);'.('['^'+').('['^(')')).( '`'|')' ).(
"\`"| '.').('['^'/').'\\$\\"'.("\["^ ('#')). '('
.'\\$=/'.('^'^('`'|'-')).'*'. (('`')| '!'
).("\`"| '"').('['^ "\("). '\\$|' .+
('*').( '^'^('`' |',')) .'-\\' .+
'$-),'. '\\$_,'. '\\$' .'/'. (
('`')| ('&')).( '`'| '/')
.('['^ ')').'\\' .'$' .'-'
.'&'. (('^')^( '`'| '/')
).'?' .'\\@;' .':' .''.
'\\' .'@~;' .''. ('['
^'(' ).( '`'| ',')
.''. ((( '`' ))|
'%' ).( '`' |((
'%' ))) .+( '['
^(( '+' ))) .+
(( '!')). ((
(( '\\') ))
). '$%\\}'. ((
((( '\\' ))))) .+
'$' .'%..' .''. (((
'^') )^("\`"| '/' )).(
"\^"^( ('`')|
('/'))). '"})');
注意: Perlに関連付けてラクダの画像を使用することは O'Reilly & Associates, Inc.の商標です。許可を受けて使用しています。
以下の様にしてcamel.plを実行することができます:
perl camel.pl 通常の方向に宙返りするラクダ
perl camel.pl b 後ろの方向に宙返りするラクダ
perl camel.pl please do a backward somersault
同じこと
そのヘッダ行の後に空行も追加する限り、camel.plの先頭に #!/usr/bin/perl -w
という行を入れてもかまいません。
12,032種類のラクダ¶
上記の宙返りするラクダと似た方法で、実行したとき12,032種類の異なる ラクダを吐き出す、ラクダの形をしたプログラムを作成します。
いつものように、生成するプログラムgencamel.plから始めます:
use Acme::EyeDrops qw(sightly);
my $src = <<'END_SRC_STR';
$~=uc shift;$:=pop||'#';open$%;chop(@~=<0>);$~=~R&&
(@~=map{$-=$_+$_;join'',map/.{$-}(.)/,@~}$%..33);
$|--&$~=~H&&next,$~!~Q&&eval"y, ,\Q$:\E,c",$~=~I&&
eval"y, \Q$:\E,\Q$:\E ,",$~=~M&&($_=reverse),
print$~=~V?/(.).?/g:$_,$/for$~=~U?reverse@~:@~
END_SRC_STR
$src =~ tr/\n//d;
my $prog = sightly( { Regex => 1,
Compact => 1,
Shape => 'camel',
SourceString => $src } );
my @a = split(/\n/, $prog);
my $max = 0; length > $max and $max = length for @a;
$_ .= ' ' x ($max - length) for @a; $\ = "\n";
print ' ' x ($max+2); print " $_ " for @a; print ' ' x ($max+2);
これを実行し:
perl gencamel.pl >camel.pl
camel.plを生成します。これは以下の様に実行することができます:
perl camel.pl 通常のラクダ
perl camel.pl q quine (プログラムがそれ自身を出力)
perl camel.pl m 鏡像 (鏡で見るラクダ)
perl camel.pl i 反転したラクダ
perl camel.pl u 上下逆さまのラクダ
perl camel.pl r 回転したラクダ
perl camel.pl h 水平方向につぶれたラクダ
perl camel.pl v 垂直方向につぶれたラクダ
そしてさらに上記のオプションと組み合わせることができます。 それぞれの組み合わせは異なるラクダを生成します。例えば:
perl camel.pl uri
は、大きな、あごひげを蓄え、ポニーテールで、メガネをかけ、 絞り染めのTシャツを着たラクダを生成します。 :)
camel.plはオプションで、ラクダを埋める文字を指定する、 第2の引数を受け取ることが出来ます。(デフォルトは#
)。 例えば:
perl camel.pl hv #で埋められた小さなラクダ
perl camel.pl hv "$" $で埋められた小さなラクダ
なぜ12,032種類のラクダなんでしょうか?主たるオプションq, m, i, u, r, h, vは 128の異なるラクダを生成します。そして第2パラメータとして94の出力可能な 文字が利用できます。合計を求めると 128 * 94 = 12,032種類のラクダになります。
裸で腕相撲¶
ミュンヘン(Munich)でのY::E 2002での最後のオークションは大叙事詩的な 運動競技が呼び物でした。これを以下のようにして思い出すことができます:
print sightly( { Regex => 1,
Shape => 'naw',
Indent => 1,
SourceString => <<'NAKED_ARM_WRESTLING' } );
$/='';open$%;$x=<0>;$y=<0>;
substr($y,428,$%)=' AAAAARRRGGGHHH!!!';
map{system$^O=~Win?CLS:'clear';
print$_&1?$y:$x;sleep!$%+($_&1)}$%..9
NAKED_ARM_WRESTLING
シェルピンスキーの三角形¶
シェルピンスキーの三角形(=Sierpinski triangle)を生成するプログラムは さまざまなメーリングリストやPerl monksでも人気を証明してきました。
単純で簡潔なシェルピンスキーの三角形を生成するプログラム、siertri.plは 以下の通りです:
#!perl -l
$x=2**pop;print$"x--$x,map$x&$_?$"x2:"/\\",0..$y++while$x
これはMtv Europeにより、元のAdam Antonikのプログラムをワン・ストローク 改善したものとして、[email protected]へ14-sep-2002に投稿されました。 これを実行すると:
perl siertri.pl 4
2**4行のシェルピンスキーの三角形を表示します。
(Acme::EyeDrops 1.13で)Mtvのプログラムが最も短いと示すことは、 以下のいくつかのようにハードに$^F
を利用することによって、より短くするよう、 Adam Antonik と Eugene van der Pijllを刺激しただけでした:
-l print$"x--$x,map$x&$_?$"x2:"/\\",0..$_-1for 1..($x=2**pop)
-l $x=2**pop;print$"x--$x,map$x&$_?$"x2:"/\\",0..$y++while$x
-l $^F**=pop;print$"x--$^F,map$^F&$_?$"x2:"/\\",0..$y++while$^F
-lX061 print$"x--$/,map$/&$_?$"x2:"/\\",0..$y++while$/<<=pop
-l print$"x--$^F,map$^F&$_?$"x2:"/\\",0..$y++while$^F*=2**pop
-l $_=$"x2**pop;$_="$'/\\",print,s/(?<=\\)../$&^KI^D5/egwhile/^ /
シェルピンスキーの三角形を作成する面白く判りにくいプログラムは:
#!/usr/bin/perl -l
s--@{[(gE^Ge)=~/[^g^e]/g]}[g^e]x((!!+~~g^e^g^e)<<pop).!gE-ge,
s-[^ge^ge]-s,,,,s,@{[(g^';').(e^'?')]},(G^'/').(E^'|')^Ge,ge,
print,s,(?<=/[^g^e])[^g^e][^g^e],$&^(G^'/').(E^'|')^gE,ge-ge
もう一つのわかりにくいものとしては、以下のようなMtvのプログラムを ベースとした、シェルピンスキーの三角形を作成するシェルピンスキーの 三角形の形をしたプログラムです:
use Acme::EyeDrops qw(sightly);
my $src = <<'END_SRC';
$-=!$%<<(pop||4);print$"x$-,map($-&$_?' ':'/\\',$%..$.++),$/while$---
END_SRC
$src =~ tr/\n//d;
print sightly( { SourceString => $src,
Regex => 1,
Compact => 1,
Indent => 1,
BorderGap => 1,
BorderWidth => 2,
# For 'siertri' built-in shape, Width=>5 means:
# height is 2**5 lines
# width is 2 * 2**5 characters
Width => 5,
Shape => 'siertri' } );
生成されるもの:
''=~('(?{'.('`'|'%').('['^'-').('`'|'!').('`'|"\,").'"\\$-=!\\$%<<('.(
'['^'+').('`'|'/').('['^'+').'||'.('^'^('`'|'*')).');'.('['^'+').('['^
(( ((
(( (( ((
(( ')') ))
)) )) )) ))
)) .(('`')| ((
(( (( (( ((
(( ')') )))) ))
)) )) )) .( (( ((
(( '`'))))))|'.').( ((
(( (( (( ((
(( '[') )))) ))
)) )) )^ (( (( ((
(( '/'))))) )))).''. ((
(( (( (( (( (( ((
(( '\\' )))) )))) )))) ))
)) .+ (( (( (( (( (( (( (( ((
(( '$')))))))))))))))))).'\\"'.('[' ^+
(( (( (( ((
(( '#') )))) ))
)) )) .+ (( (( ((
(( '\\')))) )))).'$' .+
(( (( (( (( (( ((
(( '-') )))) )))) )))) ).
(( (( (( (( (( (( (( (( (( ((
(( ','))))))))))))) ))))))))).("\`"| ((
(( (( (( (( (( ((
(( '-') )))) )))) )))) ))
)) .( (( (( (( (( (( (( (( ((
(( '`'))))) )))))))) )))))|(( '!'))).( ((
(( (( (( (( (( (( (( (( (( ((
(( '[') )))) )))) )))) )))) )))) )))^ '+') .+
(( (( (( (( (( (( (( (( (( (( (( (( (( (( (( (( (( ((
(( '(')))))))))))))))))))))))))))))))))))))).'\\$-&\\$_?'."'".('{'^ ((
(( ((
'['))))))).('{'^'[')."'".':'."'".'/\\\\\\\\'."'".',\\$%..\\$.++),\\$/'
.('['^',').('`'|'(').('`'|')').('`'|',').('`'|'%').'\\$---"})');$:='.'
闘うディンゴ(Dueling Dingos)¶
TPR02 Perlゴルフ・トーナメントの間に、`/anickは彼の経験について 述べたDueling Dingosという詩を書きました。
彼の動く詩を書き出すプログラムを以下のように作ることが出来ます:
print sightly( { Shape => 'yanick3',
Regex => 1,
Print => 1,
SourceString => <<'END_DINGO' } );
#!/usr/bin/perl
# Dueling Dingos v1.1, by Yanick Champoux (9/4/2002)
#
# Inspired by the TPR(0,2) Perl Golf contest.
# Name haven't been changed, since the involved
# parties could hardly be labelled as 'innocent',
# and are way far too gone to protect anyway.
wait until localtime > @April[0]; # wait until the first of April
BEGIN{}
study and seek FOR, $some, $inspiration;
write $stuff;
$score = 145; # no good;
delete $stuff { I_can_do_without }
and do $more_stuff;
delete $even{more_stuff};
reverse $engineer; study; eval $strategy and redo;
write, write, write;
delete $_{'!'}, delete $"{"@!"}, delete $@{'*'}; # must stop cursing
use less 'characters', $durnit;
read THE, $current, $solution;
not 2, $bad;
delete $white_spaces{''} until $program == glob;
for( $all, my @troubles )
{
unlink 1, $character;
}
ARGH:
$must, not $despair;
$I->can(do{ $it });
study new Idea;
m/mmmm/m... do{able};
kill $chickens;
'ask', $Nanabozo, 2, bless $me, 'with more inspiration';
$so, close; warn $mailing_list and alarm $Andrew;
$toil until my $solution < /-\ndrew's
/;
GOT_IT:
send $solution, $to, ref;
$brain, shutdown I,'m dead';
goto sleep;
wait; $till, $the, $day, $after;
readline last $scoreboard;
grep $all, stat;
read THE, $stats, $again until $it_sinks_in;
$Andrew,'s score' lt $mine;
$eyeball, pop @o
;
END_DINGO
ここでは、生成される2577行ものプログラムは再び生成されません。 `/anickのTPR02での苦悩をまとめる、より短いプログラムを生成するためには 以下のようにします:
print sightly( { Shape => 'yanick,eye,mosquito,coffee',
Gap => 3,
Regex => 1,
Print => 1,
SourceString => <<'END_SUFFERING' } );
My head is hurting, my right eye feels like it's going to pop
like a mosquito drinking from an expresso addict with high
blood pressure, I want to crawl somewhere damp and dark and
quiet and I consider never to touch a keyboard again.
END_SUFFERING
生成されるもの:
''=~('('.'?'.'{'.(
'['^'+').('['^')').('`'|
')').('`'|'.').('['^'/').'"'
.('`'^'-').('['^'"').('{'^'[').(
'`'|'(').('`'|'%').('`'|'!').("\`"|
'$').('{'^'[').('`'|')').('['^('(')).(
'{'^'[').('`'|'(').('['^'.').('['^"\)").(
'['^'/').('`'|')').('`'|'.').('`'|"'").','.
('{'^'[').('`'|'-').('['^'"').('{'^'[').('['^
')').('`'|')').('`'|"'").('`'|'(').('['^'/').(
'{'^'[').('`'|'%').('['^'"').('`'|'%').('{'^'['
).('`'|'&').('`'|'%').('`'|'%').('`'|',').(('[')^
'(').('{'^'[').('`'|',').('`'|')').('`'|'+').("\`"|
'%').('{'^'[').('`'|')'). ('['^ ('/')).
"'".('['^'(').('{'^'['). ("\`"|
"'").('`'|'/').('`'|')' ).''.
('`'|'.').('`'|"'").('{' ^'[')
.('[' ^'/').('`'|'/').(('{')^ '[').
('['^'+' ).('`'|'/').('['^'+'). ('!'^
'+').('`' |',') .('`'|(')')).( "\`"|
'+').('`' |'%' ).('{'^'['). ('`'|
'!').('{' ^ ('[')).( "\`"|
'-').('`' | "\/").( "\["^
'(').('[' ^ '*' ).(
'['^'.' ) .+( ( ( ( ( ( (
'`'))) ) )) | ( (
')')) ) . ( (
'[')^ ( (
'/')) ) .('`'| '/'). (
"\{"^ '[' ).('`' |'$') .
('['^ ( ( (
')')) ) ) .
('`'| ( ')')) . (
"\`"| ( '.')) . (
"\`"| ( ( (
'+'))) ) .( ( (
"\`"))| ( (( ( (
')')))))) . +( ( (
'`'))|'.').( ( (( ( (
'`')))))|"'").('{'^'[').( (( (
'`')))|'&').('['^')').('`'| (( (
'/')))).('`'|'-').('{'^'['). ('`'
|'!').('`'|'.').('{'^'[').('`' |
'%').('['^'#').('['^'+').("\["^ (
')')).('`'|'%').('['^('(')).( '['^'('
).('`'|'/').('{'^'[').("\`"|
'!').('`'|'$').('`'|"\$").(
'`'|')').(('`')|
( '#')).('['^'/').("\{"^ (
( '['))).('['^',').('`'|')') .
( '['^'/').('`'|'(').('{'^'[').( (
( '`'))|'(').('`'|')').('`'|"'").( (
( '`'))|'(').('!'^'+').('`'|('"')).( (
( '`'))|',').('`'|'/').('`'|('/')).( (
( '`'))|'$').('{'^'[').('['^'+').('['^ (
( ')'))).('`'|'%').('['^'(').('['^'(') .
( '['^'.').('['^')').('`'|'%').(',').( (
( '{'))^'[').('`'^')').('{'^'[').('['^ (
( ','))).('`'|'!').('`'|'.').('['^'/') .
( '{'^'[').('['^'/').('`'|'/').('{'^ (
( '['))).('`'|'#').('['^')').(('`')| (
( '!'))).('['^',').('`'|',').('{'^ (
( '['))).('['^'(').('`'|('/')).( (
( '`'))|'-').('`'|'%').('['^ (
( ','))).('`'|'(').('`'| (
'%')).('['^')').
+( ((
'`')) | (
"\%")).( ( (
'{'))^'[' ) . ( (
'`')|'$').( ( ( ( (
'`'))))|'!') . ( ( (
'`'))|'-').( ( ( ( (
'['))))^'+') . ( ( (
'{'))^'[').( ( ( ( (
'`'))))|'!' ) . ( (
'`')|'.' ).('`'|'$' ) . ( (
'{')^'[').('`'| ('$')).( '`'| '!' ) .
('['^')').('`'|'+') .('{'^'[').('`'| (
'!')).('`'|'.').('`'|'$').('!'^"\+").( (
'[')^'*').('['^'.').('`'|')').('`'|'%'
).('['^'/').('{'^'[') .('`'|'!').
('`'|('.')).( '`'|('$')).(
'{'^'['
).( '`'
^+ ( ( (
(( ( ( (
(( ( ( (
(( ( ( (
(( ( ( (
')') ) ) )
)) ) ) ) )
) ) ) )
) ) ) )
) ) ) )
) ) . (
( ( ( (
( ( ( (
( ( ( (
( ( ( (
'{'))))
))))))
)))))
)^'['
).''.
('`'|
'#').('`'|'/').('`'|'.').('['^'(').(('`')| ')').(
'`'|'$').('`'|'%').('['^')').('{'^('[')).( '`'|'.').
('`'|'%').('['^'-').('`'|'%').('['^')').('{'^ '['
).('['^'/').('`'|'/').('{'^'[').('['^'/').( '`'
|'/').('['^'.').('`'|'#').('`'|'(').("\{"^ '['
).('`'|'!').('{'^'[').('`'|'+').('`'|'%' ).(
'['^'"').('`'|'"').('`'|'/').('`'|'!').( '['^
')').('`'|'$').('{'^'[').('`'|('!')).( '`'|
"'").('`'|'!').('`'|')').('`'|"\."). '.'.
('!'^'+').'"'.'}'.')');$:='.'^('~');$~=
'@'|'(';$^=')'^'[';$/='`'|'.';$_='('
^'}';$,='`'|'!';$\=')'^'}';$:=
'.'^'~';$~='@'|('(');$^=
')'^'[';$/='`'|'.'
バイナリ・ファイルのエンコーディング¶
ちょっと待ってください、まだまだあるんです。 あなたはバイナリ・ファイルも コード化することができます。
print sightly({Shape => 'camel,mongers',
SourceFile => 'some_binary_file',
Binary => 1,
Print => 1,
Gap => 3 } );
これはuuencode/uudecodeよりもキレイです。 以下にsightly.plでバイナリ・ファイルをエンコード/デコードする方法を示します。
エンコード:
sightly.pl -g3 -bps camel,mongers -f some_binary_file >eyesore
デコード:
perl eyesore >f.tmp
それが動くかを確認:
cmp f.tmp some_binary_file
ゆっくりしたい日¶
本当にゆっくりしたい日には、Unix端末に座り、以下のようにタイプ することができます:
sightly.pl -r -s camel -f helloworld.pl >t1.pl
cat t1.pl
perl t1.pl
この小さなプログラムにはラクダが1頭だけ必要です。
sightly.pl -r -s camel -f t1.pl >t2.pl
cat t2.pl
perl t2.pl
フーム、これでラクダが14頭。
sightly.pl -r -s camel -f t2.pl >t3.pl
ls -l t3.pl
cat t3.pl
perl t3.pl
ラクダ195頭。563,745バイト。ウーン、遅くなった。 これまでに書かれた最も大きくって、遅いhello worldプログラムじゃない?
sightly.pl -r -s camel -f t3.pl >t4.pl
ls -l t4.pl
cat t4.pl
perl t4.pl
ラクダ2046頭。5,172,288バイト。メモリがないだって!
Buffyはクリケットに行った¶
Buffyファンは彼女の文字を回転したいかもしれません:
print sightly( { Shape => 'buffy',
Rotate => 0, # try 270, 90 and 180
RotateType => 1, # try 0, 1, 2
SourceFile => 'helloworld.pl',
Regex => 1 } );
あるいは彼女をポニーに乗せたいかもしれません:
print sightly( { Shape => 'buffy3,buffy4,riding,a,pony',
SourceString => "This is how Catherine the ".
"Great died.\n",
Gap => 2,
Regex => 1,
Print => 1 } );
一方、クリケットのファンは以下のように比較するかもしれません:
print sightly( { Shape => 'cricket',
SourceFile => 'helloworld.pl',
Regex => 1 } );
これは以下のものを生成します:
'?'
=~+(
"\(".
"\?".
"\{".(
('`')|
'%').(
('[')^
'-').( "\`"|
'!').( '`'|',')
.'"'.('[' ^'+').('['
^"\)").( '`'|"\)").(
'`'|'.') .('['^'/')
.(('{')^ '[').'\\'.
'"'.(('`')| '(').('`'
|'%').('`'|',' ).("\`"|
"\,").( '`'|'/') .('{'^'[').
(('[')^ ',').('`'|'/').(('[')^
"\)").( '`'|',').('`'|'$').''.
('\\'). '\\'.('`'|"\.").'\\'.
('"'). ';'.('!'^'+').('"').
'}'.')');$:='.'^'~';$~='@'|
'(';$^=')'^'[';$/='`'|'.';$_
='('^'}';$,='`'|'!';$\=')'^
'}';$:= '.'^'~';$~="\@"|
'('; $^=')'^"\[";$/=
'`'|'.';$_='('^
'}';$,='`'|"\!";
$\=')'^('}');$:=
'.'^'~';$~="\@"|
'(';$^=')'^"\[";
$/='`'|'.';$_='('
^'}';$,='`'|'!';$\=
')'^'}';$:='.'^'~';$~=
'@'|'(';$^=')'^('[');$/=
'`'|'.';$_='('^'}';$,='`'
|'!';$\=')'^'}';$:='.'^'~';
$~='@'|'(';$^=')'^'[';$/='`'|
( '.');$_='('^'}' ;$,='`'|"\!";
$\ =')'^"\}";$:= '.'^('~');$~=
'@' |'(';$^=')'^ '[';$/=('`')|
'.';$_=('(')^ '}';$,=('`')|
'!';$\=(')')^ '}';$:=('.')^
'~';$~='@'|'(' ;$^=')'^'[';
$/='`'|('.');$_= '('^"\}";$,=
'`'|'!';$\=')'^'}' ;$:='.'^'~'
;$~='@'|('(');$^= ')'^"\[";$/=
'`'|'.';$_='(' ^'}';$,='`'|
'!';$\= ')'^'}';$:=
"\."^ '~';$~='@'|
"\("; $^=')'^'['
;$/= '`'|'.';
$_= "\(";
そしてこれは:
print sightly( { Shape => 'cricket',
Invert => 1,
BorderWidth => 2,
SourceFile => 'helloworld.pl',
Regex => 1 } );
これを生成します:
''=~('('.'?'.'{'.('`'|'%').('['^'-').('`'|'!').('`'|(',')).
'"'.('['^'+').('['^')').('`'|')').('`'|'.').('['^'/').('{'^
'[').'\\'.'"'.('`'|'(' ).('`'|'%').('`'|',').('`'|"\,").(
'`'|'/').('{'^"\[").( '['^',').('`'|'/').('['^')').('`'|
',').('`'|'$').'\\'. '\\'.('`'|'.').'\\'.'"'.';'.("\!"^
'+').'"'.'}'."\)"); $:='.'^'~';$~='@'|'(';$^=')'^'[';$/
='`'|'.';$_="\("^ '}';$,='`'|'!';$\=')'^'}';$:='.'^'~'
;$~='@'|"\(";$^= ')'^'[';$/='`'|'.';$_='('^'}';$,='`'|
'!';$\=')'^'}'; $:='.'^'~';$~='@'|'(';$^=')'^('[');$/=
'`'|'.';$_='(' ^'}';$,='`'|'!';$\=')'^'}';$:='.'^"\~";
$~='@'|'(';$^ =')' ^'[';$/='`'|'.';$_='('^"\}";$,=
'`'|"\!";$\= ')' ^'}';$:='.'^'~';$~='@'|'(';$^=
')'^'[' ;$/= '`'|'.';$_='('^'}';$,='`'|'!'
;$\=')' ^'}'; $:='.'^'~';$~='@'|'(';$^=')'
^'['; $/='`'| '.';$_='('^'}';$,='`'|'!';$\=
"\)"^ '}';$:= '.'^'~';$~='@'|'(';$^=')'^'['
;$/ =('`')| '.';$_='('^'}';$,='`'|'!';$\=
(( ')'))^ '}';$:='.'^'~';$~='@'|'(';$^=
(( ( ')') ))^'[';$/='`'|'.';$_="\("^
(( (( '}'))));$,='`'|'!';$\=')'^
'}' ;( $:)='.'^'~';$~='@'|'(';$^
=')' ^+ '[';$/='`'|'.';$_='('^'}'
;($,)= (( '`'))|'!';$\=')'^"\}";$:=
'.'^'~' ;$~='@'|'(';$^=')'^'[';$/
=('`')| '.';$_='('^'}';$,=('`')|
"\!";$\= ')'^'}';$:='.'^('~');$~=
'@'|"\("; $^= ')'^'[';$/='`'|('.');$_=
'('^'}';$, ="\`"| '!';$\=')'^'}';$:=('.')^
'~';$~='@'|('(');$^= ')'^'[';$/='`'|('.');$_=
'('^'}';$,='`'|"\!"; $\=')'^'}';$:='.'^"\~";
$~='@'|'(';$^=(')')^ '[';$/='`'|'.';$_="\("^
'}';$,='`'|('!');$\= ')'^'}';$:='.'^"\~";$~=
'@'|'(';$^=')'^"\["; $/='`'|'.';$_='('^"\}";
$,='`'|'!';$\="\)"^ '}';$:='.'^'~';$~="\@"|
'(';$^=')'^'[';$/= '`'|'.';$_='('^'}';$,=
'`'|'!';$\="\)"^ '}';$:='.'^'~';$~='@'
|'(';$^=')'^'[' ;$/='`'|'.';$_="\("^
'}';$,='`'|'!'; $\=')'^'}';$:="\."^
'~';$~='@'|'(' ;$^=')'^'[';$/='`'
|'.';$_="\("^ '}';$,='`'|'!';$\
="\)"^ "\}"; $:= '.'^'~';$~="\@"|
'(';$^= ')' ^"\["; $/='`'|"\.";$_=
'('^'}'; ( $,)='`'| '!';$\=')'^'}'
;$:='.'^ '~';$~="\@"| '(';$^=(')')^
"\[";$/= '`'|('.');$_= '('^"\}";$,=
'`'|'!'; $\=')'^'}';$:= '.'^'~';$~=
'@'|"\("; $^=')'^"\["; $/='`'|'.'
;$_=('(')^ '}';$,='`'| ('!');$\=
')'^('}');$:= '.'^'~';$~ =('@')|
'(';$^=')'^"\["; $/='`'|'.'; $_='('
^'}';$,='`'|'!';$\=')' ^'}';$:=('.')^ "\~";
$~='@'|'(';$^=')'^"\["; $/='`'|'.';$_='(' ^((
'}'));$,='`'|('!');$\= ')'^'}';$:='.'^"\~"; $~
='@'|'(';$^=')'^'[';$/ ='`'|'.';$_='('^'}';$, =((
'`'))|'!';$\=')'^"\}"; $:='.'^'~';$~='@'|'(';$^= ')'^
'[';$/='`'|'.';$_='('^'}';$,='`'|'!';$\=')'^'}';$:='.'^'~';
$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='('^'}';$,='`'|"\!";#;#
あるいは、これは:
print sightly( { Shape => 'cricket',
Invert => 1,
BorderWidth => 1,
Reduce => 1,
SourceFile => 'helloworld.pl',
Regex => 1 } );
これを生成します:
''=~('('.'?'.'{'.('`'|('%')).(
'['^"\-").( '`'|'!').('`'|','
).'"'.('[' ^'+').('['^')').(
'`'|')'). ('`'|'.').('['^'/'
).("\{"^ '[').'\\'.'"'.('`'|
"\(").( (( '`'))|'%').('`'|
',') .( '`'|',').("\`"|
'/' ).( '{'^'[').("\["^
(( ',') )).('`'|"\/").(
( (( '[')))^')').(
(( ( '`')))|',').(
'`' | '$').'\\'.''.
'\\' .('`'|"\.").
'\\'. (( '"'))."\;".(
'!'^"\+"). '"'.'}'.')')
;$:=('.')^ '~';$~="\@"|
'(';$^=')' ^'[';$/='`'|
('.');$_= '('^'}';$,=
'`'|'!'; $\=')'^'}'
;$:='.' ^"\~";$~=
'@' |+ ( '(');$^=
')'^ '['; $/='`'|
'.'; $_='(' ^"\}";
($,)= ('`')| "\!";
$\=')'^ "\}"; ($:)
='.'^'~';$~ =('@')| '('
;$^=')'^'[' ;$/=('`')| (
'.');$_='(' ^'}';$,='`'| ((
'!'));$\=')'^'}';$:='.'^'~';#;
リファレンス¶
見た目のよいエンコーディング(Sightly Encoding)¶
見た目のよい文字セットには32文字あります:
! " # $ % & ' ( ) * + , - . / (33-47)
: ; < = > ? @ (58-64)
[ \ ] ^ _ ` (91-96)
{ | } ~ (123-126)
見た目のよい文字列は、この集合からひっぱられた文字だけで 構成されます。
ascii_to_sightly
関数はASCII文字列(0-255)を見た目のよい文字列に 変換します;sightly_to_ascii
はその逆を行います。
関数リファレンス¶
- ascii_to_sightly STRING
-
ascii文字列STRINGを与えられ、見た目のよい文字列を返します。
- sightly_to_ascii STRING
-
見た目のよい文字列STRINGを与えられ、ascii文字列を返します。
- regex_print_sightly STRING
-
ascii文字列STRINGを与えられ、見た目よくエンコードされ、 正規表現に埋め込まれたprintステートメントを持つPerlプログラム を返します。実行するとプログラムはSTRINGを出力します。
- regex_eval_sightly STRING
-
ascii文字列STRINGでPerlプログラムを与えられ、同等で、 正規表現に埋め込まれたevalステートメントを使う、 見た目よくエンコードされたPerlプログラムを返します。
- clean_print_sightly STRING
-
ascii文字列STRINGを与えられ、見た目よくエンコードされた、 evalを通して実行されるprintステートメントを持ったPerl プログラムを返します。
- clean_eval_sightly STRING
-
ascii文字列STRINGでPerlプログラムが与えられ、evalを通して 実行されるevalステートメントを使う、同等の、見た目よく エンコードされたPerlプログラムを返します。
- regex_binmode_print_sightly STRING
-
ascii文字列STRINGを与えられ、binmode(STDOUT)と正規表現に 埋め込まれたprintステートメントを持つ、見た目よくエンコード されたPerlプログラムを返します。実行するとSTRINGを出力します。 STRINGには0-255の範囲の任意の文字が入ることができることに 注意してください。この関数はバイナリ・ファイルを見た目よく エンコードするために使われます。この関数は、正規表現が バイナリのゼロのように見えないために安全ではありません; 代わりに
clean_binmode_print_sightly
を使ってください。 - clean_binmode_print_sightly STRING
-
ascii文字列STRINGを与えられ、binmode(STDOUT)とevalを通して 実行されるprintステートメントを持つ、見た目よくエンコードされた Perlプログラムを返します。実行すると、プログラムはSTRINGを 出力します。 STRINGには0-255の範囲の任意の文字が入ることができることに 注意してください。この関数はバイナリ・ファイルを見た目よく エンコードするために使われます。
- get_builtin_shapes
-
組込まれている形の名前を返します。
- get_eye_shapes
-
eyeシェイプのリストを帰します。eyeシェイプは単に、.eyeという 拡張子を持ち、EyeDrops.pmと同じディレクトリにあるファイルです。
- border_shape SHAPESTRING GAP_LEFT GAP_RIGHT GAP_TOP GAP_BOTTOM WIDTH_LEFT WIDTH_RIGHT WIDTH_TOP WIDTH_BOTTOM
-
形の周りに枠線を引きます。
- invert_shape SHAPESTRING
-
形を反転させます。
- reflect_shape SHAPESTRING
-
形を鏡像にします。
- reduce_shape SHAPESTRING FACT
-
FACTの係数にしたがって形の大きさを縮小します。
- expand_shape SHAPESTRING FACT
-
FACTの係数にしたがって形の大きさを拡大します。
- rotate_shape SHAPESTRING DEGREES RTYPE FLIP
-
時計回りに90、180、270度、形を回転させます。 RTYPE=0 大きな回転されられた形 RTYPE=1 小さな回転させられた形 RTYPE=2 つぶされて回転させられた形 FLIP=1 回転させることに加えて、形をひっくり返します(鏡像にします)。 RTYPE と FLIP は180度には適用されません。
- pour_sightly SHAPESTRING PROGSTRING GAP RFILLVAR COMPACT
-
形を文字列SHAPESTRING、見た目よくエンコードされたプログラムを 文字列PROGSTRING、そして連続する形での空間(GAP)を与えられ、 適切に形が整えられたプログラム文字列を返します。RFILLVARは 埋草変数(filler variable)の配列へのリファレンスです。 埋草変数は2文字:
$
と句読点文字、で構成される適切な Perl変数です。例えばRFILLVAR =[ '$:', '$^', '$~' ]
。 もしCOMPACTが1であれば、コンパクトな見た目のよいエンコーディングを 使います。0であれば、そのままの見た目のよいエンコーディングを 使います。 - sightly HASHREF
-
さまざまな属性について述べたハッシュ・リファレンスHASHREFが 与えられ、適切に整形されたプログラム文字列を返します。
HASHREFに入れることが出来る属性は以下の通りです:
Shape あなたが欲しい図形を記述します。 最初に、組み込まれている形が探され、次に 'eye'シェイプ(EyeDrops.pmと同じディレクトリにある .eyeファイル)が探されます。最後にファイル名が 探されます。 ShapeString 欲しい図形を記述します。 この場合は図形の文字列を指定します。 SourceFile 変換されるソースファイル名 SourceString ファイル名の代わりに文字列を指定します。 BannerString 組込図形'banner'で使われる文字列 Regex ブール値。設定されると、ソースプログラムを 正規表現に埋め込もうとします。複雑なプログラムを 変換するとき、このフラグを設定しないでください。 Compact ブール値。設定されるとコンパクトな見た目のよいエンコーディングを使います。 Print ブール値。設定されると、デフォルトのevalステートメント の代わりにprintステートメントを使います。 (プログラムではなく)テキストファイルを変換するときには このフラグを設定してください。 Binary ブール値。エンコーディングがバイナリファイルであれば設定してください。 Gap 連続する図形の間での行数 Rotate 図形を時計回りに90、180、270度に回転します。 RotateType 0 = 大きく回転した図形 1 = 小さく回転した図形 2 = つぶされ、回転された図形 RotateFlip ブール値。図形を回転させ、さらにひっくり返し (反射)させたければ設定してください。 Reflect 図形を鏡像にします。 Reduce 図形の大きさを小さくします。 Expand 図形の大きさを大きくします。 Invert 図形を反転させます。 Indent 図形をインデントさせます。インデントするための空白の数。 BorderGap 図形の周りに枠線をつけます。枠線と図形との 隙間。 BorderGapLeft,BorderGapRight,BorderGapTop,BorderGapBottom 上記の1つまたは複数でBorderGapを上書きすることが できます。 BorderWidth 図形の周りに枠線をつけます。枠線の幅。 BorderWidthLeft,BorderWidthRight,BorderWidthTop,BorderWidthBottom 上記の1つまたは複数でBorderWidthを上書きすることが できます。 Width .eyeファイル図形では無視されます。組込図形では、 図形に対して適切に、典型的には図形の幅を文字数に 適切に解釈されます。図形が指定されないと、Width文字数の 長方形のブロックが生成されます。 TrapEvalDie ブール値。 生成されたプログラムに閉じた'die $@ if $@'を追加します。 evalコード・ブロックがdie関数を呼ぶとき、 プログラムはdieしません;代わりにdie文字列が$@でevalに 返されます。このフラグを使うことにより、dieを呼び出す プログラムdieを変換することが出来ます。 TrapWarn ブール値。 生成されたプログラムの前に'local $SIG{__WARN__}=sub{};'を 加えます。生成されたプログラムが警告を有効にして実行したとき 'No such signal: SIGHUP at ...'を吐き出すときに使用してください。 FillerVar 'filler variables'(埋草変数)もリストへのリファレンス。 埋草変数は$と句読点文字の2文字で構成されるPerl変数です。 例えば、FillerVar => [ '$:', '$^' ]
図形の指定¶
以下のように図形を指定すると:
sightly( { Shape => 'fred' ...
まず組込のfred
という図形が探されます、そしてEyeDrops はEyeDrops.pmと 同じディレクトリでfred.eyeファイルを探します。 もしShape属性で'/'
や '.'
を指定すると、代わりに、その名前を持つ ファイルが探されます。例えば:
sightly( { Shape => '/tmp/fred.eye' ...
最後に文字列で図形を指定することもできます。例えば:
my $shapestr = <<'FLAMING_OSTRICHES';
#####
#######################
FLAMING_OSTRICHES
sightly ( { ShapeString => $shapestr ...
ソースファイルなしに図形を指定すると:
print sightly( { Shape => 'camel' } );
no-opの埋め草が図形を埋めます。
図形無しにソースファイルを指定すると:
print sightly( { SourceFile => 'helloworld.pl' } );
図形がない、空白や改行がまったくない見た目のよい文字列が生成 されます。この文字列はWidth属性によって、固定幅の行に分解する ことができます:
print sightly( { SourceFile => 'helloworld.pl',
Width => 40 } );
一般的には、組込図形のWidth属性は指定するべきです。Width属性が .eyeファイル図形では無視されることに注意してください。
図形リファレンス¶
組込図形には以下のものがあります:
banner BannerString属性でのテキストの
Linux banner コマンド (/usr/games/banner -w Width)
srcbanner ソーステキストのLinux banner コマンド
(/usr/games/banner -w Width)
siertri シェルピンスキーの三角形 (2**Width 行)
triangle 三角形(幅 Width 文字)
このバージョンのEyeDropsで配布される.eyeファイル図形は以下の通りです:
a "a"の水平方向のバナー
acme オレンジ色が好きなPerl/Parrot Euro-hacker
alien エイリアン (Ton Hospelだと噂されている, 1974年ごろの
Roswell archivesより)
bleach "use Acme::Bleach;"の垂直方向のバナー
buffy "Buffy"の垂直方向のバナー
buffy2 Buffyの天使のような顔
buffy3 ポニーに乗るBuffy
buffy4 "Buffy"の水平方向のバナー
camel ヒトコブラクダ (Camelus dromedarius, one hump)
camel2 もう一つのヒトコブラクダ (use.perl.orgより)
camel3 London.pmのロンドン動物園にいるフタコブラクダ
coffee 一杯のコーヒー
cricket このゲームではオーストラリアが世界チャンピオン
damian Acmeという名前空間はすべて彼の失敗
dipsy テレタビットのディブシー (london.pmのinfobotの名前でもある)
eugene Perl golferのチャンピオン, Eugene van der Pijll
eye 目
gelly パリでのY::E 2003の各セッションでの呼び物の講演者
golfer 1番アイアンを打っているゴルファー
japh JAPHはRandal L Schwartzによって1988年に発案されました
jon 標準的な問題である白いコーヒーカップをホテルの壁にぶつけること
により、Perl 6の開発を蹴り飛ばしてはじめさせました
kermit カエルのカーミット
larry Wall, Larry (Wall, RussであるRussell Wallとの対比
として)
larry2 Ryan Kingによって寄稿されたLarryのマンガ
llama ラマは一緒に繁殖することができるそれほどラクダと密接な
関係があります。(彼らの子供はcamaと呼ばれます)
london 俳句 "A Day in The Life of a London Perl Monger"
merlyn Just another Perl hacker, 別名 Randal L Schwartz
mongers Perl Mongersのロゴ
mosquito 蚊
naw 裸の腕相撲 (Y::E 2002, ミュンヘン)
parrot 初めはエイプリルフールの冗談。冗談が冗談では
なくなってしまった
pgolf Perl Golfのロゴ (`/anickによって招かれた)
pony "Pony"の水平方向のバナー
pony2 ポニーの絵
riding "riding"の水平方向のバナー
santa ゴルフをしているサンタ・クロース
schwern 私のとても嫌なこと(=is my bitch)
simon parrotの発案者
spoon 木で出来たスプーン
tonick Ton Hospel と `/anicとのゴルフ・コンテストの
絵による表現;華やかだけどサンスペスにはならない
tpr "The Perl Review"の垂直方向のバナー
uml UMLダイアグラム
undies 一組のパンツ
window 窓
yanick `/anickの頭のマンガ
yanick2 TPR02の間`/anickが口にしていたこと
yanick3 yanick2の絵によるバージョン
yanick4 図形yanickの省略したバージョン
あなた独自の図形を作るのは簡単です。図形についてのアイデアは、 Ascii ArtあるいはClip Artに検索エンジンを向けてください。 素晴らしい図形ができたら、EyeDropsの将来のバージョンに入れることが できるように送ってください。
バグ¶
一種類の文字を数多く持つ、本当に邪悪な図形は図形生成アルゴリズムを 台無しにするかもしれません。
変換されるプログラムが、正規表現と$_
の利用に注意している場合に のみ、全ての英数字を(Regex => 1によって)除去することが出来ます。 複雑なプログラムを変換するためには、Regex => 0を使わなければなりません。 それは前に見栄えのよくないeval
を吐き出します。
Regex => 1によって生成されたコードは実行するためにPerl 5.005以上を 要求します;前のバージョンで実行すると、エラーメッセージを見ることに なるでしょう: Sequence (?{...) not recognized
。
変換されたプログラムは、eval
の内側で走ります。 これは重大なプログラムで問題を起こすかもしれません。 例えばdie
ステートメントあるいはINIT
ブロックは、トラブルを起こすかも しれません。もし絶望的であれば、TrapEvalDie
とTrapWarn
属性を与え、実行し、その問題を修正するかどうかを見てください。
変換されるプログラムがPerlのフォーマット変数$:
、 $~
あるいは $^
を使っているならば、プログラムによって使われないPerl変数に 明示的にFillerVar
属性を設定する必要があるかもしれません。
Linux /usr/games/bannerは以下の文字をサポートしません:
\ [ ] { } < > ^ _ | ~
Text::Bannerが拡張されているとき、それはLinux bannerコマンドの場所で 使われます。
作者(AUTHOR)¶
Andrew Savige <[email protected]>
参考資料¶
Acmeの Y::E 2002 裸の腕相撲のムービー http://astray.com/tmp/yapcbits3.mov.
Perl Obfuscation Engines, for example, yaoe by Perl Monk mtve, at http://www.perlmonks.com/index.pl?node_id=161087 and http://www.frox25.dhs.org/~mtve/code/eso/perl/yaoe/.
Perl Monks Obfuscationセクション、特に: http://www.perlmonks.com/index.pl?node_id=45213 (Erudilのcamel code) そして http://www.perlmonks.com/index.pl?node_id=176043 (Lenの Spiralling quine) そして http://www.perlmonks.com/index.pl?node_id=188405 (シェルピンスキーの三角形).
The definitive Perl Golf reference is http://perlgolf.sourceforge.net/.
$|--
のイディオム ( 宙返りするラクダのセクションで 利用される) は、このスレッドで "説明されて"います: http://archive.develooper.com/[email protected]/msg01360.html.
Acme::Bleach Acme::Smirch Acme::Buffy Acme::Pony
クレジット(CREDITS)¶
I blame Japhy and Ronald J Kimball and others on the fwp mailing list for exposing the ''=~ trick, Jas Nagra for explaining his Acme::Smirch
module, and Rajah Ankur and Supremely Unorthodox Eric for provoking me.
I would also like to thank Ian Phillipps, Philip Newton, Ryan King, Michael G Schwern, Robert G Werner, Simon Cozens, and others on the fwp mailing list for their advice on ASCII Art, imaging programs, and on which picture of Larry to use.
Thanks also to Mtv Europe, Ronald J Kimball and Eugene van der Pijll for their help in golfing the program in the Twelve Thousand and Thirty Two Camels section. Keith Calvert Ivey also contributed some levity to this section.
Ideas from Adam Antonik, Mtv Europe, Eugene van der Pijll, Ton Hospel and Keith Calvert Ivey were used in the Sierpinski Triangles section.
The jon
shape was derived from: http://www.spidereyeballs.com/os5/set1/small_os5_r06_9705.html. Kudos to Elaine -HFB- Ashton for showing me this.
著作権(=COPYRIGHT)¶
Copyright (c) 2001-2002 Andrew Savige. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
翻訳¶
川合孝典([email protected])