Firstly, note to self: it's '-may'er, not '-mey'er.
So, Josh, stop spelling it wrong all over the place!
Next. There are some issues with the code.
Building and discarding ginormous arrays of hundreds of thousands of elements
is not really 'using the stack properly'.
When I tried to implement the plant example,
http://en.wikipedia.org/wiki/L-system#Example_7:_Fractal_plant I wanted to get more detail than the wikipedia picture.
But when I cranked it up to 7 iterations,
Poof! Stackoverflow. Seems to happen around 65535.
So this example extends the plant example,
by substituting but not expanding the subprocedures.
I also added a little nondeterminism experiment
and a UNIX-only (sorry) randomized seed.
%"Safe" seed randomizer
{ 0 4{ 8 bitshift (/dev/random)(r)file read pop add }repeat srand } stopped
{ usertime 10 { %can't open file, chop some vegetables
save 128 string 99 2 getinterval 1 vmreclaim pop restore
} repeat usertime 8 bitshift add srand } if
/setrandcolor {
rand 100 mod 400 div %red to green
rand 100 mod 300 div .4 add % .4 .. .73 medium sat
rand 100 mod 300 div .2 add % .2 .. .53 dark to medium
sethsbcolor
} def
%Stochastic control structure "randif-block"
%eg. laboriously simulate a 4-sided die
% false .25 { 1 } randif % 25% chance
% .33 { 2 } randif % 25/75% = 33% chance remaining
% .5 { 3 } randif % 25/50% = 50% chance remaining
% 1 { 4 } randif % if all else fails, 100% chance
% pop % randif yields a bool indicating if anything executed
%
% bool prob proc randif bool
/randif {
3 2 roll { %ifelse a previous proc has already executed
pop pop true
}{
exch % proc prob
1 exch div cvi % invert prob to number of "chances"
rand exch mod % chop random int by chances
0 eq {
exec true
}{
pop false
} ifelse
} ifelse
} def
<< %start constructing a dictionary
/DDOLstep { [ exch {
dup type /arraytype eq {
DDOLstep
}{
currentdict exch
2 copy known {
get exec
}{
exch pop
} ifelse
} ifelse
On Sat, 28 Jul 2012 14:13:16 -0700 (PDT), luser- -droog wrote:
> ... So parameters evaluate to numbers and then
> just occur in the arrays and get used
> where needed. ...
In my book, the terms parameter, index, and (numerical) variable have
always been pretty much interchangeable :-) . HTH. Cheers, -- tlvp
-- Avant de repondre, jeter la poubelle, SVP.
On Saturday, July 28, 2012 8:59:54 PM UTC-5, tlvp wrote:
> On Sat, 28 Jul 2012 14:13:16 -0700 (PDT), luser- -droog wrote:
> > ... So parameters evaluate to numbers and then
> > just occur in the arrays and get used
> > where needed. ...
> In my book, the terms parameter, index, and (numerical) variable have
> always been pretty much interchangeable :-) . HTH. Cheers, -- tlvp
Well, yeah. It isn't radically different in that respect.
But it does mean that the productions need to be partially
evaluated at each step. In other cases, the parameter may
select among several productions, as well as evaluate in the selected procedure.
It turns out I didn't implement the brackets correctly
in that last one, so here's the fixup.
This one was really boring until I realized
that the angle wasn't changing. That fixed,
this one is really really cool.
A simple spiral:
- Forward
- Turn Right
- Forward
- Turn Right
But what if it does little curve instead of
going straight forward?
What if it turns a different angle?
What if it takes an extra odd step?
What then, Huh?
This!
[Hacker Note. Since this one's tail-recursive,
I took out all the Dexec stuff. It's smaller in memory
as flat arrays.]
% x y z -> X Y
/project {
3 dict begin
/z exch def
/y exch def
/x exch def
1 ez z sub div
x ez mul z ex mul sub
1 index mul
y ez mul z ey mul sub
3 2 roll mul
end } def
{
/RU { /a exch def
[[a cos a sin 0 0]
[a sin neg a cos 0 0]
[0 0 1 0]
[0 0 0 1]] } def
/RL { /a exch def
[[a cos 0 a sin neg 0]
[0 1 0 0]
[a sin 0 a cos 0]
[0 0 0 1]] } def
/RH { /a exch def
[[1 0 0 0]
[0 a cos a sin neg 0]
[0 a sin a cos 0]
[0 0 0 1]] } def
} pop
/Turtle <<
/RU { /a exch def
[[a cos a sin 0]
[a sin neg a cos 0]
[0 0 1]] }
/RL { /a exch def
[[a cos 0 a sin neg]
[0 1 0 ]
[a sin 0 a cos ]] }
/RH { /a exch def
[[1 0 0 ]
[0 a cos a sin neg]
[0 a sin a cos ]] }
/F { State /P 2 copy get
State /V get 0 get %pos H^
[R R R] {mul} vop {add} vop %pos+R*H^
dup
aload pop project
pen? {lineto
currentpoint stroke moveto
/flushpage where {pop flushpage} if
}{moveto} ifelse
put
}
/renormalize {
0 1 2 {
State /V get exch 2 copy get
dup mag [ exch dup dup ] {div} vop
put
} for
}
/rot {
{
%pstack
exch %transpose exch % H L U as column vectors
matmul
%transpose %and flip 'em back to make H easy to crack in /F
exit
[ 3 1 roll % [ V R
exch { % [ .. R Vi
%1 array astore transpose
1 index matmul % [ .. R Vi*R
transpose 0 get
exch % [ .. Vi*R R
} forall
pop ]
%dup ==()=
exit } loop
}
/fixup {}%{ renormalize }
/+ { State /V 2 copy get T RU rot put fixup } % turn left
/- { State /V 2 copy get T neg RU rot put fixup } % turn right
/& { State /V 2 copy get T RL rot put fixup } % pitch down
/^ { State /V 2 copy get T neg RL rot put fixup } % pitch up
/, { State /V 2 copy get T RH rot put fixup } % roll left
/. { State /V 2 copy get T neg RH rot put fixup } % roll left
/| { State /V 2 copy get 180 RU rot put fixup } % about face
>> def
/DOL {
[ exch {
dup type /arraytype eq {
DOL
}{
currentdict exch 2 copy known {
get %aload pop
}{
exch pop
} ifelse
} ifelse
} forall ] cvx
<<
/R 20 % "radius" of movement
/T 90 % rotation angle
/pen? true
>> begin
<<
/A { B - F + C F C + F - D & F ^ D - F + & & C F C + F + B . . }
/B { A & F ^ C F B ^ F ^ D ^ ^ - F - D ^ | F ^ B | F C ^ F ^ A . . }
/C { | D ^ | F ^ B - F + C ^ F ^ A & & F A & F ^ C + F + B ^ F ^ D . . }
/D { | C F B - F + B | F A & F ^ A & & F B - F + B | F C . . }
>> begin
<< %T=45
/A { B B B B }
/B { F + C + }
/C { - & A ^ + }
>> pop%begin
<< %T=45
/A { F B - - F B - - F B - - F B - - C }
/B { + . . + A - , , - }