Improve example

This commit is contained in:
Dunya Kirkali 2024-07-07 22:43:32 +02:00
parent db883bbac8
commit 683a64a1e5

View File

@ -1,102 +1,276 @@
== Chapter 5 == Chapter 5: Programming Fractals
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed et pharetra purus. === Introduction
Nullam laoreet consequat maximus. Etiam in ipsum nec est iaculis fringilla vel
nec leo. Mauris a felis ut justo aliquet ultricies vitae quis ligula. Maecenas
et mauris mollis, egestas mauris dapibus, pulvinar lacus. Donec ut libero
ligula. Integer efficitur turpis et efficitur viverra. Etiam vestibulum, ipsum
eget venenatis commodo, mauris purus fermentum lorem, a convallis nunc leo id
ipsum.
=== Part 1 Fractals are complex patterns that are self-similar across different scales. They are fascinating both in their mathematical properties and their visual appeal. In this chapter, we will explore how to program fractals using Elixir, BQN, and Haskell, focusing on some of the most famous fractal patterns such as the Mandelbrot set and the Sierpinski triangle.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum dictum quam === The Mandelbrot Set
nec metus consequat, sit amet consectetur justo posuere. Proin rutrum nibh
nisl, ut condimentum magna hendrerit non. Vestibulum ornare velit mauris, a
auctor magna porttitor ut. Nullam turpis mi, pharetra nec tempor eget, feugiat
id augue. Sed turpis sem, vehicula quis mollis porttitor, feugiat non orci.
Pellentesque mattis tortor et hendrerit dapibus. Nulla scelerisque dui id nunc
pellentesque, a iaculis dui commodo. Ut elit libero, porta sed mattis a,
venenatis eu turpis. Ut ultrices ipsum ut dolor suscipit imperdiet. Duis vitae
mi arcu.
=== Part 1.1 The Mandelbrot set is a set of complex numbers that produces a distinctive and famous fractal shape. The set is defined by iterating the function:
Aenean sed dui risus. Integer vulputate, augue sed mattis consectetur, elit [stem]
erat ornare lacus, quis posuere ex massa eget mi. Curabitur dictum libero nunc, ++++
sed ullamcorper orci bibendum et. Sed nec gravida sapien. Cras eget efficitur z_{n+1} = z_n^2 + c
tortor, vitae mollis nunc. Maecenas imperdiet iaculis varius. Morbi non nibh at ++++
velit congue sodales. Ut semper tincidunt tristique.
=== Part 1.2 ==== Plotting the Mandelbrot Set in Elixir
Fusce sollicitudin mauris at ligula tristique egestas. Phasellus eget diam Let's start with a basic Elixir program to plot the Mandelbrot set.
mauris. Pellentesque congue eros nec venenatis rhoncus. Fusce id accumsan
tellus. Suspendisse non luctus enim, ac tincidunt sem. Aenean sit amet rhoncus
nisi. Pellentesque a scelerisque dolor. Praesent tempor in arcu nec porta. Sed
lorem dui, congue eget vestibulum sed, efficitur pulvinar magna. Quisque tempor
posuere bibendum. Nullam luctus lobortis sem et lacinia. Quisque eros mi,
molestie id elit nec, imperdiet egestas ligula. Curabitur lobortis augue a odio
tincidunt, id gravida tellus rutrum. Vestibulum nec hendrerit orci, nec
fermentum ante.
Nullam placerat sed metus sed interdum. Vestibulum ligula tellus, rhoncus eu [source,elixir]
diam ullamcorper, finibus imperdiet dui. Proin fringilla magna quis sapien ----
scelerisque, id mattis sapien accumsan. Maecenas justo ligula, varius id ligula defmodule Mandelbrot do
a, ultrices accumsan mauris. Etiam ut odio lacus. Nam sed ex libero. Morbi enim def mandelbrot(c, max_iter) do
ex, blandit tempus pellentesque eu, posuere non velit. Proin interdum odio eget iterate(c, 0, 0, max_iter)
arcu blandit faucibus. end
Nam neque ex, euismod et viverra id, luctus at tellus. Suspendisse dapibus defp iterate(_c, _z, n, max_iter) when n >= max_iter, do: n
euismod justo ac posuere. Mauris eget eros arcu. Mauris sit amet feugiat defp iterate(c, z, n, max_iter) when abs(z) > 2, do: n
lectus, eget efficitur sem. Aenean id erat eget metus tincidunt condimentum. defp iterate(c, z, n, max_iter) do
Praesent mollis maximus tortor tempor placerat. Vivamus sed lorem eu libero iterate(c, z*z + c, n + 1, max_iter)
tempus finibus ac vitae massa. end
=== Part 2 def mandelbrot_set(xmin, xmax, ymin, ymax, width, height, max_iter) do
for x <- 0..(width-1), y <- 0..(height-1) do
r = xmin + (xmax - xmin) * x / width
i = ymin + (ymax - ymin) * y / height
c = Complex.new(r, i)
{x, y, mandelbrot(c, max_iter)}
end
end
end
Etiam pretium aliquet tellus, vel facilisis erat sagittis quis. Sed cursus {:ok, _} = :application.ensure_all_started(:gnuplot)
tempus nibh a bibendum. Suspendisse potenti. Cras mattis aliquet est, et rutrum
velit cursus a. Nunc quis nibh sed massa volutpat efficitur non et ante. Ut
tempor sollicitudin massa eget luctus. Sed scelerisque magna dolor, nec viverra
justo consequat vel. Vestibulum condimentum neque in eros eleifend, quis
hendrerit ligula hendrerit. Cras sed porta dui. Vestibulum eu diam vitae lorem
convallis imperdiet. Quisque gravida a turpis vel porta. Nullam cursus, nibh
eget finibus finibus, elit ex volutpat ligula, eget tempor mi metus eu est.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum faucibus
venenatis erat, id malesuada massa fringilla vel. Nam justo dolor, placerat
quis lectus pulvinar, imperdiet iaculis tellus. Vestibulum ut magna risus.
=== Part 2.1 plot = Mandelbrot.mandelbrot_set(-2.0, 1.0, -1.5, 1.5, 800, 800, 256)
:Gnuplot.plot(plot)
----
Curabitur in luctus enim. Aliquam ullamcorper vulputate nunc, quis aliquam ex ==== Plotting the Mandelbrot Set in BQN
semper non. Ut placerat leo vitae tristique lobortis. Morbi feugiat condimentum
sapien et feugiat. Nam commodo tellus id felis placerat consectetur. Duis eu
felis interdum, fermentum turpis sed, accumsan turpis. Ut scelerisque ornare
diam quis mattis. Integer lacinia quam nec lacinia imperdiet. Morbi congue,
massa vitae euismod dapibus, augue odio tincidunt justo, eu volutpat erat justo
a enim. Integer dictum erat non felis interdum, eu elementum mauris eleifend.
Curabitur diam mauris, faucibus ut consectetur sed, bibendum vitae dui. Duis
quis euismod eros.
=== Part 2.2 Here's a BQN program to plot the Mandelbrot set.
Sed in eros aliquam, pellentesque nunc vitae, tempus tellus. Sed tincidunt ex [source,bqn]
leo, in pulvinar purus rutrum a. Duis dictum, lacus ut interdum tincidunt, ----
purus tortor placerat urna, non tristique justo ligula interdum neque. Integer mandelbrot ← {
in quam sit amet mi fringilla molestie sit amet id nisl. Nulla facilisi. Mauris z ← 0
nulla felis, rhoncus a dapibus eget, pellentesque sit amet metus. Sed finibus for n ≤ ⍟ do
eu diam at tempor. Nam porttitor tincidunt est gravida tempor. Donec eleifend if /2≤´|z then n else
sapien sem, sit amet pellentesque lorem viverra id. Morbi ac tortor semper, z +← z×z + ⍟
mollis felis non, accumsan nibh. Duis lectus ex, bibendum eget nibh ac, laoreet end
aliquam metus. Proin dapibus nunc vitae eros malesuada, eu suscipit sem end
bibendum. Phasellus luctus aliquet eros quis posuere. Nullam lectus leo, mattis n
eu arcu eget, interdum finibus ipsum. Fusce imperdiet mauris quis arcu pulvinar }
gravida.
Vestibulum sed sapien vel dui aliquet mollis ac eu nisl. Sed nec ante vel nibh mandelbrotSet ← {
faucibus accumsan. Phasellus tincidunt lorem sit amet dolor egestas molestie. r ← (⍟1+⌊○)∧!⌊○1,1⊸
Pellentesque maximus porta lorem vel ultrices. Pellentesque habitant morbi ⌽⊏ { ⊏⍟(⍟1×⍟1)⊣mandelbrot¨r¨r}¨⊸∾¨⊸∾
tristique senectus et netus et malesuada fames ac turpis egestas. Nullam et }
molestie dui. Maecenas at mi mollis lectus ultrices blandit vel sed arcu. Donec
eget sapien mollis mauris pharetra vulputate. xmin xmax ymin ymax width height max_iter ← ⊏-2 1 ¯1.5 1.5 800 800 256
plot ← mandelbrotSet xmin xmax ymin ymax width height max_iter
plot
----
==== Plotting the Mandelbrot Set in Haskell
Here's a Haskell program to plot the Mandelbrot set.
[source,haskell]
----
import Data.Complex
import Codec.Picture
mandelbrot :: Complex Double -> Int -> Int
mandelbrot c maxIter = length . takeWhile ((<= 2) . magnitude) . take maxIter $ iterate (\z -> z*z + c) 0
mandelbrotSet :: Double -> Double -> Double -> Double -> Int -> Int -> Int -> Image Pixel8
mandelbrotSet xmin xmax ymin ymax width height maxIter = generateImage pixelRenderer width height
where
pixelRenderer x y = let
real = xmin + (xmax - xmin) * fromIntegral x / fromIntegral width
imag = ymin + (ymax - ymin) * fromIntegral y / fromIntegral height
c = real :+ imag
iter = mandelbrot c maxIter
in fromIntegral (255 * iter `div` maxIter)
main :: IO ()
main = savePngImage "mandelbrot.png" (ImageY8 $ mandelbrotSet (-2.0) 1.0 (-1.5) 1.5 800 800 256)
----
=== The Sierpinski Triangle
The Sierpinski triangle is a fractal that is formed by recursively subdividing an equilateral triangle into smaller equilateral triangles.
==== Plotting the Sierpinski Triangle in Elixir
Here is an Elixir program to plot the Sierpinski triangle using recursion.
[source,elixir]
----
defmodule Sierpinski do
def draw_triangle(x, y, size, depth, canvas) when depth == 0 do
triangle = [{x, y}, {x + size / 2, y + size * :math.sqrt(3) / 2}, {x + size, y}]
:egd.filled_polygon(canvas, triangle, :egd.color(:black))
end
def draw_triangle(x, y, size, depth, canvas) do
draw_triangle(x, y, size / 2, depth - 1, canvas)
draw_triangle(x + size / 2, y, size / 2, depth - 1, canvas)
draw_triangle(x + size / 4, y + size * :math.sqrt(3) / 4, size / 2, depth - 1, canvas)
end
end
{:ok, canvas} = :egd.create(800, 800)
Sierpinski.draw_triangle(0, 0, 800, 5, canvas)
:image.create(:png, canvas)
----
==== Plotting the Sierpinski Triangle in BQN
Here is a BQN program to plot the Sierpinski triangle using recursion.
[source,bqn]
----
sierpinski ← {
size depth canvas ← ⍟
if depth = 0 then canvas
else
sierpinski size/2 depth-1 canvas (size/2) size
sierpinski size/2 depth-1 canvas ⊹⌽(size/2) size
sierpinski size/2 depth-1 canvas ⊹⌽(size/4) (size*√3/4)
end
}
sierpinski 800 5 []
----
==== Plotting the Sierpinski Triangle in Haskell
Here is a Haskell program to plot the Sierpinski triangle using recursion.
[source,haskell]
----
import Codec.Picture
drawTriangle :: Int -> Int -> Int -> Int -> Image Pixel8 -> Image Pixel8
drawTriangle x y size depth img
| depth == 0 = drawFilledPolygon img [(x, y), (x + size `div` 2, y + round (fromIntegral size * sqrt 3 / 2)), (x + size, y)] 0
| otherwise = drawTriangle x y (size `div` 2) (depth - 1) .
drawTriangle (x + size `div` 2) y (size `div` 2) (depth - 1) .
drawTriangle (x + size `div` 4) (y + round (fromIntegral size * sqrt 3 / 4)) (size `div` 2) (depth - 1) $ img
main :: IO ()
main = savePngImage "sierpinski.png" (ImageY8 $ drawTriangle 0 0 800 5 (generateImage (\_ _ -> 255) 800 800))
----
=== Julia Sets
Julia sets are another type of fractal, closely related to the Mandelbrot set. They are generated using a similar iterative function but with a fixed complex parameter.
==== Plotting a Julia Set in Elixir
Here's an Elixir program to plot a Julia set.
[source,elixir]
----
defmodule Julia do
def julia(c, z, max_iter) do
iterate(c, z, 0, max_iter)
end
defp iterate(_c, _z, n, max_iter) when n >= max_iter, do: n
defp iterate(c, z, n, max_iter) when abs(z) > 2, do: n
defp iterate(c, z, n, max_iter) do
iterate(c, z*z + c, n + 1, max_iter)
end
def julia_set(c, xmin, xmax, ymin, ymax, width, height, max_iter) do
for x <- 0..(width-1), y <- 0..(height-1) do
r = xmin + (xmax - xmin) * x / width
i = ymin + (ymax - ymin) * y / height
z = Complex.new(r, i)
{x, y, julia(c, z, max_iter)}
end
end
end
c = Complex.new(-0.7, 0.27015)
plot = Julia.julia_set(c, -1.5, 1.5, -1.5, 1.5, 800, 800, 256)
:Gnuplot.plot(plot)
----
==== Plotting a Julia Set in BQN
Here's a BQN program to plot a Julia set.
[source,bqn]
----
julia ← { z c max_iter ← ⍟
iterate ← { z +← z×z + c}
for n ≤ max_iter do
if /2≤´|z then n else iterate z
end
}
juliaSet ← { c xmin xmax ymin ymax width height max_iter ← ⍟
r1 ← (⍟1+⌊○)∧!⌊○1,1⊸
⌽⊏ { ⊏⍟(⍟1×⍟1)⊣julia¨r1¨r1¨c¨max_iter}¨⊸∾¨⊸∾
}
c = 0.27015J¯0.7
xmin xmax ymin ymax width height max_iter ← ⊏-1.5 1.5 ¯1.5 1.5 800 800 256
plot ← juliaSet c xmin xmax ymin ymax width height max_iter
plot
----
==== Plotting a Julia Set in Haskell
Here's a Haskell program to plot a Julia set.
[source,haskell]
----
import Data.Complex
import Codec.Picture
julia :: Complex Double -> Complex Double -> Int -> Int
julia c z0 maxIter = length . takeWhile ((<= 2) . magnitude) . take maxIter $ iterate (\z -> z*z + c) z0
juliaSet :: Complex Double -> Double -> Double -> Double -> Double -> Int -> Int -> Int -> Image Pixel8
juliaSet c xmin xmax ymin ymax width height maxIter = generateImage pixelRenderer width height
where
pixelRenderer x y = let
real = xmin + (xmax - xmin) * fromIntegral x / fromIntegral width
imag = ymin + (ymax - ymin) * fromIntegral y / fromIntegral height
z0 = real :+ imag
iter = julia c z0 maxIter
in fromIntegral (255 * iter `div` maxIter)
main :: IO ()
main = savePngImage "julia.png" (ImageY8 $ juliaSet (0.27015 :+ (-0.7)) (-1.5) 1.5 (-1.5) 1.5 800 800 256)
----
=== Conclusion
Fractals are an excellent way to understand the beauty and complexity of mathematical patterns. By programming these patterns, we not only appreciate their aesthetic appeal but also gain insights into their mathematical properties.
=== Further Reading
For more information on fractals and programming, check out the following resources:
* https://en.wikipedia.org/wiki/Mandelbrot_set[Mandelbrot Set - Wikipedia]
* https://en.wikipedia.org/wiki/Sierpinski_triangle[Sierpinski Triangle - Wikipedia]
* https://en.wikipedia.org/wiki/Julia_set[Julia Set - Wikipedia]
=== References
1. Mandelbrot, B. B. (1982). _The Fractal Geometry of Nature_. New York: W.H. Freeman and Company.
2. Peitgen, H.-O., Jürgens, H., & Saupe, D. (1992). _Chaos and Fractals: New Frontiers of Science_. New York: Springer.
=== Appendix
==== Image and Code Credits
* Mandelbrot Set: Code adapted from various fractal tutorials in Elixir, BQN, and Haskell.
* Sierpinski Triangle: Code adapted from various fractal tutorials in Elixir, BQN, and Haskell.
* Julia Set: Code adapted from various fractal tutorials in Elixir, BQN, and Haskell.