L-system: Difference between revisions

10,590 bytes added ,  24 days ago
m
Quackery solution moved into correct alphabetical order
m (Small correction)
m (Quackery solution moved into correct alphabetical order)
 
(21 intermediate revisions by 10 users not shown)
Line 86:
 
:* Wikipedia: [[wp:L-system|L-system]]
 
=={{header|ALGOL 68}}==
{{libheader|ALGOL 68-l-system}}
Note, the Algol 68 L-System library source code is on a separate page on Rosetta Code - follow the above link and then to the Talk page.
<syntaxhighlight lang="algol68">
BEGIN # Example of L-System evaluation and interpretation #
 
PR read "lsystem.incl.a68" PR # include L-System utilities #
 
# task rabbit population example #
LSYSTEM rabbit population = ( "I", ( "I" -> "M"
, "M" -> "MI"
)
);
INT young := 0, old := 0;
STRING result = rabbit population EVAL 5;
result INTERPRET ( ( CHAR c )VOID: IF c = "I" THEN young +:= 1 ELSE old +:= 1 FI );
 
print( ( "After 5 iterations there are ", whole( old, 0 ), " old rabbits and "
, whole( young, 0 ), " young ones (", result, ")", newline
)
)
 
END
</syntaxhighlight>
{{out}}
<pre>
After 5 iterations there are 5 old rabbits and 3 young ones (MIMMIMIM)
</pre>
 
=={{header|FreeBASIC}}==
L-system functionality as a Role that may be mixed in to a scalar.
 
<syntaxhighlight lang="vbnet">Sub Lindenmayer(s As String, rules() As String, count As Integer)
Dim As Integer i, j, k, found
Dim As String nxt, c, rep
For i = 0 To count
Print s
nxt = ""
For j = 1 To Len(s)
c = Mid(s, j, 1)
found = 0
For k = Lbound(rules) To Ubound(rules) Step 2
If c = rules(k) Then
rep = rules(k + 1)
found = 1
Exit For
End If
Next k
nxt &= Iif(found = 1, rep, c)
Next j
s = nxt
Next i
End Sub
 
Dim As String rules(3) = {"I", "M", "M", "MI"}
Lindenmayer("I", rules(), 5)
 
Sleep</syntaxhighlight>
{{out}}
<pre>I
M
MI
MIM
MIMMI
MIMMIMIM</pre>
Also see:</br>
[[Dragon_curve#FreeBASIC]]</br>
[[Hilbert_curve#FreeBASIC]]</br>
[[Koch_curve#FreeBASIC]]</br>
[[Peano_curve#FreeBASIC]]</br>
[[Penrose_tiling#FreeBASIC]]</br>
[[Sierpinski_curve#FreeBASIC]]</br>
[[Sierpinski_arrowhead_curve#FreeBASIC]]</br>
[[Sierpinski_square_curve#FreeBASIC]]</br>
among others...
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// L-system. Nigel Galloway: April 1th., 2024
type rabbit= M|I
let rules=function I->[M] |M->[M;I]
let L axiom rules=Seq.unfold(fun n->Some(n,n|>Seq.map(rules)|>Seq.concat)) axiom
L [I] rules|>Seq.take 6|>Seq.iter(fun n->n|>Seq.iter(printf "%A");printfn "")
</syntaxhighlight>
{{out}}
<pre>
I
M
MI
MIM
MIMMI
MIMMIMIM
</pre>
 
=={{header|Fōrmulæ}}==
Line 105 ⟶ 199:
[[File:Fōrmulæ - L-system 03.png]]
 
'''Test case 1. Koch's snowflake'''
 
[[File:Fōrmulæ - L-system - Koch's snowflake 01.png]]
 
[[File:Fōrmulæ - L-system - Koch's snowflake 02.png]]
 
'''Test case 2. Sierpiński curve'''
 
[[File:Fōrmulæ - L-system - Sierpiński curve 01.png]]
 
[[File:Fōrmulæ - L-system - Sierpiński curve 02.png]]
 
'''Test case 3. Peano curve'''
 
[[File:Fōrmulæ - L-system - Peano Curve 01.png]]
 
[[File:Fōrmulæ - L-system - Peano Curve 02.png]]
 
'''Test case 4. Hilbert curve'''
 
[[File:Fōrmulæ - L-system - Hilbert curve 01.png]]
 
[[File:Fōrmulæ - L-system - Hilbert curve 02.png]]
 
 
=={{header|Julia}}==
Julia has the Lindenmeyer.jl package downloadable via the package manager in the usual fashion.
<syntaxhighlight lang="julia">using Lindenmayer
 
scurve = LSystem(Dict("F" => "F+F--F+F"), "8F--F--F") # 8 sets stroke width to 8 px
drawLSystem(scurve,
forward = 16,
turn = 60,
startingx = -200,
startingy = 100,
iterations = 3,
backgroundcolor = "white",
filename = "kochsnow.png",
showpreview = true
)
 
</syntaxhighlight>{{out}}
[[File:Kochsnowflakefractal.png|thumb|center|alt=fractal image|Koch Snowflake]]
 
=={{header|Phix}}==
Just the generic part:
<syntaxhighlight lang="phix">
function lindenmayer(string s, sequence rules, integer count)
sequence {chars, reps} = columnize(rules)
for i=1 to count do
string nxt = ""
for c in s do
integer k = find(c,chars)
nxt &= iff(k?reps[k]:c)
end for
s = nxt
end for
return s
end function
</syntaxhighlight>
Invoke using eg <code><nowiki>lindenmayer("I",{{'I',"M"},{'M',"MI"}},5)</nowiki></code> which yields "MIMMIMIM"
 
=={{header|Quackery}}==
 
This solution reproduces the method used in other, pre-existing, tasks including [[Cantor set#Quackery|Cantor set]], [[Hilbert curve#Quackery|Hilbert curve]], [[Padovan sequence#Quackery|Padovan sequence]], [[Peano curve#Quackery|Peano curve]], [[Sierpinski curve#Quackery|Sierpinski curve]], and [[Sierpinski square curve#Quackery|Sierpinski square curve]].
 
The alphabet is a set of single character (of necessity) Quackery words, which are uppercase by convention (to distinguish them from, and avoid conflict with, other Quackery words, which are exclusively lowercase by convention.)
 
Rules are Quackery words in the alphabet which return a string as a result. The word <code>expand</code> takes an axiom (a string of rules) and applies the rule associated with each character sequentially and concatenates the returned strings. In other words it performs a single iteration of the L-system. The word <code>times</code> can be used to perform a specified number of iterations.
 
This example illustrates this method for the life cycle of the Gallifreyan Fibonacci Rabbit, which lives forever, matures after the first cycle, and thereafter [https://tardis.fandom.com/wiki/Bi-generation bi-generates], producing a single kitten (i.e. an immature rabbit) on every cycle.
 
<syntaxhighlight lang="Quackery"> [ $ "" swap witheach
[ nested quackery join ] ] is expand ( $ --> $ )
 
[ $ "M" ] is I ( --> $ )
[ $ "MI" ] is M ( --> $ )
 
$ "I" 5 times expand echo$</syntaxhighlight>
 
{{out}}
 
<pre>MIMMIMIM</pre>
 
Interpreting the resulting string is implemented by stepping through each character of the string and applying the actions associated with each character in the alphabet. In most of the tasks listed above this is achieved with the Quackery equivalent of a switch statement. Here, the action is to increment either a count of the number of mature rabbits, or the number of kittens, both of which are maintained on the stack, so <code>char I = if dip 1+</code> is sufficient.
 
<syntaxhighlight lang="Quackery"> [ 0 0 rot witheach
[ char I = if dip 1+ ]
say "Rabbits: " echo cr
say "Kittens: " echo cr ] is countrabbits ( $ --> )
 
$ "I" 5 times expand countrabbits</syntaxhighlight>
 
{{out}}
 
<pre>Rabbits: 5
Kittens: 3</pre>
 
=={{header|Raku}}==
L-system functionality as a Role that may be mixed in to a scalar.
 
<syntaxhighlight lang="raku" line># L-system functionality
role Lindenmayer {
has %.rules;
method succ {
self.comb.map( { %!rules{$^c} // $c } ).join but Lindenmayer(%!rules)
}
}
 
# Testing
my $rabbits = 'I' but Lindenmayer({I => 'M', M => 'MI'});
 
.say for $rabbits++ xx 6;</syntaxhighlight>
{{out}}
<pre>I
M
MI
MIM
MIMMI
MIMMIMIM</pre>
 
Also see:</br>
[[Dragon_curve#Raku]]</br>
[[Hilbert_curve#Raku]]</br>
[[Koch_curve#Raku]]</br>
[[Peano_curve#Raku]]</br>
[[Penrose_tiling#Raku]]</br>
[[Sierpinski_curve#Raku]]</br>
[[Sierpinski_arrowhead_curve#Raku]]</br>
[[Sierpinski_square_curve#Raku]]</br>
among others...
 
=={{header|RPL}}==
≪ SWAP → rules
≪ 1 SWAP '''FOR''' a
→ in
≪ ""
1 in '''FOR''' b
in b DUP SUB
1 rules SIZE '''FOR''' c
rules c GET
'''IF''' DUP2 1 GET == '''THEN'''
SWAP DROP 2 GET
rules SIZE 'c' STO
'''ELSE''' DROP '''END'''
'''NEXT'''
+
'''NEXT'''
'''NEXT'''
≫ ≫ ´<span style="color:blue">LSYS</span>' STO
 
"I" {{"I" "M"} {"M" "MI"}} 5 <span style="color:blue">LSYS</span>
{{out}}
<pre>
1: "MIMMIMIM"
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-lsystem}}
{{libheader|Wren-fmt}}
The source code for the Wren-lsystem module is available on this site by clicking the above link and then navigating to the Talk page.
 
We can use this to generate the results for the rabbit population example as follows.
<syntaxhighlight lang="wren">import "./lsystem" for LSystem, Rule
import "./fmt" for Fmt
 
var lsys = LSystem.new(
["I", "M"], // variables
[], // constants
"I", // axiom
[ // rules
Rule.new("I", "M"),
Rule.new("M", "MI")
]
)
 
System.print("Step String")
System.print("---- --------")
var steps = lsys.listSteps(5)
for (i in 0..5) Fmt.print("$-4d $8m", i, steps[i])</syntaxhighlight>
 
{{out}}
<pre>
Step String
---- --------
0 I
1 M
2 MI
3 MIM
4 MIMMI
5 MIMMIMIM
</pre>
 
{{libheader|DOME}}
We can also use it to draw a curve such as the Koch Snowflake.
<syntaxhighlight lang="wren">import "graphics" for Canvas, Color
import "dome" for Window
import "math" for Math
import "./lsystem" for LSystem, Rule
 
var TwoPi = Num.pi * 2
 
class KochSnowflake {
construct new(width, height, back, fore) {
Window.title = "Koch Snowflake"
Window.resize(width, height)
Canvas.resize(width, height)
_w = width
_h = height
_bc = back
_fc = fore
}
 
init() {
Canvas.cls(_bc)
var cx = 80
var cy = 270
var theta = Num.pi/2
var h = 9
var lsys = LSystem.new(
["F"], // variables
["+", "-"], // constants
"F--F--F", // axiom
[Rule.new("F", "F+F--F+F")], // rules
Num.pi / 3 // angle (60 degrees in radians)
)
var result = lsys.iterate(3)
var operations = {
"F": Fn.new {
var newX = cx + h*Math.sin(theta)
var newY = cy - h*Math.cos(theta)
Canvas.line(cx, cy, newX, newY, _fc, 2)
cx = newX
cy = newY
},
"+": Fn.new {
theta = (theta + lsys.angle) % TwoPi
},
"-": Fn.new {
theta = (theta - lsys.angle) % TwoPi
}
}
LSystem.execute(result, operations)
}
 
update() {}
 
draw(alpha) {}
}
 
var Game = KochSnowflake.new(400, 400, Color.blue, Color.yellow)</syntaxhighlight>
 
{{out}}
[[File:Wren-Koch_Snowflake.png]]
1,462

edits