Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
6
Task/Brownian-tree/00-META.yaml
Normal file
6
Task/Brownian-tree/00-META.yaml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
category:
|
||||
- Raster graphics operations
|
||||
- Geometry
|
||||
from: http://rosettacode.org/wiki/Brownian_tree
|
||||
note: Fractals
|
||||
11
Task/Brownian-tree/00-TASK.txt
Normal file
11
Task/Brownian-tree/00-TASK.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
;Task:
|
||||
Generate and draw a [[wp:Brownian tree|Brownian Tree]].
|
||||
|
||||
|
||||
A Brownian Tree is generated as a result of an initial seed, followed by the interaction of two processes.
|
||||
|
||||
# The initial "seed" is placed somewhere within the field. Where is not particularly important; it could be randomized, or it could be a fixed point.
|
||||
# Particles are injected into the field, and are individually given a (typically random) motion pattern.
|
||||
# When a particle collides with the seed or tree, its position is fixed, and it's considered to be part of the tree.
|
||||
|
||||
<br>Because of the lax rules governing the random nature of the particle's placement and motion, no two resulting trees are really expected to be the same, or even necessarily have the same general shape. <br><br>
|
||||
431
Task/Brownian-tree/ATS/brownian-tree.ats
Normal file
431
Task/Brownian-tree/ATS/brownian-tree.ats
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
(* This program pours all the particles onto the square at once, with
|
||||
one of them as seed, and then lets the particles move around.
|
||||
|
||||
Compile with
|
||||
patscc -std=gnu2x -D_GNU_SOURCE -g -O3 -DATS_MEMALLOC_LIBC brownian_tree_task.dats
|
||||
|
||||
You may need the -D_GNU_SOURCE to get a declaration of the
|
||||
random(3) function. *)
|
||||
(*------------------------------------------------------------------*)
|
||||
|
||||
%{^
|
||||
#include <stdlib.h>
|
||||
%}
|
||||
|
||||
#include "share/atspre_staload.hats"
|
||||
|
||||
#define NIL list_nil ()
|
||||
#define :: list_cons
|
||||
|
||||
extern castfn lint2int : {i : int} lint i -<> int i
|
||||
implement g1int2int<lintknd,intknd> i = lint2int i
|
||||
|
||||
extern fn random () : [i : nat] lint i = "mac#random"
|
||||
extern fn srandom (seed : uint) : void = "mac#srandom"
|
||||
extern fn atoi (s : string) : int = "mac#atoi"
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
|
||||
datatype grid_position =
|
||||
| Wall
|
||||
| Empty
|
||||
| Sticky
|
||||
| Freely_moving
|
||||
|
||||
fn {}
|
||||
grid_position_equal
|
||||
(x : grid_position,
|
||||
y : grid_position)
|
||||
:<> bool =
|
||||
case+ x of
|
||||
| Wall () => (case+ y of Wall () => true | _ => false)
|
||||
| Empty () => (case+ y of Empty () => true | _ => false)
|
||||
| Sticky () => (case+ y of Sticky () => true | _ => false)
|
||||
| Freely_moving () =>
|
||||
(case+ y of Freely_moving () => true | _ => false)
|
||||
|
||||
fn {}
|
||||
grid_position_notequal
|
||||
(x : grid_position,
|
||||
y : grid_position)
|
||||
:<> bool =
|
||||
~grid_position_equal (x, y)
|
||||
|
||||
overload = with grid_position_equal
|
||||
overload <> with grid_position_notequal
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
|
||||
abstype container (w : int, h : int) = ptr
|
||||
|
||||
local
|
||||
|
||||
typedef _container (w : int, h : int) =
|
||||
'{M = matrixref (grid_position, w, h),
|
||||
w = int w,
|
||||
h = int h}
|
||||
|
||||
in (* local *)
|
||||
|
||||
assume container (w, h) = _container (w, h)
|
||||
|
||||
fn {}
|
||||
container_make
|
||||
{w, h : pos}
|
||||
(w : int w,
|
||||
h : int h)
|
||||
: container (w, h) =
|
||||
'{M = matrixref_make_elt<grid_position> (i2sz w, i2sz h, Empty),
|
||||
w = w, h = h}
|
||||
|
||||
fn {}
|
||||
container_width
|
||||
{w, h : pos}
|
||||
(C : container (w, h))
|
||||
: int w =
|
||||
C.w
|
||||
|
||||
fn {}
|
||||
container_height
|
||||
{w, h : pos}
|
||||
(C : container (w, h))
|
||||
: int h =
|
||||
C.h
|
||||
|
||||
fn {}
|
||||
container_get_at
|
||||
{w, h : pos}
|
||||
(C : container (w, h),
|
||||
x : intBtwe (~1, w),
|
||||
y : intBtwe (~1, h))
|
||||
: grid_position =
|
||||
let
|
||||
macdef M = C.M
|
||||
in
|
||||
if (0 <= x) * (x < C.w) * (0 <= y) * (y < C.h) then
|
||||
M[x, C.h, y]
|
||||
else
|
||||
Wall
|
||||
end
|
||||
|
||||
fn
|
||||
container_set_at
|
||||
{w, h : pos}
|
||||
(C : container (w, h),
|
||||
x : intBtw (0, w),
|
||||
y : intBtw (0, h),
|
||||
gpos : grid_position)
|
||||
: void =
|
||||
let
|
||||
macdef M = C.M
|
||||
in
|
||||
M[x, C.h, y] := gpos
|
||||
end
|
||||
|
||||
end (* local *)
|
||||
|
||||
overload width with container_width
|
||||
overload height with container_height
|
||||
overload [] with container_get_at
|
||||
overload [] with container_set_at
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
|
||||
fn
|
||||
random_direction () :
|
||||
@(intBtwe (~1, 1), intBtwe (~1, 1)) =
|
||||
let
|
||||
val r1 = random ()
|
||||
val r2 = random ()
|
||||
val dx : intBtwe (0, 2) = g1i2i (r1 \nmod 3)
|
||||
and dy : intBtwe (0, 2) = g1i2i (r2 \nmod 3)
|
||||
in
|
||||
@(pred dx, pred dy)
|
||||
end
|
||||
|
||||
fn
|
||||
in_sticky_position
|
||||
{w, h : pos}
|
||||
(C : container (w, h),
|
||||
x : intBtw (0, w),
|
||||
y : intBtw (0, h))
|
||||
: bool =
|
||||
(C[pred x, pred y] = Sticky () ||
|
||||
C[pred x, y] = Sticky () ||
|
||||
C[pred x, succ y] = Sticky () ||
|
||||
C[succ x, pred y] = Sticky () ||
|
||||
C[succ x, y] = Sticky () ||
|
||||
C[succ x, succ y] = Sticky () ||
|
||||
C[x, pred y] = Sticky () ||
|
||||
C[x, succ y] = Sticky ())
|
||||
|
||||
fn
|
||||
find_placement_for_another_particle
|
||||
{w, h : pos}
|
||||
(C : container (w, h))
|
||||
: @(intBtw (0, w), intBtw (0, h)) =
|
||||
let
|
||||
val w = width C and h = height C
|
||||
|
||||
fun
|
||||
loop () : @(intBtw (0, w), intBtw (0, h)) =
|
||||
let
|
||||
val r1 = random ()
|
||||
val r2 = random ()
|
||||
val x : intBtw (0, w) = g1i2i (r1 \nmod w)
|
||||
and y : intBtw (0, h) = g1i2i (r2 \nmod h)
|
||||
in
|
||||
if C[x, y] <> Empty () then
|
||||
loop ()
|
||||
else
|
||||
@(x, y)
|
||||
end
|
||||
in
|
||||
loop ()
|
||||
end
|
||||
|
||||
fn
|
||||
move_particles
|
||||
{w, h : pos}
|
||||
(C : container (w, h),
|
||||
particles : &List0 @(intBtw (0, w), intBtw (0, h)) >> _)
|
||||
: void =
|
||||
let
|
||||
typedef coords = @(intBtw (0, w), intBtw (0, h))
|
||||
|
||||
fun
|
||||
loop {n : nat} .<n>.
|
||||
(particles : list (coords, n),
|
||||
new_lst : List0 coords)
|
||||
: List0 coords =
|
||||
case+ particles of
|
||||
| NIL => new_lst
|
||||
| @(x0, y0) :: tl =>
|
||||
let
|
||||
val @(dx, dy) = random_direction ()
|
||||
val x1 = x0 + dx and y1 = y0 + dy
|
||||
in
|
||||
if C[x1, y1] = Empty () then
|
||||
let
|
||||
val () = assertloc (0 <= x1)
|
||||
val () = assertloc (x1 < width C)
|
||||
val () = assertloc (0 <= y1)
|
||||
val () = assertloc (y1 < height C)
|
||||
in
|
||||
C[x1, y1] := C[x0, y0];
|
||||
C[x0, y0] := Empty ();
|
||||
loop (tl, @(x1, y1) :: new_lst)
|
||||
end
|
||||
else
|
||||
(* Our rule is: if there is anything where it WOULD have
|
||||
moved to, then the particle does not move. *)
|
||||
loop (tl, @(x0, y0) :: new_lst)
|
||||
end
|
||||
in
|
||||
particles := loop (particles, NIL)
|
||||
end
|
||||
|
||||
fn
|
||||
find_which_particles_are_stuck
|
||||
{w, h : pos}
|
||||
(C : container (w, h),
|
||||
particles : &List0 @(intBtw (0, w), intBtw (0, h)) >> _)
|
||||
: void =
|
||||
(* Our rule is: if a particle is next to something that ALREADY was
|
||||
stuck, then it too is stuck. Otherwise it remains free. *)
|
||||
let
|
||||
typedef coords = @(intBtw (0, w), intBtw (0, h))
|
||||
|
||||
fun
|
||||
loop {n : nat} .<n>.
|
||||
(particles : list (coords, n),
|
||||
new_lst : List0 coords)
|
||||
: List0 coords =
|
||||
case+ particles of
|
||||
| NIL => new_lst
|
||||
| @(x, y) :: tl =>
|
||||
if in_sticky_position (C, x, y) then
|
||||
begin
|
||||
C[x, y] := Sticky ();
|
||||
loop (tl, new_lst)
|
||||
end
|
||||
else
|
||||
loop (tl, @(x, y) :: new_lst)
|
||||
in
|
||||
particles := loop (particles, NIL)
|
||||
end
|
||||
|
||||
fn
|
||||
pour_particles
|
||||
{w, h : pos}
|
||||
{n : nat}
|
||||
(C : container (w, h),
|
||||
n : int n,
|
||||
free_particles : &List0 @(intBtw (0, w), intBtw (0, h))?
|
||||
>> List0 @(intBtw (0, w), intBtw (0, h)))
|
||||
: void =
|
||||
if n = 0 then
|
||||
free_particles := NIL
|
||||
else
|
||||
let
|
||||
typedef coords = @(intBtw (0, w), intBtw (0, h))
|
||||
|
||||
fun
|
||||
loop {i : nat | i <= n - 1}
|
||||
.<(n - 1) - i>.
|
||||
(particles : list (coords, i),
|
||||
i : int i)
|
||||
: list (coords, n - 1) =
|
||||
if i = pred n then
|
||||
particles
|
||||
else
|
||||
let
|
||||
val @(x, y) = find_placement_for_another_particle C
|
||||
in
|
||||
C[x, y] := Freely_moving;
|
||||
loop (@(x, y) :: particles, succ i)
|
||||
end
|
||||
|
||||
val @(xseed, yseed) = find_placement_for_another_particle C
|
||||
in
|
||||
C[xseed, yseed] := Sticky ();
|
||||
free_particles := loop (NIL, 0)
|
||||
end
|
||||
|
||||
fn
|
||||
go_until_all_particles_are_stuck
|
||||
{w, h : pos}
|
||||
(C : container (w, h),
|
||||
free_particles : List0 @(intBtw (0, w), intBtw (0, h)))
|
||||
: void =
|
||||
let
|
||||
typedef coords = @(intBtw (0, w), intBtw (0, h))
|
||||
|
||||
fun
|
||||
loop (free_particles : &List0 coords >> _) : void =
|
||||
case+ free_particles of
|
||||
| NIL => ()
|
||||
| _ :: _ =>
|
||||
begin
|
||||
move_particles (C, free_particles);
|
||||
find_which_particles_are_stuck (C, free_particles);
|
||||
loop free_particles
|
||||
end
|
||||
|
||||
var free_particles : List0 coords = free_particles
|
||||
in
|
||||
find_which_particles_are_stuck (C, free_particles);
|
||||
loop free_particles
|
||||
end
|
||||
|
||||
fn
|
||||
build_a_tree {w, h : pos}
|
||||
{n : nat}
|
||||
(w : int w,
|
||||
h : int h,
|
||||
n : int n)
|
||||
: container (w, h) =
|
||||
let
|
||||
val C = container_make (w, h)
|
||||
var free_particles : List0 @(intBtw (0, w), intBtw (0, h))
|
||||
in
|
||||
pour_particles (C, n, free_particles);
|
||||
go_until_all_particles_are_stuck (C, free_particles);
|
||||
C
|
||||
end
|
||||
|
||||
fn
|
||||
write_a_PAM_image
|
||||
{w, h : pos}
|
||||
(outf : FILEref,
|
||||
C : container (w, h),
|
||||
seed : uint)
|
||||
: void =
|
||||
let
|
||||
val w = width C and h = height C
|
||||
|
||||
fun
|
||||
count_particles
|
||||
{x, y : nat | x <= w; y <= h}
|
||||
.<h - y, w - x>.
|
||||
(x : int x,
|
||||
y : int y,
|
||||
n : int)
|
||||
: int =
|
||||
if y = h then
|
||||
n
|
||||
else if x = w then
|
||||
count_particles (0, succ y, n)
|
||||
else if C[x, y] = Empty () then
|
||||
count_particles (succ x, y, n)
|
||||
else
|
||||
count_particles (succ x, y, succ n)
|
||||
|
||||
fun
|
||||
loop {x, y : nat | x <= w; y <= h}
|
||||
.<h - y, w - x>.
|
||||
(x : int x,
|
||||
y : int y)
|
||||
: void =
|
||||
if y = h then
|
||||
()
|
||||
else if x = w then
|
||||
loop (0, succ y)
|
||||
else
|
||||
begin
|
||||
fprint_val<char>
|
||||
(outf, if C[x, y] = Empty () then '\1' else '\0');
|
||||
loop (succ x, y)
|
||||
end
|
||||
in
|
||||
fprintln! (outf, "P7");
|
||||
fprintln! (outf, "# Number of particles = ",
|
||||
count_particles (0, 0, 0));
|
||||
fprintln! (outf, "# Seed = ", seed);
|
||||
fprintln! (outf, "WIDTH ", width C);
|
||||
fprintln! (outf, "HEIGHT ", height C);
|
||||
fprintln! (outf, "DEPTH 1");
|
||||
fprintln! (outf, "MAXVAL 1");
|
||||
fprintln! (outf, "TUPLTYPE BLACKANDWHITE");
|
||||
fprintln! (outf, "ENDHDR");
|
||||
loop (0, 0)
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
|
||||
implement
|
||||
main0 (argc, argv) =
|
||||
let
|
||||
val args = list_vt2t (listize_argc_argv (argc, argv))
|
||||
val nargs = argc
|
||||
in
|
||||
if nargs <> 5 then
|
||||
begin
|
||||
fprintln! (stderr_ref, "Usage: ", args[0],
|
||||
" width height num_particles seed");
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
let
|
||||
val w = g1ofg0 (atoi (args[1]))
|
||||
and h = g1ofg0 (atoi (args[2]))
|
||||
and num_particles = g1ofg0 (atoi (args[3]))
|
||||
and seed = g1ofg0 (atoi (args[4]))
|
||||
in
|
||||
if (w < 1) + (h < 1) + (num_particles < 0) + (seed < 0) then
|
||||
begin
|
||||
fprintln! (stderr_ref, "Illegal command line argument.");
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
let
|
||||
val seed : uint = g0i2u seed
|
||||
val () = srandom seed
|
||||
val C = build_a_tree (w, h, num_particles)
|
||||
in
|
||||
write_a_PAM_image (stdout_ref, C, seed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
90
Task/Brownian-tree/Action-/brownian-tree.action
Normal file
90
Task/Brownian-tree/Action-/brownian-tree.action
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
BYTE FUNC CheckNeighbors(CARD x BYTE y)
|
||||
IF Locate(x-1,y-1)=1 THEN RETURN (1) FI
|
||||
IF Locate(x,y-1)=1 THEN RETURN (1) FI
|
||||
IF Locate(x+1,y-1)=1 THEN RETURN (1) FI
|
||||
IF Locate(x-1,y)=1 THEN RETURN (1) FI
|
||||
IF Locate(x+1,y)=1 THEN RETURN (1) FI
|
||||
IF Locate(x-1,y+1)=1 THEN RETURN (1) FI
|
||||
IF Locate(x,y+1)=1 THEN RETURN (1) FI
|
||||
IF Locate(x+1,y+1)=1 THEN RETURN (1) FI
|
||||
RETURN (0)
|
||||
|
||||
PROC DrawTree()
|
||||
DEFINE MAXW="255"
|
||||
DEFINE MINX="1"
|
||||
DEFINE MAXX="318"
|
||||
DEFINE MINY="1"
|
||||
DEFINE MAXY="190"
|
||||
BYTE CH=$02FC
|
||||
CARD x,l,r
|
||||
BYTE y,t,b,w,h,dx,dy,m=[20]
|
||||
|
||||
x=160 y=96
|
||||
Plot(x,y)
|
||||
l=x-m r=x+m
|
||||
t=y-m b=y+m
|
||||
w=r-l+1 h=b-t+1
|
||||
DO
|
||||
DO
|
||||
x=Rand(w)+l y=Rand(h)+t
|
||||
UNTIL Locate(x,y)=0
|
||||
OD
|
||||
|
||||
WHILE CheckNeighbors(x,y)=0
|
||||
DO
|
||||
DO
|
||||
dx=Rand(3) dy=Rand(3)
|
||||
UNTIL dx#2 OR dy#2
|
||||
OD
|
||||
|
||||
IF dx=0 THEN
|
||||
IF x>l THEN x==-1
|
||||
ELSE x=r-1
|
||||
FI
|
||||
ELSEIF dx=1 THEN
|
||||
IF x<r THEN x==+1
|
||||
ELSE x=l+1
|
||||
FI
|
||||
FI
|
||||
IF dy=0 THEN
|
||||
IF y>t THEN y==-1
|
||||
ELSE y=b-1
|
||||
FI
|
||||
ELSEIF dy=1 THEN
|
||||
IF y<b THEN y==+1
|
||||
ELSE y=t+1
|
||||
FI
|
||||
FI
|
||||
OD
|
||||
|
||||
Plot(x,y)
|
||||
|
||||
IF l>MINX AND l+m>x AND w<MAXW THEN
|
||||
l==-1 w==+1
|
||||
FI
|
||||
IF r<MAXX AND r-m<x AND w<MAXW THEN
|
||||
r==+1 w==+1
|
||||
FI
|
||||
IF t>MINY AND t+m>y THEN
|
||||
t==-1 h==+1
|
||||
FI
|
||||
IF b<MAXY AND b-m<y THEN
|
||||
b==+1 h==+1
|
||||
FI
|
||||
|
||||
Poke(77,0) ;turn off the attract mode
|
||||
UNTIL CH#$FF ;until key pressed
|
||||
OD
|
||||
CH=$FF
|
||||
RETURN
|
||||
|
||||
PROC Main()
|
||||
BYTE COLOR1=$02C5,COLOR2=$02C6
|
||||
|
||||
Graphics(8+16)
|
||||
Color=1
|
||||
COLOR1=$0E
|
||||
COLOR2=$02
|
||||
|
||||
DrawTree()
|
||||
RETURN
|
||||
125
Task/Brownian-tree/Ada/brownian-tree.ada
Normal file
125
Task/Brownian-tree/Ada/brownian-tree.ada
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
with Ada.Numerics.Discrete_Random;
|
||||
|
||||
with SDL.Video.Windows.Makers;
|
||||
with SDL.Video.Renderers.Makers;
|
||||
with SDL.Events.Events;
|
||||
|
||||
procedure Brownian_Tree is
|
||||
|
||||
Width : constant := 800;
|
||||
Height : constant := 600;
|
||||
Points : constant := 50_000;
|
||||
|
||||
subtype Width_Range is Integer range 1 .. Width;
|
||||
subtype Height_Range is Integer range 1 .. Height;
|
||||
type Direction is (N, NE, E, SE, S, SW, W, NW);
|
||||
package Random_Width is new Ada.Numerics.Discrete_Random (Width_Range);
|
||||
package Random_Height is new Ada.Numerics.Discrete_Random (Height_Range);
|
||||
package Random_Direc is new Ada.Numerics.Discrete_Random (Direction);
|
||||
|
||||
Window : SDL.Video.Windows.Window;
|
||||
Renderer : SDL.Video.Renderers.Renderer;
|
||||
Event : SDL.Events.Events.Events;
|
||||
|
||||
Width_Gen : Random_Width.Generator;
|
||||
Height_Gen : Random_Height.Generator;
|
||||
Direc_Gen : Random_Direc.Generator;
|
||||
|
||||
function Poll_Quit return Boolean is
|
||||
use type SDL.Events.Event_Types;
|
||||
begin
|
||||
while SDL.Events.Events.Poll (Event) loop
|
||||
if Event.Common.Event_Type = SDL.Events.Quit then
|
||||
return True;
|
||||
end if;
|
||||
end loop;
|
||||
return False;
|
||||
end Poll_Quit;
|
||||
|
||||
procedure Draw_Brownian_Tree is
|
||||
Field : array (Width_Range, Height_Range) of Boolean := (others => (others => False));
|
||||
X : Width_Range;
|
||||
Y : Height_Range;
|
||||
Direc : Direction;
|
||||
|
||||
procedure Random_Free (X : out Width_Range; Y : out Height_Range) is
|
||||
begin
|
||||
-- Find free random spot
|
||||
loop
|
||||
X := Random_Width.Random (Width_Gen);
|
||||
Y := Random_Height.Random (Height_Gen);
|
||||
exit when Field (X, Y) = False;
|
||||
end loop;
|
||||
end Random_Free;
|
||||
|
||||
begin
|
||||
-- Seed
|
||||
Field (Random_Width.Random (Width_Gen),
|
||||
Random_Height.Random (Height_Gen)) := True;
|
||||
|
||||
for I in 0 .. Points loop
|
||||
Random_Free (X, Y);
|
||||
loop
|
||||
-- If collide with wall then new random start
|
||||
while
|
||||
X = Width_Range'First or X = Width_Range'Last or
|
||||
Y = Height_Range'First or Y = Height_Range'Last
|
||||
loop
|
||||
Random_Free (X, Y);
|
||||
end loop;
|
||||
exit when Field (X - 1, Y - 1) or Field (X, Y - 1) or Field (X + 1, Y - 1);
|
||||
exit when Field (X - 1, Y) or Field (X + 1, Y);
|
||||
exit when Field (X - 1, Y + 1) or Field (X, Y + 1) or Field (X + 1, Y + 1);
|
||||
Direc := Random_Direc.Random (Direc_Gen);
|
||||
case Direc is
|
||||
when NW | N | NE => Y := Y - 1;
|
||||
when SW | S | SE => Y := Y + 1;
|
||||
when others => null;
|
||||
end case;
|
||||
case Direc is
|
||||
when NW | W | SW => X := X - 1;
|
||||
when SE | E | NE => X := X + 1;
|
||||
when others => null;
|
||||
end case;
|
||||
end loop;
|
||||
Field (X, Y) := True;
|
||||
Renderer.Draw (Point => (SDL.C.int (X), SDL.C.int (Y)));
|
||||
|
||||
if I mod 100 = 0 then
|
||||
if Poll_Quit then
|
||||
return;
|
||||
end if;
|
||||
Window.Update_Surface;
|
||||
end if;
|
||||
end loop;
|
||||
end Draw_Brownian_Tree;
|
||||
|
||||
begin
|
||||
Random_Width.Reset (Width_Gen);
|
||||
Random_Height.Reset (Height_Gen);
|
||||
Random_Direc.Reset (Direc_Gen);
|
||||
|
||||
if not SDL.Initialise (Flags => SDL.Enable_Screen) then
|
||||
return;
|
||||
end if;
|
||||
|
||||
SDL.Video.Windows.Makers.Create (Win => Window,
|
||||
Title => "Brownian tree",
|
||||
Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
|
||||
Size => SDL.Positive_Sizes'(Width, Height),
|
||||
Flags => 0);
|
||||
SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
|
||||
Renderer.Set_Draw_Colour ((0, 0, 0, 255));
|
||||
Renderer.Fill (Rectangle => (0, 0, Width, Height));
|
||||
Renderer.Set_Draw_Colour ((200, 200, 200, 255));
|
||||
|
||||
Draw_Brownian_Tree;
|
||||
Window.Update_Surface;
|
||||
|
||||
loop
|
||||
exit when Poll_Quit;
|
||||
delay 0.050;
|
||||
end loop;
|
||||
Window.Finalize;
|
||||
SDL.Finalise;
|
||||
end Brownian_Tree;
|
||||
16
Task/Brownian-tree/Applesoft-BASIC/brownian-tree.basic
Normal file
16
Task/Brownian-tree/Applesoft-BASIC/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
0GOSUB2:FORQ=0TOTSTEP0:X=A:Y=B:FORO=0TOTSTEP0:XDRAWTATX,Y:X=INT(RND(T)*J)*Z:Y=INT(RND(T)*H):XDRAWTATX,Y:O=PEEK(C)>0:NEXTO:FORP=0TOTSTEP0:A=X:B=Y:R=INT(RND(T)*E):X=X+X(R):Y=Y+Y(R):IFX<0ORX>MORY<0ORY>NTHENNEXTQ
|
||||
1 XDRAW T AT X,Y:P = NOT PEEK (C): XDRAW T AT A,B: NEXT P: XDRAW T AT X,Y:Q = A = 0 OR A = M OR B = 0 OR B = N: NEXT Q: END
|
||||
2 T = 1:Z = 2:E = 8:C = 234
|
||||
3 W = 280:A = W / 2:J = A
|
||||
4 H = 192:B = H / 2:M = W - 2
|
||||
5 N = H - 1:U = - 1:V = - 2
|
||||
6 Y(0) = U:X(0) = V:Y(1) = U
|
||||
7 Y(2) = U:X(2) = 2:X(3) = 2
|
||||
8 Y(4) = 1:X(4) = 2:Y(5) = 1
|
||||
9 X(6) = V:Y(6) = 1:X(7) = V
|
||||
10 POKE 768,1: POKE 769,0
|
||||
11 POKE 770,4: POKE 771,0
|
||||
12 POKE 772,5: POKE 773,0
|
||||
13 POKE 232,0: POKE 233,3
|
||||
14 HGR : POKE 49234,0
|
||||
15 ROT= 0: SCALE= 1: RETURN
|
||||
53
Task/Brownian-tree/AutoHotkey/brownian-tree.ahk
Normal file
53
Task/Brownian-tree/AutoHotkey/brownian-tree.ahk
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
SetBatchLines -1
|
||||
Process, Priority,, high
|
||||
size := 400
|
||||
D := .08
|
||||
num := size * size * d
|
||||
field:= Object()
|
||||
field[size//2, size//2] := true ; set the seed
|
||||
lost := 0
|
||||
|
||||
Loop % num
|
||||
{
|
||||
x := Rnd(1, size), y := Rnd(1, size)
|
||||
Loop
|
||||
{
|
||||
oldX := X, oldY := Y
|
||||
x += Rnd(-1, 1), y += Rnd(1, -1)
|
||||
If ( field[x, y] )
|
||||
{
|
||||
field[oldX, oldY] := true
|
||||
break
|
||||
}
|
||||
If ( X > Size ) or ( Y > Size) or ( X < 1 ) or ( Y < 1 )
|
||||
{
|
||||
lost++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pToken := Gdip_startup()
|
||||
pBitmap := Gdip_CreateBitmap(size, size)
|
||||
loop %size%
|
||||
{
|
||||
x := A_index
|
||||
Loop %size%
|
||||
{
|
||||
If ( field[x, A_Index] )
|
||||
{
|
||||
Gdip_SetPixel(pBitmap, x, A_Index, 0xFF0000FF)
|
||||
}
|
||||
}
|
||||
}
|
||||
Gdip_SaveBitmapToFile(pBitmap, "brownian.png")
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
Run brownian.png
|
||||
|
||||
MsgBox lost %lost%
|
||||
|
||||
Rnd(min, max){
|
||||
Random, r, min, max
|
||||
return r
|
||||
}
|
||||
27
Task/Brownian-tree/BBC-BASIC/brownian-tree.basic
Normal file
27
Task/Brownian-tree/BBC-BASIC/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
SYS "SetWindowText", @hwnd%, "Brownian Tree"
|
||||
SIZE = 400
|
||||
|
||||
VDU 23,22,SIZE;SIZE;8,16,16,0
|
||||
GCOL 10
|
||||
|
||||
REM set the seed:
|
||||
PLOT SIZE, SIZE
|
||||
|
||||
OFF
|
||||
REPEAT
|
||||
|
||||
REM set particle's initial position:
|
||||
REPEAT
|
||||
X% = RND(SIZE)-1
|
||||
Y% = RND(SIZE)-1
|
||||
UNTIL POINT(2*X%,2*Y%) = 0
|
||||
|
||||
REPEAT
|
||||
oldX% = X%
|
||||
oldY% = Y%
|
||||
X% += RND(3) - 2
|
||||
Y% += RND(3) - 2
|
||||
UNTIL POINT(2*X%,2*Y%)
|
||||
IF X%>=0 IF X%<SIZE IF Y%>=0 IF Y%<SIZE PLOT 2*oldX%,2*oldY%
|
||||
|
||||
UNTIL FALSE
|
||||
295
Task/Brownian-tree/C++/brownian-tree.cpp
Normal file
295
Task/Brownian-tree/C++/brownian-tree.cpp
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
#include <windows.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
using namespace std;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
enum states { SEED, GROWING, MOVING, REST };
|
||||
enum treeStates { NONE, MOVER, TREE };
|
||||
const int MAX_SIDE = 480, MAX_MOVERS = 511, MAX_CELLS = 15137;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
class point
|
||||
{
|
||||
public:
|
||||
point() { x = y = 0; }
|
||||
point( int a, int b ) { x = a; y = b; }
|
||||
void set( int a, int b ) { x = a; y = b; }
|
||||
|
||||
int x, y;
|
||||
};
|
||||
//--------------------------------------------------------------------
|
||||
class movers
|
||||
{
|
||||
public:
|
||||
point pos;
|
||||
bool moving;
|
||||
movers() : moving( false ){}
|
||||
};
|
||||
//--------------------------------------------------------------------
|
||||
class myBitmap
|
||||
{
|
||||
public:
|
||||
myBitmap() : pen( NULL ) {}
|
||||
~myBitmap()
|
||||
{
|
||||
DeleteObject( pen );
|
||||
DeleteDC( hdc );
|
||||
DeleteObject( bmp );
|
||||
}
|
||||
|
||||
bool create( int w, int h )
|
||||
{
|
||||
BITMAPINFO bi;
|
||||
ZeroMemory( &bi, sizeof( bi ) );
|
||||
|
||||
bi.bmiHeader.biSize = sizeof( bi.bmiHeader );
|
||||
bi.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
|
||||
bi.bmiHeader.biCompression = BI_RGB;
|
||||
bi.bmiHeader.biPlanes = 1;
|
||||
bi.bmiHeader.biWidth = w;
|
||||
bi.bmiHeader.biHeight = -h;
|
||||
|
||||
HDC dc = GetDC( GetConsoleWindow() );
|
||||
bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
|
||||
if( !bmp ) return false;
|
||||
|
||||
hdc = CreateCompatibleDC( dc );
|
||||
SelectObject( hdc, bmp );
|
||||
ReleaseDC( GetConsoleWindow(), dc );
|
||||
|
||||
width = w; height = h;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
ZeroMemory( pBits, width * height * sizeof( DWORD ) );
|
||||
}
|
||||
|
||||
void setPenColor( DWORD clr )
|
||||
{
|
||||
if( pen ) DeleteObject( pen );
|
||||
pen = CreatePen( PS_SOLID, 1, clr );
|
||||
SelectObject( hdc, pen );
|
||||
}
|
||||
|
||||
void saveBitmap( string path )
|
||||
{
|
||||
BITMAPFILEHEADER fileheader;
|
||||
BITMAPINFO infoheader;
|
||||
BITMAP bitmap;
|
||||
DWORD* dwpBits;
|
||||
DWORD wb;
|
||||
HANDLE file;
|
||||
|
||||
GetObject( bmp, sizeof( bitmap ), &bitmap );
|
||||
|
||||
dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];
|
||||
ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
|
||||
ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
|
||||
ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );
|
||||
|
||||
infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
|
||||
infoheader.bmiHeader.biCompression = BI_RGB;
|
||||
infoheader.bmiHeader.biPlanes = 1;
|
||||
infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
|
||||
infoheader.bmiHeader.biHeight = bitmap.bmHeight;
|
||||
infoheader.bmiHeader.biWidth = bitmap.bmWidth;
|
||||
infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );
|
||||
|
||||
fileheader.bfType = 0x4D42;
|
||||
fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
|
||||
fileheader.bfSize = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;
|
||||
|
||||
GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );
|
||||
|
||||
file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
|
||||
WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
|
||||
WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
|
||||
CloseHandle( file );
|
||||
|
||||
delete [] dwpBits;
|
||||
}
|
||||
|
||||
HDC getDC() { return hdc; }
|
||||
int getWidth() { return width; }
|
||||
int getHeight() { return height; }
|
||||
|
||||
private:
|
||||
HBITMAP bmp;
|
||||
HDC hdc;
|
||||
HPEN pen;
|
||||
void *pBits;
|
||||
int width, height;
|
||||
};
|
||||
//--------------------------------------------------------------------
|
||||
class brownianTree
|
||||
{
|
||||
public:
|
||||
brownianTree()
|
||||
{
|
||||
_bmp.create( MAX_SIDE, MAX_SIDE );
|
||||
init();
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
_cellCount = 0;
|
||||
ZeroMemory( _grid, sizeof( _grid ) );
|
||||
_bmp.clear();
|
||||
_state = SEED;
|
||||
}
|
||||
|
||||
bool mainLoop()
|
||||
{
|
||||
switch( _state )
|
||||
{
|
||||
case REST: saveTree(); return false;
|
||||
case SEED: doSeed(); break;
|
||||
case GROWING: startMovers(); break;
|
||||
case MOVING: moveMovers();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
myBitmap* getBmp() { return &_bmp; }
|
||||
|
||||
private:
|
||||
void saveTree()
|
||||
{
|
||||
for( int y = 0; y < MAX_SIDE; y++ )
|
||||
for( int x = 0; x < MAX_SIDE; x++ )
|
||||
if( _grid[x][y] == TREE )
|
||||
SetPixel( _bmp.getDC(), x, y, RGB( 255, 120, 0 ) );
|
||||
|
||||
_bmp.saveBitmap( "f:\\rc\\tree.bmp" );
|
||||
}
|
||||
|
||||
void doSeed()
|
||||
{
|
||||
int x = MAX_SIDE - MAX_SIDE / 2, y = MAX_SIDE / 4;
|
||||
_grid[rand() % x + y][rand() % x + y] = TREE;
|
||||
_cellCount++;
|
||||
_state = GROWING;
|
||||
}
|
||||
|
||||
void addMover( movers* m )
|
||||
{
|
||||
m->moving = true;
|
||||
int x = MAX_SIDE - MAX_SIDE / 2, y = MAX_SIDE / 4, a, b;
|
||||
while( true )
|
||||
{
|
||||
a = rand() % x + y; b = rand() % x + y;
|
||||
if( _grid[a][b] == NONE ) break;
|
||||
}
|
||||
|
||||
m->pos.set( a, b );
|
||||
_grid[a][b] = MOVER;
|
||||
}
|
||||
|
||||
void startMovers()
|
||||
{
|
||||
movers* m;
|
||||
for( int c = 0; c < MAX_MOVERS; c++ )
|
||||
{
|
||||
m = &_movers[c];
|
||||
addMover( m );
|
||||
}
|
||||
_state = MOVING;
|
||||
}
|
||||
|
||||
void addToTree( movers* m )
|
||||
{
|
||||
m->moving = false;
|
||||
_grid[m->pos.x][m->pos.y] = TREE;
|
||||
if( ++_cellCount >= MAX_CELLS ) _state = REST;
|
||||
|
||||
COORD c = { 0, 1 };
|
||||
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), c );
|
||||
cout << "Cells added: " << _cellCount
|
||||
<< " from " << MAX_CELLS << " => "
|
||||
<< static_cast<float>( 100 * _cellCount ) /
|
||||
static_cast<float>( MAX_CELLS )
|
||||
<< "% ";
|
||||
}
|
||||
|
||||
bool moveIt( movers* m )
|
||||
{
|
||||
point f[8]; int ff = 0;
|
||||
for( int y = -1; y < 2; y++ )
|
||||
{
|
||||
for( int x = -1; x < 2; x++ )
|
||||
{
|
||||
if( !x && !y ) continue;
|
||||
int a = m->pos.x + x, b = m->pos.y + y;
|
||||
if( a < 0 || b < 0 || a >= MAX_SIDE || b >= MAX_SIDE )
|
||||
{
|
||||
addToTree( m );
|
||||
return true;
|
||||
}
|
||||
switch( _grid[a][b] )
|
||||
{
|
||||
case TREE:
|
||||
addToTree( m );
|
||||
return true;
|
||||
case NONE:
|
||||
f[ff++].set( a, b );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( ff < 1 ) return false;
|
||||
|
||||
_grid[m->pos.x][m->pos.y] = NONE;
|
||||
m->pos = f[rand() % ff];
|
||||
_grid[m->pos.x][m->pos.y] = MOVER;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void moveMovers()
|
||||
{
|
||||
movers* mm;
|
||||
for( int m = 0; m < MAX_MOVERS; m++ )
|
||||
{
|
||||
mm = &_movers[m];
|
||||
if( !mm->moving ) continue;
|
||||
if( moveIt( mm ) && _cellCount < MAX_CELLS ) addMover( mm );
|
||||
}
|
||||
}
|
||||
|
||||
states _state;
|
||||
BYTE _grid[MAX_SIDE][MAX_SIDE];
|
||||
myBitmap _bmp;
|
||||
int _cellCount;
|
||||
movers _movers[MAX_MOVERS];
|
||||
};
|
||||
//--------------------------------------------------------------------
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
ShowWindow( GetConsoleWindow(), SW_MAXIMIZE );
|
||||
srand( GetTickCount() );
|
||||
|
||||
brownianTree tree;
|
||||
|
||||
DWORD now = GetTickCount();
|
||||
while( tree.mainLoop() );
|
||||
|
||||
now = GetTickCount() - now;
|
||||
cout << endl << endl << "It took "
|
||||
<< now / 1000
|
||||
<< " seconds to complete the task!" << endl << endl;
|
||||
|
||||
BitBlt( GetDC( GetConsoleWindow() ), 20, 90, MAX_SIDE, MAX_SIDE,
|
||||
tree.getBmp()->getDC(), 0, 0, SRCCOPY );
|
||||
|
||||
system( "pause" );
|
||||
return 0;
|
||||
}
|
||||
//--------------------------------------------------------------------
|
||||
51
Task/Brownian-tree/C-sharp/brownian-tree.cs
Normal file
51
Task/Brownian-tree/C-sharp/brownian-tree.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace BrownianTree
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static Bitmap BrownianTree(int size, int numparticles)
|
||||
{
|
||||
Bitmap bmp = new Bitmap(size, size);
|
||||
Rectangle bounds = new Rectangle { X = 0, Y = 0, Size = bmp.Size };
|
||||
using (Graphics g = Graphics.FromImage(bmp))
|
||||
{
|
||||
g.Clear(Color.Black);
|
||||
}
|
||||
Random rnd = new Random();
|
||||
bmp.SetPixel(rnd.Next(size), rnd.Next(size), Color.White);
|
||||
Point pt = new Point(), newpt = new Point();
|
||||
for (int i = 0; i < numparticles; i++)
|
||||
{
|
||||
pt.X = rnd.Next(size);
|
||||
pt.Y = rnd.Next(size);
|
||||
do
|
||||
{
|
||||
newpt.X = pt.X + rnd.Next(-1, 2);
|
||||
newpt.Y = pt.Y + rnd.Next(-1, 2);
|
||||
if (!bounds.Contains(newpt))
|
||||
{
|
||||
pt.X = rnd.Next(size);
|
||||
pt.Y = rnd.Next(size);
|
||||
}
|
||||
else if (bmp.GetPixel(newpt.X, newpt.Y).R > 0)
|
||||
{
|
||||
bmp.SetPixel(pt.X, pt.Y, Color.White);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
pt = newpt;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
BrownianTree(300, 3000).Save("browniantree.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Task/Brownian-tree/C/brownian-tree-1.c
Normal file
65
Task/Brownian-tree/C/brownian-tree-1.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <FreeImage.h>
|
||||
|
||||
#define NUM_PARTICLES 1000
|
||||
#define SIZE 800
|
||||
|
||||
void draw_brownian_tree(int world[SIZE][SIZE]){
|
||||
int px, py; // particle values
|
||||
int dx, dy; // offsets
|
||||
int i;
|
||||
|
||||
// set the seed
|
||||
world[rand() % SIZE][rand() % SIZE] = 1;
|
||||
|
||||
for (i = 0; i < NUM_PARTICLES; i++){
|
||||
// set particle's initial position
|
||||
px = rand() % SIZE;
|
||||
py = rand() % SIZE;
|
||||
|
||||
while (1){
|
||||
// randomly choose a direction
|
||||
dx = rand() % 3 - 1;
|
||||
dy = rand() % 3 - 1;
|
||||
|
||||
if (dx + px < 0 || dx + px >= SIZE || dy + py < 0 || dy + py >= SIZE){
|
||||
// plop the particle into some other random location
|
||||
px = rand() % SIZE;
|
||||
py = rand() % SIZE;
|
||||
}else if (world[py + dy][px + dx] != 0){
|
||||
// bumped into something
|
||||
world[py][px] = 1;
|
||||
break;
|
||||
}else{
|
||||
py += dy;
|
||||
px += dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
int world[SIZE][SIZE];
|
||||
FIBITMAP * img;
|
||||
RGBQUAD rgb;
|
||||
int x, y;
|
||||
|
||||
memset(world, 0, sizeof world);
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
draw_brownian_tree(world);
|
||||
|
||||
img = FreeImage_Allocate(SIZE, SIZE, 32, 0, 0, 0);
|
||||
|
||||
for (y = 0; y < SIZE; y++){
|
||||
for (x = 0; x < SIZE; x++){
|
||||
rgb.rgbRed = rgb.rgbGreen = rgb.rgbBlue = (world[y][x] ? 255 : 0);
|
||||
FreeImage_SetPixelColor(img, x, y, &rgb);
|
||||
}
|
||||
}
|
||||
FreeImage_Save(FIF_BMP, img, "brownian_tree.bmp", 0);
|
||||
FreeImage_Unload(img);
|
||||
}
|
||||
43
Task/Brownian-tree/C/brownian-tree-2.c
Normal file
43
Task/Brownian-tree/C/brownian-tree-2.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define SIDE 600
|
||||
#define NUM_PARTICLES 10000
|
||||
|
||||
bool W[SIDE][SIDE];
|
||||
|
||||
int main() {
|
||||
srand((unsigned)time(NULL));
|
||||
W[SIDE / 2][SIDE / 2] = true;
|
||||
|
||||
for (int i = 0; i < NUM_PARTICLES; i++) {
|
||||
unsigned int x, y;
|
||||
OVER: do {
|
||||
x = rand() % (SIDE - 2) + 1;
|
||||
y = rand() % (SIDE - 2) + 1;
|
||||
} while (W[y][x]);
|
||||
|
||||
while (W[y-1][x-1] + W[y-1][x] + W[y-1][x+1] +
|
||||
W[y][x-1] + W[y][x+1] +
|
||||
W[y+1][x-1] + W[y+1][x] + W[y+1][x+1] == 0) {
|
||||
unsigned int dxy = rand() % 8;
|
||||
if (dxy > 3) dxy++;
|
||||
x += (dxy % 3) - 1;
|
||||
y += (dxy / 3) - 1;
|
||||
if (x < 1 || x >= SIDE - 1 || y < 1 || y >= SIDE - 1)
|
||||
goto OVER;
|
||||
}
|
||||
|
||||
W[y][x] = true;
|
||||
}
|
||||
|
||||
printf("P1\n%d %d\n", SIDE, SIDE);
|
||||
for (int r = 0; r < SIDE; r++) {
|
||||
for (int c = 0; c < SIDE; c++)
|
||||
printf("%d ", W[r][c]);
|
||||
putchar('\n');
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
85
Task/Brownian-tree/Common-Lisp/brownian-tree.lisp
Normal file
85
Task/Brownian-tree/Common-Lisp/brownian-tree.lisp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
;;; brownian.lisp
|
||||
;;; sbcl compile: first load and then (sb-ext:save-lisp-and-die "brownian" :executable t :toplevel #'brownian::main)
|
||||
(ql:quickload "cl-gd")
|
||||
|
||||
(defpackage #:brownian
|
||||
(:use #:cl #:cl-gd))
|
||||
(in-package #:brownian)
|
||||
|
||||
(defvar *size* 512)
|
||||
(defparameter bitmap (make-array *size*))
|
||||
(dotimes (i *size*)
|
||||
(setf (svref bitmap i) (make-array *size* :element-type 'bit)))
|
||||
|
||||
;;; is pixel at coord set? returns coord if so otherwise nil if not set or invalid
|
||||
;;; type:pair->pair|nil
|
||||
(defun set-p (coord)
|
||||
(and coord (= (sbit (svref bitmap (car coord)) (cdr coord)) 1) coord))
|
||||
|
||||
;;; valid coord predicate, return its arg if valid or nil otherwise
|
||||
;;; type:pair->pair|nil
|
||||
(defun coord-p (coord)
|
||||
(and ((lambda (v hi) (and (>= v 0) (< v hi))) (car coord) *size*)
|
||||
((lambda (v hi) (and (>= v 0) (< v hi))) (cdr coord) *size*)
|
||||
coord))
|
||||
|
||||
;;; valid coord predicate for the ith neighbour, return its arg if valid or nil otherwise
|
||||
;;; type:pair->pair|nil
|
||||
(defun coordi-p (coord i)
|
||||
(coord-p (cons (+ (car coord) (nth i '(-1 -1 -1 0 0 1 1 1)))
|
||||
(+ (cdr coord) (nth i '(-1 0 1 -1 1 -1 0 1))))))
|
||||
|
||||
;;; random walk until out of bounds or hit occupied pixel
|
||||
;;; assumes start is valid vacant coord, return start or nil if off-grid
|
||||
;;; type:pair->pair|nil
|
||||
(defun random-walk (start)
|
||||
(let ((next (coordi-p start (random 8))))
|
||||
(if (set-p next) start
|
||||
(and next (random-walk next)))))
|
||||
|
||||
;;; random walk until out of bounds or or adjacent to occupied pixel
|
||||
;;; assumes start is valid vacant coord, return start or nil if off-grid
|
||||
;;; type:pair->pair|nil
|
||||
(defun random-walk2 (start)
|
||||
(if (some #'set-p
|
||||
(remove-if #'null (mapcar (lambda (i) (coordi-p start i)) '(0 1 2 3 4 5 6 7))))
|
||||
start
|
||||
(let ((next (coordi-p start (random 8))))
|
||||
(and next (random-walk2 next)))))
|
||||
|
||||
|
||||
(defparameter use-walk2 nil)
|
||||
(defun main ()
|
||||
(setf *random-state* (make-random-state t)) ;; randomize
|
||||
(when (cdr sb-ext:*posix-argv*) (setf use-walk2 t)) ;; any cmd line arg -> use alt walk algorithm
|
||||
(with-image* (*size* *size*)
|
||||
(allocate-color 0 0 0) ; background color
|
||||
|
||||
;;; set the desired number of pixels in image as a pct (10%) of total
|
||||
(let ((target (truncate (* 0.10 (* *size* *size*))))
|
||||
(green (allocate-color 104 156 84)))
|
||||
|
||||
(defun write-pixel (coord)
|
||||
(set-pixel (car coord) (cdr coord) :color green)
|
||||
(setf (sbit (svref bitmap (car coord)) (cdr coord)) 1)
|
||||
coord)
|
||||
|
||||
;; initial point set
|
||||
(write-pixel (cons (truncate (/ *size* 2)) (truncate (/ *size* 2))))
|
||||
|
||||
;; iterate until target # of pixels are set
|
||||
(do ((i 0 i)
|
||||
(seed (cons (random *size*) (random *size*)) (cons (random *size*) (random *size*))))
|
||||
((= i target) )
|
||||
|
||||
(let ((newcoord (and (not (set-p seed)) (if use-walk2 (random-walk2 seed) (random-walk seed)))))
|
||||
(when newcoord
|
||||
(write-pixel newcoord)
|
||||
(incf i)
|
||||
|
||||
;; report every 5% of progress
|
||||
(when (zerop (rem i (round (* target 0.05))))
|
||||
(format t "~A% done.~%" (round (/ i target 0.01))))))))
|
||||
|
||||
(write-image-to-file "brownian.png"
|
||||
:compression-level 6 :if-exists :supersede)))
|
||||
38
Task/Brownian-tree/D/brownian-tree.d
Normal file
38
Task/Brownian-tree/D/brownian-tree.d
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
void main() {
|
||||
import core.stdc.stdio, std.random, grayscale_image;
|
||||
|
||||
enum uint side = 600; // Square world side.
|
||||
enum uint num_particles = 10_000;
|
||||
static assert(side > 2 && num_particles < (side ^^ 2 * 0.7));
|
||||
|
||||
auto rng = unpredictableSeed.Xorshift;
|
||||
ubyte[side][side] W; // World.
|
||||
W[side / 2][side / 2] = 1; // Set tree root.
|
||||
|
||||
foreach (immutable _; 0 .. num_particles) {
|
||||
// Random initial particle position.
|
||||
OVER: uint x, y;
|
||||
do {
|
||||
x = uniform(1, side - 1, rng);
|
||||
y = uniform(1, side - 1, rng);
|
||||
} while (W[y][x]); // Assure the chosen cell is empty.
|
||||
|
||||
while (W[y-1][x-1] + W[y-1][x] + W[y-1][x+1] +
|
||||
W[y][x-1] + W[y][x+1] +
|
||||
W[y+1][x-1] + W[y+1][x] + W[y+1][x+1] == 0) {
|
||||
// Randomly choose a direction (Moore neighborhood).
|
||||
uint dxy = uniform(0, 8, rng);
|
||||
if (dxy > 3) dxy++; // To avoid the center.
|
||||
x += (dxy % 3) - 1;
|
||||
y += (dxy / 3) - 1;
|
||||
if (x < 1 || x >= side - 1 || y < 1 || y >= side - 1)
|
||||
goto OVER;
|
||||
}
|
||||
|
||||
W[y][x] = 1; // Touched, set the cell.
|
||||
}
|
||||
|
||||
ubyte[] data = (&W[0][0])[0 .. side ^^ 2]; // Flat view.
|
||||
data[] += 255;
|
||||
Image!ubyte.fromData(data, side, side).savePGM("brownian_tree.pgm");
|
||||
}
|
||||
54
Task/Brownian-tree/Delphi/brownian-tree.delphi
Normal file
54
Task/Brownian-tree/Delphi/brownian-tree.delphi
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
const
|
||||
SIZE = 256;
|
||||
NUM_PARTICLES = 1000;
|
||||
|
||||
procedure TForm1.Button1Click(Sender: TObject);
|
||||
type
|
||||
TByteArray = array[0..0] of Byte;
|
||||
PByteArray = ^TByteArray;
|
||||
var
|
||||
B: TBitmap;
|
||||
I: Integer;
|
||||
P, D: TPoint;
|
||||
begin
|
||||
Randomize;
|
||||
B := TBitmap.Create;
|
||||
try
|
||||
B.Width := SIZE;
|
||||
B.Height := SIZE;
|
||||
B.PixelFormat := pf8bit;
|
||||
|
||||
B.Canvas.Brush.Color := clBlack;
|
||||
B.Canvas.FillRect(B.Canvas.ClipRect);
|
||||
B.Canvas.Pixels[Random(SIZE), Random(SIZE)] := clWhite;
|
||||
|
||||
For I := 0 to NUM_PARTICLES - 1 do
|
||||
Begin
|
||||
P.X := Random(SIZE);
|
||||
P.Y := Random(SIZE);
|
||||
|
||||
While true do
|
||||
Begin
|
||||
D.X := Random(3) - 1;
|
||||
D.Y := Random(3) - 1;
|
||||
Inc(P.X, D.X);
|
||||
Inc(P.Y, D.Y);
|
||||
|
||||
If ((P.X or P.Y) < 0) or (P.X >= SIZE) or (P.Y >= SIZE) Then
|
||||
Begin
|
||||
P.X := Random(SIZE);
|
||||
P.Y := Random(SIZE);
|
||||
end
|
||||
else if PByteArray(B.ScanLine[P.Y])^[P.X] <> 0 then
|
||||
begin
|
||||
PByteArray(B.ScanLine[P.Y-D.Y])^[P.X-D.X] := $FF;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Canvas.Draw(0, 0, B);
|
||||
finally
|
||||
FreeAndNil(B);
|
||||
end;
|
||||
end;
|
||||
33
Task/Brownian-tree/EasyLang/brownian-tree.easy
Normal file
33
Task/Brownian-tree/EasyLang/brownian-tree.easy
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
color3 0 1 1
|
||||
len f[] 200 * 200
|
||||
move 50 50
|
||||
rect 0.5 0.5
|
||||
f[100 * 200 + 100] = 1
|
||||
n = 9000
|
||||
while i < n
|
||||
repeat
|
||||
x = random 200 - 1
|
||||
y = random 200 - 1
|
||||
until f[y * 200 + x + 1] <> 1
|
||||
.
|
||||
while 1 = 1
|
||||
xo = x
|
||||
yo = y
|
||||
x += random 3 - 2
|
||||
y += random 3 - 2
|
||||
if x < 0 or y < 0 or x >= 200 or y >= 200
|
||||
break 1
|
||||
.
|
||||
if f[y * 200 + x + 1] = 1
|
||||
move xo / 2 yo / 2
|
||||
rect 0.5 0.5
|
||||
f[yo * 200 + xo + 1] = 1
|
||||
i += 1
|
||||
if i mod 16 = 0
|
||||
color3 0.2 + i / n 1 1
|
||||
sleep 0
|
||||
.
|
||||
break 1
|
||||
.
|
||||
.
|
||||
.
|
||||
48
Task/Brownian-tree/Factor/brownian-tree.factor
Normal file
48
Task/Brownian-tree/Factor/brownian-tree.factor
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
USING: accessors images images.loader kernel literals math
|
||||
math.vectors random sets ;
|
||||
FROM: sets => in? ;
|
||||
EXCLUDE: sequences => move ;
|
||||
IN: rosetta-code.brownian-tree
|
||||
|
||||
CONSTANT: size 512
|
||||
CONSTANT: num-particles 30000
|
||||
CONSTANT: seed { 256 256 }
|
||||
CONSTANT: spawns { { 10 10 } { 502 10 } { 10 502 } { 502 502 } }
|
||||
CONSTANT: bg-color B{ 0 0 0 255 }
|
||||
CONSTANT: fg-color B{ 255 255 255 255 }
|
||||
|
||||
: in-bounds? ( loc -- ? )
|
||||
dup { 0 0 } ${ size 1 - dup } vclamp = ;
|
||||
|
||||
: move ( loc -- loc' )
|
||||
dup 2 [ { 1 -1 } random ] replicate v+ dup in-bounds?
|
||||
[ nip ] [ drop ] if ;
|
||||
|
||||
: grow ( particles -- particles' )
|
||||
spawns random dup
|
||||
[ 2over swap in? ] [ drop dup move swap ] until nip
|
||||
swap [ adjoin ] keep ;
|
||||
|
||||
: brownian-data ( -- seq )
|
||||
HS{ $ seed } clone num-particles 1 - [ grow ] times { }
|
||||
set-like ;
|
||||
|
||||
: blank-bitmap ( -- bitmap )
|
||||
size sq [ bg-color ] replicate B{ } concat-as ;
|
||||
|
||||
: init-img ( -- img )
|
||||
<image>
|
||||
${ size size } >>dim
|
||||
BGRA >>component-order
|
||||
ubyte-components >>component-type
|
||||
blank-bitmap >>bitmap ;
|
||||
|
||||
: brownian-img ( -- img )
|
||||
init-img dup brownian-data
|
||||
[ swap [ fg-color swap first2 ] dip set-pixel-at ] with each
|
||||
;
|
||||
|
||||
: save-brownian-tree-image ( -- )
|
||||
brownian-img "brownian.png" save-graphic-image ;
|
||||
|
||||
MAIN: save-brownian-tree-image
|
||||
101
Task/Brownian-tree/Fantom/brownian-tree.fantom
Normal file
101
Task/Brownian-tree/Fantom/brownian-tree.fantom
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
using fwt
|
||||
using gfx
|
||||
|
||||
class Main
|
||||
{
|
||||
public static Void main ()
|
||||
{
|
||||
particles := Particles (300, 200)
|
||||
1000.times { particles.addParticle } // add 1000 particles
|
||||
Window // open up a display for the final tree
|
||||
{
|
||||
title = "Brownian Tree"
|
||||
EdgePane
|
||||
{
|
||||
center = ScrollPane { content = ParticleCanvas(particles) }
|
||||
},
|
||||
}.open
|
||||
}
|
||||
}
|
||||
|
||||
class Particles
|
||||
{
|
||||
Bool[][] image
|
||||
Int height
|
||||
Int width
|
||||
|
||||
new make (Int height, Int width)
|
||||
{
|
||||
this.height = height
|
||||
this.width = width
|
||||
// set up initial image as an array of booleans with one set cell
|
||||
image = [,]
|
||||
width.times |w|
|
||||
{
|
||||
row := [,]
|
||||
height.times { row.add (false) }
|
||||
image.add (row)
|
||||
}
|
||||
image[Int.random(0..<width)][Int.random(0..<height)] = true
|
||||
}
|
||||
|
||||
Bool get (Int w, Int h) { return image[w][h] }
|
||||
|
||||
Void addParticle ()
|
||||
{
|
||||
x := Int.random(0..<width)
|
||||
y := Int.random(0..<height)
|
||||
|
||||
Int dx := 0
|
||||
Int dy := 0
|
||||
while (!image[x][y]) // loop until hit existing part of the tree
|
||||
{
|
||||
dx = [-1,0,1].random
|
||||
dy = [-1,0,1].random
|
||||
|
||||
if ((0..<width).contains(x + dx))
|
||||
x += dx
|
||||
else // did not change x, so set dx = 0
|
||||
dx = 0
|
||||
if ((0..<height).contains(y + dy))
|
||||
y += dy
|
||||
else
|
||||
dy = 0
|
||||
}
|
||||
|
||||
// put x,y back to just before move onto existing part of tree
|
||||
x -= dx
|
||||
y -= dy
|
||||
|
||||
image[x][y] = true
|
||||
}
|
||||
}
|
||||
|
||||
class ParticleCanvas : Canvas
|
||||
{
|
||||
Particles particles
|
||||
|
||||
new make (Particles particles) { this.particles = particles }
|
||||
|
||||
// provides canvas size for parent scrollpane
|
||||
override Size prefSize(Hints hints := Hints.defVal)
|
||||
{
|
||||
Size(particles.width, particles.height)
|
||||
}
|
||||
|
||||
// repaint the display
|
||||
override Void onPaint (Graphics g)
|
||||
{
|
||||
g.brush = Color.black
|
||||
g.fillRect(0, 0, size.w, size.h)
|
||||
g.brush = Color.green
|
||||
particles.width.times |w|
|
||||
{
|
||||
particles.height.times |h|
|
||||
{
|
||||
if (particles.get(w, h)) // draw a 1x1 square for each set particle
|
||||
g.fillRect (w, h, 1, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
Task/Brownian-tree/Fortran/brownian-tree.f
Normal file
106
Task/Brownian-tree/Fortran/brownian-tree.f
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
program BrownianTree
|
||||
use RCImageBasic
|
||||
use RCImageIO
|
||||
|
||||
implicit none
|
||||
|
||||
integer, parameter :: num_particles = 1000
|
||||
integer, parameter :: wsize = 800
|
||||
|
||||
integer, dimension(wsize, wsize) :: world
|
||||
type(rgbimage) :: gworld
|
||||
integer :: x, y
|
||||
|
||||
! init seed
|
||||
call init_random_seed
|
||||
|
||||
world = 0
|
||||
call draw_brownian_tree(world)
|
||||
|
||||
call alloc_img(gworld, wsize, wsize)
|
||||
call fill_img(gworld, rgb(0,0,0))
|
||||
|
||||
do y = 1, wsize
|
||||
do x = 1, wsize
|
||||
if ( world(x, y) /= 0 ) then
|
||||
call put_pixel(gworld, x, y, rgb(255, 255, 255))
|
||||
end if
|
||||
end do
|
||||
end do
|
||||
|
||||
open(unit=10, file='browniantree.ppm', action='write')
|
||||
call output_ppm(10, gworld)
|
||||
close(10)
|
||||
|
||||
call free_img(gworld)
|
||||
|
||||
contains
|
||||
|
||||
! this code is taken from the GNU gfortran online doc
|
||||
subroutine init_random_seed
|
||||
integer :: i, n, clock
|
||||
integer, dimension(:), allocatable :: seed
|
||||
|
||||
call random_seed(size = n)
|
||||
allocate(seed(n))
|
||||
call system_clock(count = clock)
|
||||
seed = clock + 37 * (/ ( i - 1, i = 1, n) /)
|
||||
call random_seed(put = seed)
|
||||
deallocate(seed)
|
||||
end subroutine init_random_seed
|
||||
|
||||
|
||||
function randbetween(a, b) result(res) ! suppose a < b
|
||||
integer, intent(in) :: a, b
|
||||
integer :: res
|
||||
|
||||
real :: r
|
||||
|
||||
call random_number(r)
|
||||
|
||||
res = a + int((b-a)*r + 0.5)
|
||||
|
||||
end function randbetween
|
||||
|
||||
function bounded(v, ll, ul) result(res)
|
||||
integer, intent(in) :: v, ll, ul
|
||||
logical res
|
||||
|
||||
res = ( v >= ll ) .and. ( v <= ul )
|
||||
end function bounded
|
||||
|
||||
|
||||
subroutine draw_brownian_tree(w)
|
||||
integer, dimension(:,:), intent(inout) :: w
|
||||
|
||||
integer :: px, py, dx, dy, i
|
||||
integer :: xsize, ysize
|
||||
|
||||
xsize = size(w, 1)
|
||||
ysize = size(w, 2)
|
||||
|
||||
w(randbetween(1, xsize), randbetween(1, ysize)) = 1
|
||||
|
||||
do i = 1, num_particles
|
||||
px = randbetween(1, xsize)
|
||||
py = randbetween(1, ysize)
|
||||
|
||||
do
|
||||
dx = randbetween(-1, 1)
|
||||
dy = randbetween(-1, 1)
|
||||
if ( .not. bounded(dx+px, 1, xsize) .or. .not. bounded(dy+py, 1, ysize) ) then
|
||||
px = randbetween(1, xsize)
|
||||
py = randbetween(1, ysize)
|
||||
else if ( w(px+dx, py+dy) /= 0 ) then
|
||||
w(px, py) = 1
|
||||
exit
|
||||
else
|
||||
py = py + dy
|
||||
px = px + dx
|
||||
end if
|
||||
end do
|
||||
end do
|
||||
|
||||
end subroutine draw_brownian_tree
|
||||
|
||||
end program
|
||||
60
Task/Brownian-tree/FreeBASIC/brownian-tree.basic
Normal file
60
Task/Brownian-tree/FreeBASIC/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
' version 16-03-2017
|
||||
' compile with: fbc -s gui
|
||||
|
||||
Const As ULong w = 400
|
||||
Const As ULong w1 = w -1
|
||||
|
||||
Dim As Long x, y, lastx, lasty
|
||||
Dim As Long count, max = w * w \ 4
|
||||
|
||||
ScreenRes w, w, 8 ' windowsize 400 * 400, 8bit
|
||||
' hit any key to stop or mouseclick on close window [X]
|
||||
WindowTitle "hit any key to stop and close the window"
|
||||
|
||||
Palette 0, 0 ' black
|
||||
Palette 1, RGB( 1, 1, 1) ' almost black
|
||||
Palette 2, RGB(255, 255, 255) ' white
|
||||
Palette 3, RGB( 0, 255, 0) ' green
|
||||
|
||||
Line (0, 0) - (w1, w1), 0, BF ' make field black
|
||||
Line (0, 0) - (w1, w1), 1, B ' draw border in almost black color
|
||||
|
||||
Randomize Timer
|
||||
x = Int(Rnd * 11) - 5
|
||||
y = Int(Rnd * 11) - 5
|
||||
|
||||
PSet(w \ 2 + x, w \ 2 + y), 3 ' place seed near center
|
||||
|
||||
Do
|
||||
Do ' create new particle
|
||||
x = Int(Rnd * w1) + 1
|
||||
y = Int(Rnd * w1) + 1
|
||||
Loop Until Point(x, y) = 0 ' black
|
||||
PSet(x, y), 2
|
||||
|
||||
Do
|
||||
lastx = x
|
||||
lasty = y
|
||||
Do
|
||||
x = lastx + Int(Rnd * 3) -1
|
||||
y = lasty + Int(Rnd * 3) -1
|
||||
Loop Until Point(x, y) <> 1
|
||||
|
||||
If Point(x, y) = 3 Then
|
||||
PSet(lastx, lasty), 3
|
||||
Exit Do ' exit do loop and create new particle
|
||||
End If
|
||||
|
||||
PSet(lastx, lasty), 0
|
||||
PSet(x,y), 2
|
||||
|
||||
If Inkey <> "" Or Inkey = Chr(255) + "k" Then
|
||||
End
|
||||
End If
|
||||
Loop
|
||||
|
||||
count += 1
|
||||
Loop Until count > max
|
||||
|
||||
Beep : Sleep 5000
|
||||
End
|
||||
14
Task/Brownian-tree/Gnuplot/brownian-tree-1.gnuplot
Normal file
14
Task/Brownian-tree/Gnuplot/brownian-tree-1.gnuplot
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
## plotff.gp 11/27/16 aev
|
||||
## Plotting from any data-file with 2 columns (space delimited), and writing to png-file.
|
||||
## Especially useful to plot colored fractals using points.
|
||||
## Note: assign variables: clr, filename and ttl (before using load command).
|
||||
reset
|
||||
set terminal png font arial 12 size 640,640
|
||||
ofn=filename.".png"
|
||||
set output ofn
|
||||
unset border; unset xtics; unset ytics; unset key;
|
||||
set size square
|
||||
dfn=filename.".dat"
|
||||
set title ttl font "Arial:Bold,12"
|
||||
plot dfn using 1:2 with points pt 7 ps 0.5 lc @clr
|
||||
set output
|
||||
41
Task/Brownian-tree/Gnuplot/brownian-tree-2.gnuplot
Normal file
41
Task/Brownian-tree/Gnuplot/brownian-tree-2.gnuplot
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
## BTff.gp 11/27/16 aev
|
||||
## Plotting 6 Brownian tree pictures.
|
||||
## dat-files are PARI/GP generated output files:
|
||||
## http://rosettacode.org/wiki/Brownian_tree#PARI.2FGP
|
||||
#cd 'C:\gnupData'
|
||||
|
||||
##BT1
|
||||
clr = '"dark-green"'
|
||||
filename = "BTAH1"
|
||||
ttl = "Brownian Tree v.#1"
|
||||
load "plotff.gp"
|
||||
|
||||
##BT2
|
||||
clr = '"brown"'
|
||||
filename = "BTOC1"
|
||||
ttl = "Brownian Tree v.#2"
|
||||
load "plotff.gp"
|
||||
|
||||
##BT3
|
||||
clr = '"navy"'
|
||||
filename = "BTSE1"
|
||||
ttl = "Brownian Tree v.#3"
|
||||
load "plotff.gp"
|
||||
|
||||
##BT41
|
||||
clr = '"red"'
|
||||
filename = "BTPB1"
|
||||
ttl = "Brownian Tree v.#4-1"
|
||||
load "plotff.gp"
|
||||
|
||||
##BT42
|
||||
clr = '"red"'
|
||||
filename = "BTPB2"
|
||||
ttl = "Brownian Tree v.#4-2"
|
||||
load "plotff.gp"
|
||||
|
||||
##BT43
|
||||
clr = '"red"'
|
||||
filename = "BTPB3"
|
||||
ttl = "Brownian Tree v.#4-3"
|
||||
load "plotff.gp"
|
||||
85
Task/Brownian-tree/Go/brownian-tree-1.go
Normal file
85
Task/Brownian-tree/Go/brownian-tree-1.go
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"math/rand"
|
||||
"os"
|
||||
)
|
||||
|
||||
const w = 400 // image width
|
||||
const h = 300 // image height
|
||||
const n = 15000 // number of particles to add
|
||||
const frost = 255 // white
|
||||
|
||||
var g *image.Gray
|
||||
|
||||
func main() {
|
||||
g = image.NewGray(image.Rectangle{image.Point{0, 0}, image.Point{w, h}})
|
||||
// off center seed position makes pleasingly asymetrical tree
|
||||
g.SetGray(w/3, h/3, color.Gray{frost})
|
||||
generate:
|
||||
for a := 0; a < n; {
|
||||
// generate random position for new particle
|
||||
rp := image.Point{rand.Intn(w), rand.Intn(h)}
|
||||
if g.At(rp.X, rp.Y).(color.Gray).Y == frost {
|
||||
// position is already set. find a nearby free position.
|
||||
for {
|
||||
rp.X += rand.Intn(3) - 1
|
||||
rp.Y += rand.Intn(3) - 1
|
||||
// execpt if we run out of bounds, consider the particle lost.
|
||||
if !rp.In(g.Rect) {
|
||||
continue generate
|
||||
}
|
||||
if g.At(rp.X, rp.Y).(color.Gray).Y != frost {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// else particle is in free space. let it wander
|
||||
// until it touches tree
|
||||
for !hasNeighbor(rp) {
|
||||
rp.X += rand.Intn(3) - 1
|
||||
rp.Y += rand.Intn(3) - 1
|
||||
// but again, if it wanders out of bounds consider it lost.
|
||||
if !rp.In(g.Rect) {
|
||||
continue generate
|
||||
}
|
||||
}
|
||||
}
|
||||
// x, y now specify a free position toucing the tree.
|
||||
g.SetGray(rp.X, rp.Y, color.Gray{frost})
|
||||
a++
|
||||
// progress indicator
|
||||
if a%100 == 0 {
|
||||
fmt.Println(a, "of", n)
|
||||
}
|
||||
}
|
||||
f, err := os.Create("tree.png")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
err = png.Encode(f, g)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
|
||||
var n8 = []image.Point{
|
||||
{-1, -1}, {-1, 0}, {-1, 1},
|
||||
{0, -1}, {0, 1},
|
||||
{1, -1}, {1, 0}, {1, 1}}
|
||||
|
||||
func hasNeighbor(p image.Point) bool {
|
||||
for _, n := range n8 {
|
||||
o := p.Add(n)
|
||||
if o.In(g.Rect) && g.At(o.X, o.Y).(color.Gray).Y == frost {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
79
Task/Brownian-tree/Go/brownian-tree-2.go
Normal file
79
Task/Brownian-tree/Go/brownian-tree-2.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package main
|
||||
|
||||
// Files required to build supporting package raster are found in:
|
||||
// * Bitmap
|
||||
// * Grayscale image
|
||||
// * Write a PPM file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"raster"
|
||||
)
|
||||
|
||||
const w = 400 // image width
|
||||
const h = 300 // image height
|
||||
const n = 15000 // number of particles to add
|
||||
const frost = 65535 // white
|
||||
|
||||
var g *raster.Grmap
|
||||
|
||||
func main() {
|
||||
g = raster.NewGrmap(w, h)
|
||||
// off center seed position makes pleasingly asymetrical tree
|
||||
g.SetPx(w/3, h/3, frost)
|
||||
var x, y int
|
||||
generate:
|
||||
for a := 0; a < n; {
|
||||
// generate random position for new particle
|
||||
x, y = rand.Intn(w), rand.Intn(h)
|
||||
switch p, ok := g.GetPx(x, y); p {
|
||||
case frost:
|
||||
// position is already set. find a nearby free position.
|
||||
for p == frost {
|
||||
x += rand.Intn(3) - 1
|
||||
y += rand.Intn(3) - 1
|
||||
p, ok = g.GetPx(x, y)
|
||||
|
||||
// execpt if we run out of bounds, consider the particle lost.
|
||||
if !ok {
|
||||
continue generate
|
||||
}
|
||||
}
|
||||
default:
|
||||
// else particle is in free space. let it wander
|
||||
// until it touches tree
|
||||
for !hasNeighbor(x, y) {
|
||||
x += rand.Intn(3) - 1
|
||||
y += rand.Intn(3) - 1
|
||||
// but again, if it wanders out of bounds consider it lost.
|
||||
_, ok = g.GetPx(x, y)
|
||||
if !ok {
|
||||
continue generate
|
||||
}
|
||||
}
|
||||
}
|
||||
// x, y now specify a free position toucing the tree.
|
||||
g.SetPx(x, y, frost)
|
||||
a++
|
||||
// progress indicator
|
||||
if a%100 == 0 {
|
||||
fmt.Println(a, "of", n)
|
||||
}
|
||||
}
|
||||
g.Bitmap().WritePpmFile("tree.ppm")
|
||||
}
|
||||
|
||||
var n8 = [][]int{
|
||||
{-1, -1}, {-1, 0}, {-1, 1},
|
||||
{ 0, -1}, { 0, 1},
|
||||
{ 1, -1}, { 1, 0}, { 1, 1}}
|
||||
|
||||
func hasNeighbor(x, y int) bool {
|
||||
for _, n := range n8 {
|
||||
if p, ok := g.GetPx(x+n[0], y+n[1]); ok && p == frost {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
46
Task/Brownian-tree/Haskell/brownian-tree.hs
Normal file
46
Task/Brownian-tree/Haskell/brownian-tree.hs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import Control.Monad
|
||||
import Control.Monad.ST
|
||||
import Data.STRef
|
||||
import Data.Array.ST
|
||||
import System.Random
|
||||
import Bitmap
|
||||
import Bitmap.BW
|
||||
import Bitmap.Netpbm
|
||||
|
||||
main = do
|
||||
g <- getStdGen
|
||||
(t, _) <- stToIO $ drawTree (50, 50) (25, 25) 300 g
|
||||
writeNetpbm "/tmp/tree.pbm" t
|
||||
|
||||
drawTree :: (Int, Int) -> (Int, Int) -> Int -> StdGen -> ST s (Image s BW, StdGen)
|
||||
drawTree (width, height) start steps stdgen = do
|
||||
img <- image width height off
|
||||
setPix img (Pixel start) on
|
||||
gen <- newSTRef stdgen
|
||||
let -- randomElem :: [a] -> ST s a
|
||||
randomElem l = do
|
||||
stdgen <- readSTRef gen
|
||||
let (i, stdgen') = randomR (0, length l - 1) stdgen
|
||||
writeSTRef gen stdgen'
|
||||
return $ l !! i
|
||||
-- newPoint :: ST s (Int, Int)
|
||||
newPoint = do
|
||||
p <- randomElem border
|
||||
c <- getPix img $ Pixel p
|
||||
if c == off then return p else newPoint
|
||||
-- wander :: (Int, Int) -> ST s ()
|
||||
wander p = do
|
||||
next <- randomElem $ filter (inRange pointRange) $ adjacent p
|
||||
c <- getPix img $ Pixel next
|
||||
if c == on then setPix img (Pixel p) on else wander next
|
||||
replicateM_ steps $ newPoint >>= wander
|
||||
stdgen <- readSTRef gen
|
||||
return (img, stdgen)
|
||||
where pointRange = ((0, 0), (width - 1, height - 1))
|
||||
adjacent (x, y) = [(x - 1, y - 1), (x, y - 1), (x + 1, y - 1),
|
||||
(x - 1, y), (x + 1, y),
|
||||
(x - 1, y + 1), (x, y + 1), (x + 1, y + 1)]
|
||||
border = liftM2 (,) [0, width - 1] [0 .. height - 1] ++
|
||||
liftM2 (,) [1 .. width - 2] [0, height - 1]
|
||||
off = black
|
||||
on = white
|
||||
66
Task/Brownian-tree/Icon/brownian-tree.icon
Normal file
66
Task/Brownian-tree/Icon/brownian-tree.icon
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
link graphics,printf
|
||||
|
||||
procedure main() # brownian tree
|
||||
|
||||
Density := .08 # % particles to area
|
||||
SeedArea := .5 # central area to confine seed
|
||||
ParticleArea := .7 # central area to exclude particles appearing
|
||||
Height := Width := 400 # canvas
|
||||
|
||||
Particles := Height * Width * Density
|
||||
Field := list(Height)
|
||||
every !Field := list(Width)
|
||||
|
||||
Size := sprintf("size=%d,%d",Width,Height)
|
||||
Fg := sprintf("fg=%s",?["green","red","blue"])
|
||||
Label := sprintf("label=Brownian Tree %dx%d PA=%d%% SA=%d%% D=%d%%",
|
||||
Width,Height,ParticleArea*100,SeedArea*100,Density*100)
|
||||
WOpen(Label,Size,Fg,"bg=black") | stop("Unable to open Window")
|
||||
|
||||
sx := Height * SetInside(SeedArea)
|
||||
sy := Width * SetInside(SeedArea)
|
||||
Field[sx,sy] := 1
|
||||
DrawPoint(sx,sy) # Seed the field
|
||||
|
||||
Lost := 0
|
||||
|
||||
every 1 to Particles do {
|
||||
repeat {
|
||||
px := Height * SetOutside(ParticleArea)
|
||||
py := Width * SetOutside(ParticleArea)
|
||||
if /Field[px,py] then
|
||||
break # don't materialize in the tree
|
||||
}
|
||||
repeat {
|
||||
dx := delta()
|
||||
dy := delta()
|
||||
if not ( xy := Field[px+dx,py+dy] ) then {
|
||||
Lost +:= 1
|
||||
next # lost try again
|
||||
}
|
||||
if \xy then
|
||||
break # collision
|
||||
|
||||
px +:= dx # move to clear spot
|
||||
py +:= dy
|
||||
}
|
||||
Field[px,py] := 1
|
||||
DrawPoint(px,py) # Stick the particle
|
||||
}
|
||||
printf("Brownian Tree Complete: Particles=%d Lost=%d.\n",Particles,Lost)
|
||||
WDone()
|
||||
end
|
||||
|
||||
procedure delta() #: return a random 1 pixel perturbation
|
||||
return integer(?0 * 3) - 1
|
||||
end
|
||||
|
||||
procedure SetInside(core) #: set coord inside area
|
||||
return core * ?0 + (1-core)/2
|
||||
end
|
||||
|
||||
procedure SetOutside(core) #: set coord outside area
|
||||
pt := ?0 * (1 - core)
|
||||
pt +:= ( pt > (1-core)/2, core)
|
||||
return pt
|
||||
end
|
||||
19
Task/Brownian-tree/J/brownian-tree-1.j
Normal file
19
Task/Brownian-tree/J/brownian-tree-1.j
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
brtr=:4 :0
|
||||
seed=. ?x
|
||||
clip=. 0 >. (<:x) <."1 ]
|
||||
near=. [: clip +"1/&(,"0/~i:1)
|
||||
p=.i.0 2
|
||||
mask=. 1 (<"1 near seed)} x$0
|
||||
field=.1 (<seed)} x$0
|
||||
for.i.y do.
|
||||
p=. clip (p +"1 <:?3$~$p),?x
|
||||
b=.(<"1 p) { mask
|
||||
fix=. b#p
|
||||
if.#fix do. NB. if. works around j602 bug: 0(0#a:)}i.0 0
|
||||
p=. (-.b)# p
|
||||
mask=. 1 (<"1 near fix)} mask
|
||||
field=. 1 (<"1 fix)} field
|
||||
end.
|
||||
end.
|
||||
field
|
||||
)
|
||||
2
Task/Brownian-tree/J/brownian-tree-2.j
Normal file
2
Task/Brownian-tree/J/brownian-tree-2.j
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
require'viewmat'
|
||||
viewmat 480 640 brtr 30000
|
||||
72
Task/Brownian-tree/Java/brownian-tree-1.java
Normal file
72
Task/Brownian-tree/Java/brownian-tree-1.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.*;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
public class BrownianTree extends JFrame implements Runnable {
|
||||
|
||||
BufferedImage I;
|
||||
private List<Particle> particles;
|
||||
static Random rand = new Random();
|
||||
|
||||
public BrownianTree() {
|
||||
super("Brownian Tree");
|
||||
setBounds(100, 100, 400, 300);
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
I = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
|
||||
I.setRGB(I.getWidth() / 2, I.getHeight() / 2, 0xff00);
|
||||
particles = new LinkedList<Particle>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
g.drawImage(I, 0, 0, this);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
particles.add(new Particle());
|
||||
}
|
||||
while (!particles.isEmpty()) {
|
||||
for (Iterator<Particle> it = particles.iterator(); it.hasNext();) {
|
||||
if (it.next().move()) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
BrownianTree b = new BrownianTree();
|
||||
b.setVisible(true);
|
||||
new Thread(b).start();
|
||||
}
|
||||
|
||||
private class Particle {
|
||||
|
||||
private int x, y;
|
||||
|
||||
private Particle() {
|
||||
x = rand.nextInt(I.getWidth());
|
||||
y = rand.nextInt(I.getHeight());
|
||||
}
|
||||
|
||||
/* returns true if either out of bounds or collided with tree */
|
||||
private boolean move() {
|
||||
int dx = rand.nextInt(3) - 1;
|
||||
int dy = rand.nextInt(3) - 1;
|
||||
if ((x + dx < 0) || (y + dy < 0)
|
||||
|| (y + dy >= I.getHeight()) || (x + dx >= I.getWidth())) {
|
||||
return true;
|
||||
}
|
||||
x += dx;
|
||||
y += dy;
|
||||
if ((I.getRGB(x, y) & 0xff00) == 0xff00) {
|
||||
I.setRGB(x - dx, y - dy, 0xff00);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
90
Task/Brownian-tree/Java/brownian-tree-2.java
Normal file
90
Task/Brownian-tree/Java/brownian-tree-2.java
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import java.awt.Point;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class BasicBrownianTree {
|
||||
|
||||
private int pixelsLost;
|
||||
private Point p;
|
||||
private Point nextP;
|
||||
private int pixelCount;
|
||||
private int width;
|
||||
private int height;
|
||||
private int color;
|
||||
private BufferedImage img;
|
||||
|
||||
public BasicBrownianTree( int argb, int size, double density ) {
|
||||
pixelsLost = 0;
|
||||
p = new Point();
|
||||
nextP = new Point();
|
||||
width = size;
|
||||
height = size;
|
||||
color = argb;
|
||||
pixelCount = (int) ( width * height * density );
|
||||
img = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB );
|
||||
}
|
||||
|
||||
public void generate() {
|
||||
// print text to the console
|
||||
System.out.println( "Drawing " + pixelCount + " pixels" );
|
||||
int background = img.getRGB( 0, 0 );
|
||||
img.setRGB( width / 2, height / 2, color );
|
||||
|
||||
for( int i = 0; i < pixelCount; i++ ) {
|
||||
p.x = (int) ( Math.random() * width );
|
||||
p.y = (int) ( Math.random() * height );
|
||||
|
||||
while ( true ) {
|
||||
int dx = (int) ( Math.random() * 3 ) - 1;
|
||||
int dy = (int) ( Math.random() * 3 ) - 1;
|
||||
nextP.setLocation( p.x + dx, p.y + dy );
|
||||
// handle out-of-bounds
|
||||
if ( nextP.x < 0 || nextP.x >= width || nextP.y < 0
|
||||
|| nextP.y >= height ) {
|
||||
// increment the number of pixels lost and escape the loop
|
||||
pixelsLost++;
|
||||
break;
|
||||
}
|
||||
if ( img.getRGB( nextP.x, nextP.y ) != background ) {
|
||||
img.setRGB( p.x, p.y, color );
|
||||
break;
|
||||
}
|
||||
p.setLocation( nextP );
|
||||
}
|
||||
// Print a message every 2%
|
||||
if ( i % ( pixelCount / 50 ) == 0 ) {
|
||||
System.out.println( "Done with " + i + " pixels" );
|
||||
}
|
||||
}
|
||||
// We're done. Let the user know how many pixels were lost
|
||||
System.out.println( "Finished. Pixels lost = " + pixelsLost );
|
||||
}
|
||||
|
||||
public BufferedImage getImage() {
|
||||
return img;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public static void main( String[] args ) {
|
||||
// create the new generator
|
||||
BasicBrownianTree generator = new BasicBrownianTree( 0x664444ff, 400, 0.4 );
|
||||
// generate the image
|
||||
generator.generate();
|
||||
try {
|
||||
// save the image to the file "image.png"
|
||||
ImageIO.write( generator.getImage(), "png", new File( "image.png" ) );
|
||||
} catch ( IOException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
129
Task/Brownian-tree/JavaScript/brownian-tree-1.js
Normal file
129
Task/Brownian-tree/JavaScript/brownian-tree-1.js
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
function brownian(canvasId, messageId) {
|
||||
var canvas = document.getElementById(canvasId);
|
||||
var ctx = canvas.getContext("2d");
|
||||
|
||||
// Options
|
||||
var drawPos = true;
|
||||
var seedResolution = 50;
|
||||
var clearShade = 0; // 0..255
|
||||
|
||||
// Static state
|
||||
var width = canvas.width;
|
||||
var height = canvas.height;
|
||||
var cx = width/2;
|
||||
var cy = height/2;
|
||||
var clearStyle = "rgba("+clearShade+", "+clearShade+", "+clearShade+", 1)";
|
||||
|
||||
// Utilities
|
||||
function radius(x,y) {
|
||||
return Math.sqrt((x-cx)*(x-cy)+(y-cx)*(y-cy));
|
||||
}
|
||||
function test(x, y) {
|
||||
if (x < 0 || y < 0 || x >= width || y >= height)
|
||||
return false;
|
||||
var data = ctx.getImageData(x, y, 1, 1).data;
|
||||
return data[0] != clearShade || data[1] != clearShade || data[2] != clearShade;
|
||||
}
|
||||
var shade = 120;
|
||||
function setc(x, y, c) {
|
||||
//var imgd = ctx.createImageData(1, 1);
|
||||
//var pix = imgd.data;
|
||||
//pix[0] = pix[1] = pix[2] = c == 255 ? 255 : shade;
|
||||
//pix[3] = 255;
|
||||
//shade = (shade + 1) % 254;
|
||||
//ctx.putImageData(imgd, x, y);
|
||||
//ctx.fillStyle = "rgba("+c+", "+c+", "+c+", 1)";
|
||||
shade = (shade + 0.02) % 360;
|
||||
if (c) {
|
||||
ctx.fillStyle = "hsl("+shade+", 100%, 50%)";
|
||||
} else {
|
||||
ctx.fillStyle = clearStyle;
|
||||
}
|
||||
ctx.fillRect (x, y, 1, 1);
|
||||
}
|
||||
function set(x,y) {
|
||||
setc(x,y,true);
|
||||
}
|
||||
function clear(x,y) {
|
||||
setc(x,y,false);
|
||||
}
|
||||
|
||||
// Initialize canvas to blank opaque
|
||||
ctx.fillStyle = clearStyle;
|
||||
ctx.fillRect (0, 0, width, height);
|
||||
|
||||
// Current position
|
||||
var x;
|
||||
var y;
|
||||
|
||||
// Farthest distance from center a particle has yet been placed.
|
||||
var closeRadius = 1;
|
||||
|
||||
// Place seed
|
||||
set(cx, cy);
|
||||
|
||||
// Choose a new random position for a particle (not necessarily unoccupied)
|
||||
function newpos() {
|
||||
// Wherever particles are injected, the tree will tend to grow faster
|
||||
// toward it. Ideally, particles wander in from infinity; the best we
|
||||
// could do is to have them wander in from the edge of the field.
|
||||
// But in order to have the rendering occur in a reasonable time when
|
||||
// the seed is small, without too much visible bias, we instead place
|
||||
// the particles in a coarse grid. The final tree will cover every
|
||||
// point on the grid.
|
||||
//
|
||||
// There's probably a better strategy than this.
|
||||
x = Math.floor(Math.random()*(width/seedResolution))*seedResolution;
|
||||
y = Math.floor(Math.random()*(height/seedResolution))*seedResolution;
|
||||
}
|
||||
newpos();
|
||||
|
||||
var animation;
|
||||
animation = window.setInterval(function () {
|
||||
if (drawPos) clear(x,y);
|
||||
for (var i = 0; i < 10000; i++) {
|
||||
var ox = x;
|
||||
var oy = y;
|
||||
|
||||
// Changing this to use only the first four directions will result
|
||||
// in a denser tree.
|
||||
switch (Math.floor(Math.random()*8)) {
|
||||
case 0: x++; break;
|
||||
case 1: x--; break;
|
||||
case 2: y++; break;
|
||||
case 3: y--; break;
|
||||
case 4: x++; y++; break;
|
||||
case 5: x--; y++; break;
|
||||
case 6: x++; y--; break;
|
||||
case 7: x--; y--; break;
|
||||
}
|
||||
if (x < 0 || y < 0 ||
|
||||
x >= width || y >= height ||
|
||||
radius(x,y) > closeRadius+seedResolution+2) {
|
||||
// wandered out of bounds or out of interesting range of the
|
||||
// tree, so pick a new spot
|
||||
var progress = 1000;
|
||||
do {
|
||||
newpos();
|
||||
progress--;
|
||||
} while ((test(x-1,y-1) || test(x,y-1) || test(x+1,y-1) ||
|
||||
test(x-1,y ) || test(x,y ) || test(x+1,y ) ||
|
||||
test(x-1,y+1) || test(x,y+1) || test(x+1,y+1)) && progress > 0);
|
||||
if (progress <= 0) {
|
||||
document.getElementById(messageId).appendChild(
|
||||
document.createTextNode("Stopped for lack of room."));
|
||||
clearInterval(animation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (test(x, y)) {
|
||||
// hit something, mark where we came from and pick a new spot
|
||||
set(ox,oy);
|
||||
closeRadius = Math.max(closeRadius, radius(ox,oy));
|
||||
newpos();
|
||||
}
|
||||
}
|
||||
if (drawPos) set(x,y);
|
||||
}, 1);
|
||||
|
||||
}
|
||||
9
Task/Brownian-tree/JavaScript/brownian-tree-2.js
Normal file
9
Task/Brownian-tree/JavaScript/brownian-tree-2.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="brownian.js"></script>
|
||||
</head>
|
||||
<body onload="brownian('canvas', 'message')">
|
||||
<canvas id="canvas" width="402" height="402" style="border: 2px inset;"></canvas>
|
||||
<div id="message"></div>
|
||||
</body>
|
||||
</html>
|
||||
42
Task/Brownian-tree/Julia/brownian-tree.julia
Normal file
42
Task/Brownian-tree/Julia/brownian-tree.julia
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using Images, FileIO
|
||||
|
||||
function main(h::Integer, w::Integer, side::Bool=false)
|
||||
W0 = w >> 1
|
||||
H0 = h >> 1
|
||||
@inline function motecolor(x::Integer, y::Integer)
|
||||
h = clamp(180 * (atan2(y - H0, x - W0) / π + 1.0), 0.0, 360.0)
|
||||
return HSV(h, 0.5, 0.5)
|
||||
end
|
||||
|
||||
img = zeros(RGB{N0f8}, h, w)
|
||||
img[H0, W0] = RGB(1, 1, 1)
|
||||
free = trues(h, w)
|
||||
free[H0, W0] = false
|
||||
for i in eachindex(img)
|
||||
x = rand(1:h)
|
||||
y = rand(1:w)
|
||||
free[x, y] || continue
|
||||
mc = motecolor(x, y)
|
||||
for j in 1:1000
|
||||
xp = x + rand(-1:1)
|
||||
yp = y + rand(-1:1)
|
||||
contained = checkbounds(Bool, img, xp, yp)
|
||||
if contained && free[xp, yp]
|
||||
x, y = xp, yp
|
||||
continue
|
||||
else
|
||||
if side || (contained && !free[xp, yp])
|
||||
free[x, y] = false
|
||||
img[x, y] = mc
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return img
|
||||
end
|
||||
|
||||
imgnoside = main(256, 256)
|
||||
imgwtside = main(256, 256, true)
|
||||
save("data/browniantree_noside.jpg", imgnoside)
|
||||
save("data/browniantree_wtside.jpg", imgwtside)
|
||||
64
Task/Brownian-tree/Kotlin/brownian-tree.kotlin
Normal file
64
Task/Brownian-tree/Kotlin/brownian-tree.kotlin
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// version 1.1.2
|
||||
|
||||
import java.awt.Graphics
|
||||
import java.awt.image.BufferedImage
|
||||
import java.util.*
|
||||
import javax.swing.JFrame
|
||||
|
||||
class BrownianTree : JFrame("Brownian Tree"), Runnable {
|
||||
private val img: BufferedImage
|
||||
private val particles = LinkedList<Particle>()
|
||||
|
||||
private companion object {
|
||||
val rand = Random()
|
||||
}
|
||||
|
||||
private inner class Particle {
|
||||
private var x = rand.nextInt(img.width)
|
||||
private var y = rand.nextInt(img.height)
|
||||
|
||||
/* returns true if either out of bounds or collided with tree */
|
||||
fun move(): Boolean {
|
||||
val dx = rand.nextInt(3) - 1
|
||||
val dy = rand.nextInt(3) - 1
|
||||
if ((x + dx < 0) || (y + dy < 0) || (y + dy >= img.height) ||
|
||||
(x + dx >= img.width)) return true
|
||||
x += dx
|
||||
y += dy
|
||||
if ((img.getRGB(x, y) and 0xff00) == 0xff00) {
|
||||
img.setRGB(x - dx, y - dy, 0xff00)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
setBounds(100, 100, 400, 300)
|
||||
defaultCloseOperation = EXIT_ON_CLOSE
|
||||
img = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
|
||||
img.setRGB(img.width / 2, img.height / 2, 0xff00)
|
||||
}
|
||||
|
||||
override fun paint(g: Graphics) {
|
||||
g.drawImage(img, 0, 0, this)
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
(0 until 20000).forEach { particles.add(Particle()) }
|
||||
|
||||
while (!particles.isEmpty()) {
|
||||
val iter = particles.iterator()
|
||||
while (iter.hasNext()) {
|
||||
if (iter.next().move()) iter.remove()
|
||||
}
|
||||
repaint()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val b = BrownianTree()
|
||||
b.isVisible = true
|
||||
Thread(b).start()
|
||||
}
|
||||
83
Task/Brownian-tree/Liberty-BASIC/brownian-tree.basic
Normal file
83
Task/Brownian-tree/Liberty-BASIC/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
'[RC]Brownian motion tree
|
||||
nomainwin
|
||||
dim screen(600,600)
|
||||
WindowWidth = 600
|
||||
WindowHeight = 600
|
||||
open "Brownian" for graphics_nsb_nf as #1
|
||||
#1 "trapclose [quit]"
|
||||
#1 "down ; fill blue"
|
||||
rad=57.29577951
|
||||
particles=500
|
||||
|
||||
'draw starting circle and mid point
|
||||
for n= 1 to 360
|
||||
x=300-(200*sin(n/rad))
|
||||
y=300-(200*cos(n/rad))
|
||||
#1, "color white ; set ";x;" ";y
|
||||
screen(x,y)=1
|
||||
next n
|
||||
#1, "color white ; set 300 300"
|
||||
screen(300,300)=1
|
||||
|
||||
'set up initial particles
|
||||
dim particle(particles,9)'x y deltax deltay rotx roty
|
||||
for n = 1 to particles
|
||||
gosub [randomparticle]
|
||||
next
|
||||
|
||||
'start timed drawing loop
|
||||
timer 17, [draw]
|
||||
wait
|
||||
|
||||
|
||||
[draw]
|
||||
#1 "discard"
|
||||
scan
|
||||
for n = 1 to particles
|
||||
oldx=particle(n,1)
|
||||
oldy=particle(n,2)
|
||||
|
||||
'erase particle
|
||||
if not(screen(oldx,oldy)) then
|
||||
#1 "color blue ; set ";oldx;" ";oldy
|
||||
end if
|
||||
|
||||
'move particle x
|
||||
particle(n,1)=particle(n,1)+int((sin(particle(n,6)/rad)*10)+particle(n,3))
|
||||
particle(n,5)=particle(n,5)+6 mod 360
|
||||
if particle(n,1)>599 or particle(n,1)<1 then gosub [randomparticle]
|
||||
|
||||
'move particle y
|
||||
particle(n,2)=particle(n,2)+int((sin(particle(n,5)/rad)*10)+particle(n,4))
|
||||
particle(n,6)=particle(n,6)+6 mod 360
|
||||
if particle(n,2)>599 or particle(n,2)<1 then gosub [randomparticle]
|
||||
|
||||
'checkhit
|
||||
x=particle(n,1)
|
||||
y=particle(n,2)
|
||||
if screen(x-1,y-1) or screen(x-1,y) or screen(x-1,y+1)_
|
||||
or screen(x,y-1) or screen(x,y) or screen(x,y+1)_
|
||||
or screen(x+1,y-1) or screen(x+1,y) or screen(x+1,y+1) then
|
||||
#1 "color white ; set ";particle(n,1);" ";particle(n,2)
|
||||
screen(particle(n,1),particle(n,2))=1
|
||||
else
|
||||
#1 "color red ; set ";particle(n,1);" ";particle(n,2)
|
||||
end if
|
||||
next
|
||||
wait
|
||||
|
||||
|
||||
|
||||
[randomparticle]
|
||||
particle(n,1)=int(rnd(0)*599)+1
|
||||
particle(n,2)=int(rnd(0)*599)+1
|
||||
particle(n,3)=int(2-rnd(0)*4)
|
||||
particle(n,4)=int(2-rnd(0)*4)
|
||||
particle(n,5)=int(rnd(0)*360)
|
||||
particle(n,6)=int(rnd(0)*360)
|
||||
return
|
||||
|
||||
[quit]
|
||||
timer 0
|
||||
close #1
|
||||
end
|
||||
16
Task/Brownian-tree/Locomotive-Basic/brownian-tree.basic
Normal file
16
Task/Brownian-tree/Locomotive-Basic/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
10 MODE 1:DEFINT a-z:RANDOMIZE TIME:np=10000
|
||||
20 INK 0,0:INK 1,26:BORDER 0
|
||||
30 PLOT 320,200
|
||||
40 FOR i=1 TO np
|
||||
50 GOSUB 1000
|
||||
60 IF TEST(x+1,y+1)+TEST(x,y+1)+TEST(x+1,y)+TEST(x-1,y-1)+TEST(x-1,y)+TEST(x,y-1)<>0 THEN 100
|
||||
70 x=x+RND*2-1: y=y+RND*2-1
|
||||
80 IF x<1 OR x>640 OR y<1 OR y>400 THEN GOSUB 1000
|
||||
90 GOTO 60
|
||||
100 PLOT x,y
|
||||
110 NEXT
|
||||
120 END
|
||||
1000 ' Calculate new position
|
||||
1010 x=RND*640
|
||||
1020 y=RND*400
|
||||
1030 RETURN
|
||||
67
Task/Brownian-tree/Lua/brownian-tree.lua
Normal file
67
Task/Brownian-tree/Lua/brownian-tree.lua
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
function SetSeed( f )
|
||||
for i = 1, #f[1] do -- the whole boundary of the scene is used as the seed
|
||||
f[1][i] = 1
|
||||
f[#f][i] = 1
|
||||
end
|
||||
for i = 1, #f do
|
||||
f[i][1] = 1
|
||||
f[i][#f[1]] = 1
|
||||
end
|
||||
end
|
||||
|
||||
function SetParticle( f )
|
||||
local pos_x, pos_y
|
||||
repeat
|
||||
pos_x = math.random( #f )
|
||||
pos_y = math.random( #f[1] )
|
||||
until f[pos_x][pos_y] == 0
|
||||
|
||||
return pos_x, pos_y
|
||||
end
|
||||
|
||||
|
||||
function Iterate( f, num_particles )
|
||||
for i = 1, num_particles do
|
||||
local pos_x, pos_y = SetParticle( f )
|
||||
|
||||
while true do
|
||||
local dx = math.random(5) - 3
|
||||
local dy = math.random(5) - 3
|
||||
|
||||
if ( pos_x+dx >= 1 and pos_x+dx <= #f and pos_y+dy >= 1 and pos_y+dy <= #f[1] ) then
|
||||
if f[pos_x+dx][pos_y+dy] ~= 0 then
|
||||
f[pos_x][pos_y] = 1
|
||||
break
|
||||
else
|
||||
pos_x = pos_x + dx
|
||||
pos_y = pos_y + dy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
size_x, size_y = 400, 400 -- size of the scene
|
||||
num_particles = 16000
|
||||
|
||||
math.randomseed( os.time() )
|
||||
|
||||
f = {}
|
||||
for i = 1, size_x do
|
||||
f[i] = {}
|
||||
for j = 1, size_y do
|
||||
f[i][j] = 0
|
||||
end
|
||||
end
|
||||
|
||||
SetSeed( f )
|
||||
Iterate( f, num_particles )
|
||||
|
||||
-- prepare the data for writing into a ppm-image file
|
||||
for i = 1, size_x do
|
||||
for j = 1, size_y do
|
||||
if f[i][j] == 1 then f[i][j] = 255 end
|
||||
end
|
||||
end
|
||||
Write_PPM( "brownian_tree.ppm", ConvertToColorImage(f) )
|
||||
26
Task/Brownian-tree/Mathematica/brownian-tree.math
Normal file
26
Task/Brownian-tree/Mathematica/brownian-tree.math
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
canvasdim = 1000;
|
||||
n = 0.35*canvasdim^2;
|
||||
canvas = ConstantArray[0, {canvasdim, canvasdim}];
|
||||
init = Floor@(0.5*{canvasdim, canvasdim}); (*RandomInteger[canvasdim,2]*)
|
||||
canvas[[init[[1]], init[[2]]]] = 1; (*1st particle initialized to midpoint*)
|
||||
|
||||
Monitor[ (*Provides real-time intermediate result monitoring*)
|
||||
Do[
|
||||
particle = RandomInteger[canvasdim, 2];
|
||||
While[True,
|
||||
ds = RandomInteger[{-1, 1}, 2];
|
||||
While[ (*New Particle Domain Limit Section*)
|
||||
!And @@ (0 < (particle + ds)[[#]] <= canvasdim & /@ {1, 2}),
|
||||
particle = RandomInteger[canvasdim, 2];
|
||||
];
|
||||
(* Particle Aggregation Section *)
|
||||
If[canvas[[(particle + ds)[[1]], (particle + ds)[[2]]]] > 0,
|
||||
canvas[[particle[[1]], particle[[2]]]] = i;
|
||||
Break[],
|
||||
particle += ds
|
||||
];
|
||||
],
|
||||
{i, n}],
|
||||
{i, (particle + ds), MatrixPlot@canvas}
|
||||
]
|
||||
MatrixPlot[canvas,FrameTicks->None,ColorFunction->"DarkRainbow",ColorRules->{0 -> None}]
|
||||
43
Task/Brownian-tree/Nim/brownian-tree.nim
Normal file
43
Task/Brownian-tree/Nim/brownian-tree.nim
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import random
|
||||
import imageman
|
||||
|
||||
const
|
||||
Size = 400 # Area size.
|
||||
MaxXY = Size - 1 # Maximum possible value for x and y.
|
||||
NPart = 25_000 # Number of particles.
|
||||
Background = ColorRGBU [byte 0, 0, 0] # Background color.
|
||||
Foreground = ColorRGBU [byte 50, 150, 255] # Foreground color.
|
||||
|
||||
randomize()
|
||||
var image = initImage[ColorRGBU](Size, Size)
|
||||
image.fill(Background)
|
||||
image[Size div 2, Size div 2] = Foreground
|
||||
|
||||
for _ in 1..NPart:
|
||||
|
||||
block ProcessParticle:
|
||||
while true: # Repeat until the particle is freezed.
|
||||
|
||||
# Choose position of particle.
|
||||
var x, y = rand(MaxXY)
|
||||
if image[x, y] == Foreground:
|
||||
continue # Not free. Try again.
|
||||
|
||||
# Move the particle.
|
||||
while true:
|
||||
|
||||
# Choose a motion.
|
||||
let dx, dy = rand(-1..1)
|
||||
inc x, dx
|
||||
inc y, dy
|
||||
if x notin 0..MaxXY or y notin 0..MaxXY:
|
||||
break # Out of limits. Try again.
|
||||
|
||||
# Valid move.
|
||||
if image[x, y] == Foreground:
|
||||
# Not free. Freeze the particle at its previous position.
|
||||
image[x - dx, y - dy] = Foreground
|
||||
break ProcessParticle # Done. Process next particle.
|
||||
|
||||
# Save into a PNG file.
|
||||
image.savePNG("brownian.png", compression = 9)
|
||||
48
Task/Brownian-tree/OCaml/brownian-tree.ocaml
Normal file
48
Task/Brownian-tree/OCaml/brownian-tree.ocaml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
let world_width = 400
|
||||
let world_height = 400
|
||||
let num_particles = 20_000
|
||||
|
||||
let () =
|
||||
assert(num_particles > 0);
|
||||
assert(world_width * world_height > num_particles);
|
||||
;;
|
||||
|
||||
let dla ~world =
|
||||
(* put the tree seed *)
|
||||
world.(world_height / 2).(world_width / 2) <- 1;
|
||||
|
||||
for i = 1 to num_particles do
|
||||
(* looping helper function *)
|
||||
let rec aux px py =
|
||||
(* randomly choose a direction *)
|
||||
let dx = (Random.int 3) - 1 (* offsets *)
|
||||
and dy = (Random.int 3) - 1 in
|
||||
|
||||
if dx + px < 0 || dx + px >= world_width ||
|
||||
dy + py < 0 || dy + py >= world_height then
|
||||
(* plop the particle into some other random location *)
|
||||
aux (Random.int world_width) (Random.int world_height)
|
||||
else if world.(py + dy).(px + dx) <> 0 then
|
||||
(* bumped into something, particle set *)
|
||||
world.(py).(px) <- 1
|
||||
else
|
||||
aux (px + dx) (py + dy)
|
||||
in
|
||||
(* set particle's initial position *)
|
||||
aux (Random.int world_width) (Random.int world_height)
|
||||
done
|
||||
|
||||
let to_pbm ~world =
|
||||
print_endline "P1"; (* Type=Portable bitmap, Encoding=ASCII *)
|
||||
Printf.printf "%d %d\n" world_width world_height;
|
||||
Array.iter (fun line ->
|
||||
Array.iter print_int line;
|
||||
print_newline()
|
||||
) world
|
||||
|
||||
let () =
|
||||
Random.self_init();
|
||||
let world = Array.make_matrix world_width world_height 0 in
|
||||
dla ~world;
|
||||
to_pbm ~world;
|
||||
;;
|
||||
27
Task/Brownian-tree/Octave/brownian-tree.octave
Normal file
27
Task/Brownian-tree/Octave/brownian-tree.octave
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
function r = browniantree(xsize, ysize = xsize, numparticle = 1000)
|
||||
r = zeros(xsize, ysize, "uint8");
|
||||
r(unidrnd(xsize), unidrnd(ysize)) = 1;
|
||||
|
||||
for i = 1:numparticle
|
||||
px = unidrnd(xsize-1)+1;
|
||||
py = unidrnd(ysize-1)+1;
|
||||
while(1)
|
||||
dx = unidrnd(2) - 1;
|
||||
dy = unidrnd(2) - 1;
|
||||
if ( (dx+px < 1) || (dx+px > xsize) || (dy+py < 1) || (dy+py > ysize) )
|
||||
px = unidrnd(xsize-1)+1;
|
||||
py = unidrnd(ysize-1)+1;
|
||||
elseif ( r(px+dx, py+dy) != 0 )
|
||||
r(px, py) = 1;
|
||||
break;
|
||||
else
|
||||
px += dx;
|
||||
py += dy;
|
||||
endif
|
||||
endwhile
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
r = browniantree(200);
|
||||
r( r > 0 ) = 255;
|
||||
jpgwrite("browniantree.jpg", r, 100); % image package
|
||||
28
Task/Brownian-tree/PARI-GP/brownian-tree-1.parigp
Normal file
28
Task/Brownian-tree/PARI-GP/brownian-tree-1.parigp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
\\ 2 old plotting helper functions 3/2/16 aev
|
||||
\\ insm(): Check if x,y are inside matrix mat (+/- p deep).
|
||||
insm(mat,x,y,p=0)={my(xz=#mat[1,],yz=#mat[,1]);
|
||||
return(x+p>0 && x+p<=xz && y+p>0 && y+p<=yz && x-p>0 && x-p<=xz && y-p>0 && y-p<=yz)}
|
||||
\\ plotmat(): Simple plotting using a square matrix mat (filled with 0/1).
|
||||
plotmat(mat)={
|
||||
my(xz=#mat[1,],yz=#mat[,1],vx=List(),vy=vx,x,y);
|
||||
for(i=1,yz, for(j=1,xz, if(mat[i,j]==0, next, listput(vx,i); listput(vy,j))));
|
||||
print(" *** matrix(",xz,"x",yz,") ",#vy, " DOTS");
|
||||
plothraw(Vec(vx),Vec(vy));
|
||||
}
|
||||
\\ 2 new plotting helper functions 11/27/16 aev
|
||||
\\ wrtmat(): Writing file fn containing X,Y coordinates from matrix mat.
|
||||
\\ Created primarily for using file in Gnuplot, also for re-plotting.
|
||||
wrtmat(mat, fn)={
|
||||
my(xz=#mat[1,],yz=#mat[,1],ws,d=0);
|
||||
for(i=1,yz, for(j=1,xz, if(mat[i,j]==0, next, d++; ws=Str(i," ",j); write(fn,ws))));
|
||||
print(" *** matrix(",xz,"x",yz,") ",d, " DOTS put in ",fn);
|
||||
}
|
||||
\\ plotff(): Plotting from a file written by the wrtmat().
|
||||
\\ Saving possibly huge generation time if re-plotting needed.
|
||||
plotff(fn)={
|
||||
my(F,nf,vx=List(),vy=vx,Vr);
|
||||
F=readstr(fn); nf=#F;
|
||||
print(" *** Plotting from: ", fn, " - ", nf, " DOTS");
|
||||
for(i=1,nf, Vr=stok(F[i],","); listput(vx,eval(Vr[1])); listput(vy,eval(Vr[2])));
|
||||
plothraw(Vec(vx),Vec(vy));
|
||||
}
|
||||
26
Task/Brownian-tree/PARI-GP/brownian-tree-2.parigp
Normal file
26
Task/Brownian-tree/PARI-GP/brownian-tree-2.parigp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
\\ Brownian tree v.#1. Translated from AutoHotkey
|
||||
\\ 3/8/2016, upgraded 11/27/16 aev
|
||||
\\ Where: size - size of a square matrix; lim - limit of testing dots;
|
||||
\\ fn - file name (fn=""-only plot, fn!=""-only writing file)..
|
||||
BrownianTree1(size,lim, fn="")={
|
||||
my(Myx=matrix(size,size),sz=size-1,sz2=sz\2,x,y,ox,oy);
|
||||
x=sz2; y=sz2; Myx[y,x]=1; \\ seed in center
|
||||
print(" *** BT1 SEED: ",x,"/",y);
|
||||
for(i=1,lim,
|
||||
x=random(sz)+1; y=random(sz)+1;
|
||||
while(1,
|
||||
ox=x; oy=y;
|
||||
x+=random(3)-1; y+=random(3)-1;
|
||||
if(insm(Myx,x,y)&&Myx[y,x],
|
||||
if(insm(Myx,ox,oy), Myx[oy,ox]=1; break));
|
||||
if(!insm(Myx,x,y), break);
|
||||
);\\wend
|
||||
);\\ fend i
|
||||
if(fn=="", plotmat(Myx), wrtmat(Myx, fn));
|
||||
}
|
||||
\\ Executing 1 or 2 lines below:
|
||||
|
||||
BrownianTree1(400,15000); \\BTAH1.png
|
||||
|
||||
{BrownianTree1(400,15000,"c:\\pariData\\BTAH1.dat");
|
||||
plotff("c:\\pariData\\BTAH1.dat");} \\BTAH1.png
|
||||
24
Task/Brownian-tree/PARI-GP/brownian-tree-3.parigp
Normal file
24
Task/Brownian-tree/PARI-GP/brownian-tree-3.parigp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
\\ Brownian tree v.#2. Translated from Octave
|
||||
\\ 3/8/2016, upgraded 11/27/16 aev
|
||||
\\ Where: size - size of a square matrix; lim - limit of testing dots;
|
||||
\\ fn - file name (fn=""-only plot, fn!=""-only writing file)..
|
||||
BrownianTree2(size,lim, fn="")={
|
||||
my(Myx=matrix(size,size),sz=size-1,dx,dy,x,y);
|
||||
x=random(sz); y=random(sz); Myx[y,x]=1; \\ random seed
|
||||
print(" *** BT2 SEED: ",x,"/",y);
|
||||
for(i=1,lim,
|
||||
x=random(sz)+1; y=random(sz)+1;
|
||||
while(1,
|
||||
dx=random(3)-1; dy=random(3)-1;
|
||||
if(!insm(Myx,x+dx,y+dy), x=random(sz)+1; y=random(sz)+1,
|
||||
if(Myx[y+dy,x+dx], Myx[y,x]=1; break, x+=dx; y+=dy));
|
||||
);\\wend
|
||||
);\\fend i
|
||||
if(fn=="", plotmat(Myx), wrtmat(Myx, fn));
|
||||
}
|
||||
\\ Executing 1 or 2 lines below:
|
||||
|
||||
BrownianTree2(1000,3000); \\BTOC1.png
|
||||
|
||||
{BrownianTree2(1000,3000,"c:\\pariData\\BTOC1.dat");
|
||||
plotff("c:\\pariData\\BTOC1.dat");} \\BTOC1.png
|
||||
26
Task/Brownian-tree/PARI-GP/brownian-tree-4.parigp
Normal file
26
Task/Brownian-tree/PARI-GP/brownian-tree-4.parigp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
\\ Brownian tree v.#3. Translated from Seed7
|
||||
\\ 3/8/2016, upgraded 11/27/16 aev
|
||||
\\ Where: size - size of a square matrix; lim - limit of testing dots;
|
||||
\\ fn - file name (fn=""-only plot, fn!=""-only writing file)..
|
||||
BrownianTree3(size,lim, fn="")={
|
||||
my(Myx=matrix(size,size),sz=size-2,x,y,dx,dy,b=0);
|
||||
x=random(sz); y=random(sz); Myx[y,x]=1; \\ random seed
|
||||
print("*** BT3 SEED: ", x,"/",y);
|
||||
for(i=1,lim,
|
||||
x=random(sz); y=random(sz);
|
||||
b=0; \\ bumped not
|
||||
while(!b,
|
||||
dx=random(3)-1; dy=random(3)-1;
|
||||
if(!insm(Myx,x+dx,y+dy), x=random(sz); y=random(sz),
|
||||
if(Myx[y+dy,x+dx]==1, Myx[y,x]=1; b=1, x+=dx; y+=dy);
|
||||
);
|
||||
);\\wend
|
||||
);\\fend i
|
||||
if(fn=="", plotmat(Myx), wrtmat(Myx, fn));
|
||||
}
|
||||
\\ Executing 1 or 2 lines below:
|
||||
|
||||
BrownianTree3(400,5000); \\BTSE1.png
|
||||
|
||||
{BrownianTree3(400,5000,"c:\\pariData\\BTSE1.dat");
|
||||
plotff("c:\\pariData\\BTSE1.dat");} \\BTSE1.png
|
||||
39
Task/Brownian-tree/PARI-GP/brownian-tree-5.parigp
Normal file
39
Task/Brownian-tree/PARI-GP/brownian-tree-5.parigp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
\\ Brownian tree v.#4. Translated from PureBasic
|
||||
\\ 3/8/2016, upgraded 11/27/16 aev
|
||||
\\ Where: size - size of a square matrix; lim - limit of testing dots;
|
||||
\\ fn - file name (fn=""-only plot, fn!=""-only writing file)..
|
||||
\\ s=1/2(random seed/seed in the center); p=0..n (level of the "deep" checking).
|
||||
BrownianTree4(size,lim, fn="",s=1,p=0)={
|
||||
my(Myx=matrix(size,size),sz=size-3,x,y);
|
||||
\\ seed s=1 for BTPB1, s=2 for BTPB2, BTPB3
|
||||
if(s==1,x=random(sz); y=random(sz), x=sz\2; y=sz\2); Myx[y,x]=1;
|
||||
print(" *** BT4 SEED: ",x,"/",y);
|
||||
for(i=1,lim,
|
||||
if(!(i==1&&s==2), x=random(sz)+1; y=random(sz)+1);
|
||||
while(insm(Myx,x,y,1)&&
|
||||
(Myx[y+1,x+1]+Myx[y+1,x]+Myx[y+1,x-1]+Myx[y,x+1]+
|
||||
Myx[y-1,x-1]+Myx[y,x-1]+Myx[y-1,x]+Myx[y-1,x+1])==0,
|
||||
x+=random(3)-1; y+=random(3)-1;
|
||||
\\ p=0 for BTPB1, BTPB2; p=5 for BTPB3
|
||||
if(!insm(Myx,x,y,p), x=random(sz)+1; y=random(sz)+1;);
|
||||
);\\wend
|
||||
Myx[y,x]=1;
|
||||
);\\fend i
|
||||
if(fn=="", plotmat(Myx), wrtmat(Myx, fn));
|
||||
}
|
||||
\\ Executing 1 or 2 lines below:
|
||||
|
||||
BrownianTree4(200,4000); \\BTPB1.png
|
||||
|
||||
{BrownianTree4(200,4000,"c:\\pariData\\BTPB1.dat");
|
||||
plotff("c:\\pariData\\BTPB1.dat");} \\BTPB1.png
|
||||
|
||||
BrownianTree4(200,4000,,2); \\BTPB2.png
|
||||
|
||||
{BrownianTree4(200,4000,"c:\\pariData\\BTPB2.dat",2);
|
||||
plotff("c:\\pariData\\BTPB2.dat");} \\BTPB2.png
|
||||
|
||||
BrownianTree4(200,4000,,2,5); \\BTPB3.png
|
||||
|
||||
{BrownianTree4(200,4000,"c:\\pariData\\BTPB3.dat",2,5);
|
||||
plotff("c:\\pariData\\BTPB3.dat");} \\BTPB3.png
|
||||
154
Task/Brownian-tree/Perl/brownian-tree.pl
Normal file
154
Task/Brownian-tree/Perl/brownian-tree.pl
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
use constant PI => 2*atan2(1,0); # π
|
||||
use constant STEP => 0.5; # How far particle moves each step. Affects both speed and accuracy greatly
|
||||
use constant STOP_RADIUS => 100; # When the tree reaches this far from center, end
|
||||
|
||||
# At each step, move this much towards center. Bigger numbers help the speed because
|
||||
# particles are less likely to wander off, but greatly affects tree shape.
|
||||
# Should be between 0 and 1 ish. Set to 0 for pain.
|
||||
use constant ATTRACT => 0.2;
|
||||
|
||||
my @particles = map([ map([], 0 .. 2 * STOP_RADIUS) ], 0 .. 2 * STOP_RADIUS);
|
||||
push @{ $particles[STOP_RADIUS][STOP_RADIUS] }, [0, 0];
|
||||
my($r_start, $max_dist) = (3, 0);
|
||||
|
||||
sub dist2 {
|
||||
no warnings 'uninitialized';
|
||||
my ($dx, $dy) = ($_[0][0] - $_[1][0], $_[0][1] - $_[1][1]);
|
||||
$dx * $dx + $dy * $dy
|
||||
}
|
||||
|
||||
sub move {
|
||||
my $p = shift;
|
||||
# moved too far, kill particle
|
||||
# return if dist2($p, [0, 0]) > 2 * $r_start * $r_start;
|
||||
$p->[0] += 2 * $r_start while $p->[0] < -$r_start;
|
||||
$p->[0] -= 2 * $r_start while $p->[0] > $r_start;
|
||||
$p->[1] += 2 * $r_start while $p->[1] < -$r_start;
|
||||
$p->[1] -= 2 * $r_start while $p->[1] > $r_start;
|
||||
|
||||
my ($ix, $iy) = (int($p->[0]), int($p->[1]));
|
||||
my $dist = 2 * $r_start * $r_start;
|
||||
my $nearest;
|
||||
|
||||
# see if the particle is close enough to stick to an exist one
|
||||
for ($ix - 1 .. $ix + 1) {
|
||||
my $idx = STOP_RADIUS + $_;
|
||||
next if $idx > 2 * STOP_RADIUS || $idx < 0;
|
||||
my $xs = $particles[ $idx ];
|
||||
for ($iy - 1 .. $iy + 1) {
|
||||
my $idx = STOP_RADIUS + $_;
|
||||
next if $idx > 2 * STOP_RADIUS || $idx < 0;
|
||||
for (@{ $xs->[ $idx ] }) {
|
||||
my $d = dist2($p, $_);
|
||||
next if $d > 2;
|
||||
next if $d > $dist;
|
||||
|
||||
$dist = $d;
|
||||
$nearest = $_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# yes, found one
|
||||
if ($nearest) {
|
||||
my $displace = [ $p->[0] - $nearest->[0],
|
||||
$p->[1] - $nearest->[1] ];
|
||||
my $angle = atan2($displace->[1], $displace->[0]);
|
||||
$p->[0] = $nearest->[0] + cos($angle);
|
||||
$p->[1] = $nearest->[1] + sin($angle);
|
||||
|
||||
push @{$particles[$ix + STOP_RADIUS][$iy + STOP_RADIUS]}, [ @$p ];
|
||||
$dist = sqrt dist2($p);
|
||||
|
||||
if ($dist + 10 > $r_start && $r_start < STOP_RADIUS + 10) {
|
||||
$r_start = $dist + 10
|
||||
}
|
||||
if (int($dist + 1) > $max_dist) {
|
||||
$max_dist = int($dist + 1);
|
||||
# write_eps();
|
||||
# system('pstopnm -portrait -xborder 0 -yborder 0 test.eps 2> /dev/null');
|
||||
# system('pnmtopng test.eps001.ppm 2>/dev/null > test.png');
|
||||
return 3 if $max_dist >= STOP_RADIUS;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
# random walk
|
||||
my $angle = rand(2 * PI);
|
||||
$p->[0] += STEP * cos($angle);
|
||||
$p->[1] += STEP * sin($angle);
|
||||
|
||||
# drag particle towards center by some distance
|
||||
my $nudge;
|
||||
if (sqrt(dist2($p, [0, 0])) > STOP_RADIUS + 1) {
|
||||
$nudge = 1;
|
||||
} else {
|
||||
$nudge = STEP * ATTRACT;
|
||||
}
|
||||
|
||||
if ($nudge) {
|
||||
$angle = atan2($p->[1], $p->[0]);
|
||||
$p->[0] -= $nudge * cos($angle);
|
||||
$p->[1] -= $nudge * sin($angle);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $count;
|
||||
PARTICLE: while () {
|
||||
my $a = rand(2 * PI);
|
||||
my $p = [ $r_start * cos($a), $r_start * sin($a) ];
|
||||
while (my $m = move $p) {
|
||||
if ($m == 1) { next }
|
||||
elsif ($m == 2) { $count++; last }
|
||||
elsif ($m == 3) { last PARTICLE }
|
||||
else { last }
|
||||
}
|
||||
print STDERR "$count $max_dist/@{[int($r_start)]}/@{[STOP_RADIUS]}\r" unless $count% 7;
|
||||
}
|
||||
|
||||
sub write_eps {
|
||||
my $size = 128;
|
||||
my $p = $size / (STOP_RADIUS * 1.05);
|
||||
my $b = STOP_RADIUS * $p;
|
||||
if ($p < 1) {
|
||||
$size = STOP_RADIUS * 1.05;
|
||||
$p = 1;
|
||||
$b = STOP_RADIUS;
|
||||
}
|
||||
my $hp = $p / 2;
|
||||
|
||||
open OUT, '>', 'test.eps';
|
||||
print OUT <<~"HEAD";
|
||||
%!PS-Adobe-3.0 EPSF-3.0
|
||||
%%BoundingBox: 0 0 @{[$size*2, $size*2]}
|
||||
$size $size translate
|
||||
/l{ rlineto }def
|
||||
/c{ $hp 0 360 arc fill }def
|
||||
-$size -$size moveto
|
||||
$size 2 mul 0 l
|
||||
0 $size 2 mul l
|
||||
-$size 2 mul 0 l
|
||||
closepath
|
||||
0 setgray fill
|
||||
0 setlinewidth .1 setgray 0 0 $b 0 360 arc stroke
|
||||
.8 setgray /TimesRoman findfont 16 scalefont setfont
|
||||
-$size 10 add $size -16 add moveto
|
||||
(Step = @{[STEP]} Attract = @{[ATTRACT]}) show
|
||||
0 1 0 setrgbcolor newpath
|
||||
HEAD
|
||||
|
||||
for (@particles) {
|
||||
for (@$_) {
|
||||
printf OUT "%.3g %.3g c ", map { $_ * $p } @$_ for @$_;
|
||||
}
|
||||
}
|
||||
print OUT "\n%%EOF";
|
||||
close OUT;
|
||||
}
|
||||
|
||||
write_eps();
|
||||
64
Task/Brownian-tree/Phix/brownian-tree.phix
Normal file
64
Task/Brownian-tree/Phix/brownian-tree.phix
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #000080;font-style:italic;">-- demo\rosetta\BrownianTree.exw</span>
|
||||
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
|
||||
|
||||
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">canvas</span>
|
||||
<span style="color: #004080;">cdCanvas</span> <span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">redraw_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*ih*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*posx*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000080;font-style:italic;">/*posy*/</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ox</span><span style="color: #0000FF;">,</span><span style="color: #000000;">oy</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">width</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">height</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetIntInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"DRAWSIZE"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">grid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">width</span><span style="color: #0000FF;">),</span><span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">xy</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">*</span><span style="color: #000000;">height</span><span style="color: #0000FF;">*</span><span style="color: #000000;">0.8</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000080;font-style:italic;">--atom t = time()+1</span>
|
||||
<span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)][</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">height</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #7060A8;">cdCanvasActivate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">cdCanvasClear</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">xy</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">width</span><span style="color: #0000FF;">)</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">height</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">ox</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span> <span style="color: #000000;">oy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">width</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">y</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">height</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">oy</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ox</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #7060A8;">cdCanvasPixel</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ox</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">oy</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">#00FF00</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">exit</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">ox</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">2</span>
|
||||
<span style="color: #000000;">oy</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span> <span style="color: #000000;">y</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">2</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #000080;font-style:italic;">-- -- if making the canvas bigger/resizeable,
|
||||
-- -- put this in so that you can kill it.
|
||||
-- if time()>=t then
|
||||
-- ?{i,xy}
|
||||
-- t = time()+1
|
||||
-- end if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #7060A8;">cdCanvasFlush</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">map_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">cdcanvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_IUP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ih</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">cddbuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">cdCreateCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">CD_DBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cdcanvas</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">cdCanvasSetBackground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_WHITE</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">cdCanvasSetForeground</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cddbuffer</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CD_RED</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span>
|
||||
|
||||
<span style="color: #000000;">canvas</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupCanvas</span><span style="color: #0000FF;">(</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RASTERSIZE"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"200x200"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- fixed size</span>
|
||||
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"MAP_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"map_cb"</span><span style="color: #0000FF;">))</span>
|
||||
|
||||
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"RESIZE=NO"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Brownian Tree"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">IupSetCallback</span><span style="color: #0000FF;">(</span><span style="color: #000000;">canvas</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"ACTION"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"redraw_cb"</span><span style="color: #0000FF;">))</span>
|
||||
|
||||
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<!--
|
||||
19
Task/Brownian-tree/PicoLisp/brownian-tree.l
Normal file
19
Task/Brownian-tree/PicoLisp/brownian-tree.l
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
(load "@lib/simul.l")
|
||||
|
||||
(de brownianTree (File Size Cnt)
|
||||
(let Img (grid Size Size)
|
||||
(put Img (/ Size 2) (/ Size 2) 'pix T)
|
||||
(use (P Q)
|
||||
(do Cnt
|
||||
(setq P (get Img (rand 1 Size) (rand 1 Size)))
|
||||
(loop
|
||||
(setq Q ((if2 (rand T) (rand T) north east south west) P))
|
||||
(T (; Q pix) (put P 'pix T))
|
||||
(setq P (or Q (get Img (rand 1 Size) (rand 1 Size)))) ) ) )
|
||||
(out "img.pbm"
|
||||
(prinl "P1")
|
||||
(prinl Size " " Size)
|
||||
(for L Img
|
||||
(for This L
|
||||
(prin (if (: pix) 1 0)) )
|
||||
(prinl) ) ) ) )
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
SIDESTICK = False
|
||||
|
||||
def setup() :
|
||||
global is_taken
|
||||
size(512, 512)
|
||||
background(0)
|
||||
is_taken = [[False] * height for _ in range(width)]
|
||||
is_taken[width/2][height/2] = True
|
||||
|
||||
|
||||
def draw() :
|
||||
x = floor(random(width))
|
||||
y = floor(random(height))
|
||||
if is_taken[x][y]:
|
||||
return
|
||||
while True:
|
||||
xp = x + floor(random(-1, 2))
|
||||
yp = y + floor(random(-1, 2))
|
||||
is_contained = 0 <= xp < width and 0 <= yp < height
|
||||
if is_contained and not is_taken[xp][yp]:
|
||||
x = xp
|
||||
y = yp
|
||||
continue
|
||||
else:
|
||||
if SIDESTICK or (is_contained and is_taken[xp][yp]):
|
||||
is_taken[x][y] = True
|
||||
set(x, y, color(255))
|
||||
break
|
||||
|
||||
if frameCount > width * height:
|
||||
noLoop()
|
||||
39
Task/Brownian-tree/Processing/brownian-tree.processing
Normal file
39
Task/Brownian-tree/Processing/brownian-tree.processing
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
boolean SIDESTICK = false;
|
||||
boolean[][] isTaken;
|
||||
|
||||
void setup() {
|
||||
size(512, 512);
|
||||
background(0);
|
||||
isTaken = new boolean[width][height];
|
||||
isTaken[width/2][height/2] = true;
|
||||
}
|
||||
|
||||
void draw() {
|
||||
int x = floor(random(width));
|
||||
int y = floor(random(height));
|
||||
if (isTaken[x][y]) {
|
||||
return;
|
||||
}
|
||||
while (true) {
|
||||
int xp = x + floor(random(-1, 2));
|
||||
int yp = y + floor(random(-1, 2));
|
||||
boolean iscontained = (
|
||||
0 <= xp && xp < width &&
|
||||
0 <= yp && yp < height
|
||||
);
|
||||
if (iscontained && !isTaken[xp][yp]) {
|
||||
x = xp;
|
||||
y = yp;
|
||||
continue;
|
||||
} else {
|
||||
if (SIDESTICK || (iscontained && isTaken[xp][yp])) {
|
||||
isTaken[x][y] = true;
|
||||
set(x, y, #FFFFFF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (frameCount > width * height) {
|
||||
noLoop();
|
||||
}
|
||||
}
|
||||
39
Task/Brownian-tree/PureBasic/brownian-tree.basic
Normal file
39
Task/Brownian-tree/PureBasic/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#Window1 = 0
|
||||
#Image1 = 0
|
||||
#ImgGadget = 0
|
||||
|
||||
#NUM_PARTICLES = 3000
|
||||
#width = 200
|
||||
#height = 200
|
||||
#xmax = #width -3
|
||||
#ymax = #height -3
|
||||
Define.i Event ,i ,x,y
|
||||
|
||||
If OpenWindow(#Window1, 0, 0, #width, #height, "Brownian Tree PureBasic Example", #PB_Window_SystemMenu )
|
||||
If CreateImage(#Image1, #width, #height)
|
||||
ImageGadget(#ImgGadget, 0, 0, #width, #height, ImageID(#Image1))
|
||||
StartDrawing(ImageOutput(#Image1))
|
||||
FrontColor($FFFFFF)
|
||||
Plot( Random(#xmax) , Random(#ymax ))
|
||||
StopDrawing()
|
||||
SetGadgetState(#ImgGadget, ImageID(#Image1))
|
||||
For i = 1 To #NUM_PARTICLES
|
||||
x = Random(#xmax)+1 : y = Random (#ymax)+1
|
||||
StartDrawing(ImageOutput(#Image1))
|
||||
While Point(x+1, y+1) + Point(x, y+1)+Point(x+1, y)+Point(x-1, y-1)+Point(x-1, y)+Point(x, y-1) = 0
|
||||
x = x + (Random(2)-1) : y = y + (Random(2)-1)
|
||||
If x < 1 Or x > #xmax Or y < 1 Or y > #ymax
|
||||
x = Random(#xmax)+1 : y = Random (#ymax)+1
|
||||
EndIf
|
||||
Wend
|
||||
Plot(x,y)
|
||||
StopDrawing()
|
||||
SetGadgetState(#ImgGadget, ImageID(#Image1))
|
||||
Next
|
||||
|
||||
EndIf
|
||||
|
||||
Repeat
|
||||
Event = WaitWindowEvent()
|
||||
Until Event = #PB_Event_CloseWindow
|
||||
EndIf
|
||||
101
Task/Brownian-tree/Python/brownian-tree.py
Normal file
101
Task/Brownian-tree/Python/brownian-tree.py
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
import pygame, sys, os
|
||||
from pygame.locals import *
|
||||
from random import randint
|
||||
pygame.init()
|
||||
|
||||
MAXSPEED = 15
|
||||
SIZE = 3
|
||||
COLOR = (45, 90, 45)
|
||||
WINDOWSIZE = 400
|
||||
TIMETICK = 1
|
||||
MAXPART = 50
|
||||
|
||||
freeParticles = pygame.sprite.Group()
|
||||
tree = pygame.sprite.Group()
|
||||
|
||||
window = pygame.display.set_mode((WINDOWSIZE, WINDOWSIZE))
|
||||
pygame.display.set_caption("Brownian Tree")
|
||||
|
||||
screen = pygame.display.get_surface()
|
||||
|
||||
|
||||
class Particle(pygame.sprite.Sprite):
|
||||
def __init__(self, vector, location, surface):
|
||||
pygame.sprite.Sprite.__init__(self)
|
||||
self.vector = vector
|
||||
self.surface = surface
|
||||
self.accelerate(vector)
|
||||
self.add(freeParticles)
|
||||
self.rect = pygame.Rect(location[0], location[1], SIZE, SIZE)
|
||||
self.surface.fill(COLOR, self.rect)
|
||||
|
||||
def onEdge(self):
|
||||
if self.rect.left <= 0:
|
||||
self.vector = (abs(self.vector[0]), self.vector[1])
|
||||
elif self.rect.top <= 0:
|
||||
self.vector = (self.vector[0], abs(self.vector[1]))
|
||||
elif self.rect.right >= WINDOWSIZE:
|
||||
self.vector = (-abs(self.vector[0]), self.vector[1])
|
||||
elif self.rect.bottom >= WINDOWSIZE:
|
||||
self.vector = (self.vector[0], -abs(self.vector[1]))
|
||||
|
||||
def update(self):
|
||||
if freeParticles in self.groups():
|
||||
self.surface.fill((0,0,0), self.rect)
|
||||
self.remove(freeParticles)
|
||||
if pygame.sprite.spritecollideany(self, freeParticles):
|
||||
self.accelerate((randint(-MAXSPEED, MAXSPEED),
|
||||
randint(-MAXSPEED, MAXSPEED)))
|
||||
self.add(freeParticles)
|
||||
elif pygame.sprite.spritecollideany(self, tree):
|
||||
self.stop()
|
||||
else:
|
||||
self.add(freeParticles)
|
||||
|
||||
self.onEdge()
|
||||
|
||||
if (self.vector == (0,0)) and tree not in self.groups():
|
||||
self.accelerate((randint(-MAXSPEED, MAXSPEED),
|
||||
randint(-MAXSPEED, MAXSPEED)))
|
||||
self.rect.move_ip(self.vector[0], self.vector[1])
|
||||
self.surface.fill(COLOR, self.rect)
|
||||
|
||||
def stop(self):
|
||||
self.vector = (0,0)
|
||||
self.remove(freeParticles)
|
||||
self.add(tree)
|
||||
|
||||
def accelerate(self, vector):
|
||||
self.vector = vector
|
||||
|
||||
NEW = USEREVENT + 1
|
||||
TICK = USEREVENT + 2
|
||||
|
||||
pygame.time.set_timer(NEW, 50)
|
||||
pygame.time.set_timer(TICK, TIMETICK)
|
||||
|
||||
|
||||
def input(events):
|
||||
for event in events:
|
||||
if event.type == QUIT:
|
||||
sys.exit(0)
|
||||
elif event.type == NEW and (len(freeParticles) < MAXPART):
|
||||
Particle((randint(-MAXSPEED,MAXSPEED),
|
||||
randint(-MAXSPEED,MAXSPEED)),
|
||||
(randint(0, WINDOWSIZE), randint(0, WINDOWSIZE)),
|
||||
screen)
|
||||
elif event.type == TICK:
|
||||
freeParticles.update()
|
||||
|
||||
|
||||
half = WINDOWSIZE/2
|
||||
tenth = WINDOWSIZE/10
|
||||
|
||||
root = Particle((0,0),
|
||||
(randint(half-tenth, half+tenth),
|
||||
randint(half-tenth, half+tenth)), screen)
|
||||
root.stop()
|
||||
|
||||
while True:
|
||||
input(pygame.event.get())
|
||||
pygame.display.flip()
|
||||
39
Task/Brownian-tree/R/brownian-tree-1.r
Normal file
39
Task/Brownian-tree/R/brownian-tree-1.r
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# plotmat(): Simple plotting using a square matrix mat (filled with 0/1). v. 8/31/16
|
||||
# Where: mat - matrix; fn - file name; clr - color; ttl - plot title;
|
||||
# dflg - writing dump file flag (0-no/1-yes): psz - picture size.
|
||||
plotmat <- function(mat, fn, clr, ttl, dflg=0, psz=600) {
|
||||
m <- nrow(mat); d <- 0;
|
||||
X=NULL; Y=NULL;
|
||||
pf = paste0(fn, ".png"); df = paste0(fn, ".dmp");
|
||||
for (i in 1:m) {
|
||||
for (j in 1:m) {if(mat[i,j]==0){next} else {d=d+1; X[d] <- i; Y[d] <- j;} }
|
||||
};
|
||||
cat(" *** Matrix(", m,"x",m,")", d, "DOTS\n");
|
||||
# Dumping if requested (dflg=1).
|
||||
if (dflg==1) {dump(c("X","Y"), df); cat(" *** Dump file:", df, "\n")};
|
||||
# Plotting
|
||||
plot(X,Y, main=ttl, axes=FALSE, xlab="", ylab="", col=clr, pch=20);
|
||||
dev.copy(png, filename=pf, width=psz, height=psz);
|
||||
# Cleaning
|
||||
dev.off(); graphics.off();
|
||||
}
|
||||
|
||||
# plotv2(): Simple plotting using 2 vectors (dumped into ".dmp" file by plotmat()).
|
||||
# Where: fn - file name; clr - color; ttl - plot title; psz - picture size.
|
||||
# v. 8/31/16
|
||||
plotv2 <- function(fn, clr, ttl, psz=600) {
|
||||
cat(" *** START:", date(), "clr=", clr, "psz=", psz, "\n");
|
||||
cat(" *** File name -", fn, "\n");
|
||||
pf = paste0(fn, ".png"); df = paste0(fn, ".dmp");
|
||||
source(df);
|
||||
d <- length(X);
|
||||
cat(" *** Source dump-file:", df, d, "DOTS\n");
|
||||
cat(" *** Plot file -", pf, "\n");
|
||||
# Plotting
|
||||
plot(X, Y, main=ttl, axes=FALSE, xlab="", ylab="", col=clr, pch=20);
|
||||
# Writing png-file
|
||||
dev.copy(png, filename=pf, width=psz, height=psz);
|
||||
# Cleaning
|
||||
dev.off(); graphics.off();
|
||||
cat(" *** END:", date(), "\n");
|
||||
}
|
||||
33
Task/Brownian-tree/R/brownian-tree-2.r
Normal file
33
Task/Brownian-tree/R/brownian-tree-2.r
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Generate and plot Brownian tree. Version #1.
|
||||
# 7/27/16 aev
|
||||
# gpBrownianTree1(m, n, clr, fn, ttl, dflg, psz)
|
||||
# Where: m - defines matrix m x m; n - limit of the number of moves;
|
||||
# fn - file name (.ext will be added); ttl - plot title; dflg - 0-no dump,
|
||||
# 1-dump: psz - picture size.
|
||||
gpBrownianTree1 <- function(m, n, clr, fn, ttl, dflg=0, psz=600)
|
||||
{
|
||||
cat(" *** START:", date(), "m=",m, "n=",n, "clr=",clr, "psz=", psz, "\n");
|
||||
M <- matrix(c(0), ncol=m, nrow=m, byrow=TRUE);
|
||||
# Seed in center
|
||||
x <- m%/%2; y <- m%/%2;
|
||||
M[x,y]=1;
|
||||
pf=paste0(fn, ".png");
|
||||
cat(" *** Plot file -", pf, "\n");
|
||||
# Main loops
|
||||
for (i in 1:n) {
|
||||
if(i>1) {
|
||||
x <- sample(1:m, 1, replace=FALSE)
|
||||
y <- sample(1:m, 1, replace=FALSE)}
|
||||
while(1) {
|
||||
ox = x; oy = y;
|
||||
x <- x + sample(-1:1, 1, replace=FALSE);
|
||||
y <- y + sample(-1:1, 1, replace=FALSE);
|
||||
if(x<=m && y<=m && x>0 && y>0 && M[x,y])
|
||||
{if(ox<=m && oy<=m && ox>0 && oy>0) {M[ox,oy]=1; break}}
|
||||
if(!(x<=m && y<=m && x>0 && y>0)) {break}
|
||||
}
|
||||
}
|
||||
plotmat(M, fn, clr, ttl, dflg, psz);
|
||||
cat(" *** END:",date(),"\n");
|
||||
}
|
||||
gpBrownianTree1(400,15000,"red", "BT1R", "Brownian Tree v.1", 1);
|
||||
37
Task/Brownian-tree/R/brownian-tree-3.r
Normal file
37
Task/Brownian-tree/R/brownian-tree-3.r
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Generate and plot Brownian tree. Version #2.
|
||||
# 7/27/16 aev
|
||||
# gpBrownianTree2(m, n, clr, fn, ttl, dflg, psz)
|
||||
# Where: m - defines matrix m x m; n - limit of the number of moves;
|
||||
# fn - file name (.ext will be added); ttl - plot title; dflg - 0-no dump,
|
||||
# 1-dump; psz - picture size.
|
||||
gpBrownianTree2 <- function(m, n, clr, fn, ttl, dflg=0, psz=600)
|
||||
{
|
||||
cat(" *** START:", date(), "m=",m, "n=",n, "clr=",clr, "psz=", psz, "\n");
|
||||
M <- matrix(c(0), ncol=m, nrow=m, byrow=TRUE);
|
||||
# Random seed always
|
||||
x <- sample(1:m, 1, replace=FALSE); y <- sample(1:m, 1, replace=FALSE);
|
||||
M[x,y]=1;
|
||||
pf=paste0(fn,".png");
|
||||
cat(" *** Plot file -",pf,"Seed:",x,"/",y,"\n");
|
||||
# Main loops
|
||||
for (i in 1:n) {
|
||||
if(i>1) {
|
||||
x <- sample(1:m, 1, replace=FALSE)
|
||||
y <- sample(1:m, 1, replace=FALSE)}
|
||||
while(1) {
|
||||
dx <- sample(-1:1, 1, replace=FALSE);
|
||||
dy <- sample(-1:1, 1, replace=FALSE);
|
||||
nx=x+dx; ny=y+dy;
|
||||
if(!(nx<=m && ny<=m && nx>0 && ny>0)) {
|
||||
x <- sample(1:m, 1, replace=FALSE); y <- sample(1:m, 1, replace=FALSE)}
|
||||
else {if(M[nx,ny]) {M[x,y]=1; break}
|
||||
else{x=nx; y=ny;}}
|
||||
}
|
||||
}
|
||||
plotmat(M, fn, clr, ttl, dflg, psz);
|
||||
cat(" *** END:",date(),"\n");
|
||||
}
|
||||
gpBrownianTree2(400,5000,"brown", "BT2R", "Brownian Tree v.2", 1);
|
||||
|
||||
## Rename BT2R.dmp to BT2aR.dmp
|
||||
plotv2("BT2aR", "orange", "Brownian Tree v.2a", 640)
|
||||
39
Task/Brownian-tree/R/brownian-tree-4.r
Normal file
39
Task/Brownian-tree/R/brownian-tree-4.r
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Generate and plot Brownian tree. Version #3.
|
||||
# 7/27/16 aev
|
||||
# gpBrownianTree3(m, n, clr, fn, ttl, dflg, seed, psz):
|
||||
# Where: m - defines matrix m x m; n - limit of the number of moves;
|
||||
# fn - file name (.ext will be added); ttl - plot title; dflg - 0-no dump,
|
||||
# 1-dump; seed - 0-center, 1-random: psz - picture size.
|
||||
gpBrownianTree3 <- function(m, n, clr, fn, ttl, dflg=0, seed=0, psz=600)
|
||||
{
|
||||
cat(" *** START:", date(),"m=",m,"n=",n,"clr=",clr, "psz=",psz, "\n");
|
||||
M <- matrix(c(0), ncol=m, nrow=m, byrow=TRUE);
|
||||
# Random seed
|
||||
if(seed==1)
|
||||
{x <- sample(1:m, 1, replace=FALSE);y <- sample(1:m, 1, replace=FALSE)}
|
||||
# Seed in center
|
||||
else {x <- m%/%2; y <- m%/%2}
|
||||
M[x,y]=1;
|
||||
pf=paste0(fn,". png");
|
||||
cat(" *** Plot file -", pf, "Seed:",x,"/",y, "\n");
|
||||
# Main loops
|
||||
for (i in 1:n) {
|
||||
if(i>1) {
|
||||
x <- sample(1:m, 1, replace=FALSE)
|
||||
y <- sample(1:m, 1, replace=FALSE)}
|
||||
b <- 0;
|
||||
while(b==0) {
|
||||
dx <- sample(-1:1, 1, replace=FALSE)
|
||||
dy <- sample(-1:1, 1, replace=FALSE)
|
||||
if(!(x+dx<=m && y+dy<=m && x+dx>0 && y+dy>0))
|
||||
{ x <- sample(1:m, 1, replace=FALSE)
|
||||
y <- sample(1:m, 1, replace=FALSE)
|
||||
}
|
||||
else{if(M[x+dx,y+dy]==1) {M[x,y]=1; b=1}
|
||||
else {x=x+dx; y=y+dy;} }
|
||||
}
|
||||
}
|
||||
plotmat(M, fn, clr, ttl, dflg, psz);
|
||||
cat(" *** END:", date(), "\n");
|
||||
}
|
||||
gpBrownianTree3(400,5000,"dark green", "BT3R", "Brownian Tree v.3", 1);
|
||||
41
Task/Brownian-tree/R/brownian-tree-5.r
Normal file
41
Task/Brownian-tree/R/brownian-tree-5.r
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Generate and plot Brownian tree. Version #4.
|
||||
# 7/27/16 aev
|
||||
# gpBrownianTree4(m, n, clr, fn, ttl, dflg, seed, psz)
|
||||
# Where: m - defines matrix m x m; n - limit of the number of moves;
|
||||
# fn - file name (.ext will be added); ttl - plot title; dflg - 0-no dump,
|
||||
# 1-dump; seed - 0-center, 1-random: psz - picture size.
|
||||
gpBrownianTree4 <- function(m, n, clr, fn, ttl, dflg=0, seed=0, psz=600)
|
||||
{
|
||||
cat(" *** START:", date(), "m=",m, "n=",n, "clr=",clr, "psz=",psz, "\n");
|
||||
M <- matrix(c(0), ncol=m, nrow=m, byrow=TRUE);
|
||||
# Random seed
|
||||
if(seed==1)
|
||||
{x <- sample(1:m, 1, replace=FALSE);y <- sample(1:m, 1, replace=FALSE)}
|
||||
# Seed in center
|
||||
else {x <- m%/%2; y <- m%/%2}
|
||||
M[x,y]=1;
|
||||
pf=paste0(fn,".png");
|
||||
cat(" *** Plot file -",pf,"Seed:",x,"/",y,"\n");
|
||||
# Main loops
|
||||
for (i in 1:n) {
|
||||
if(i>1) {
|
||||
x <- sample(1:m, 1, replace=FALSE)
|
||||
y <- sample(1:m, 1, replace=FALSE)}
|
||||
while((x<=m && y<=m && x>0 && y>0)) {
|
||||
if(!(x+1<=m && y+1<=m && x-1>0 && y-1>0)) {break;}
|
||||
b=M[x+1,y+1]+M[x,y+1]+M[x-1,y+1]+M[x+1,y];
|
||||
b=b+M[x-1,y-1]+M[x-1,y]+M[x,y-1]+M[x+1,y-1];
|
||||
if(b!=0) {break;}
|
||||
x <- x + sample(-1:1, 1, replace=FALSE)
|
||||
y <- y + sample(-1:1, 1, replace=FALSE)
|
||||
if(!(x<=m && y<=m && x>0 && y>0))
|
||||
{ x <- sample(1:m, 1, replace=FALSE)
|
||||
y <- sample(1:m, 1, replace=FALSE)
|
||||
}
|
||||
}
|
||||
M[x,y]=1;
|
||||
}
|
||||
plotmat(M, fn, clr, ttl, dflg, psz);
|
||||
cat(" *** END:",date(),"\n");
|
||||
}
|
||||
gpBrownianTree4(400,15000,"navy", "BT4R", "Brownian Tree v.4", 1);
|
||||
78
Task/Brownian-tree/REXX/brownian-tree.rexx
Normal file
78
Task/Brownian-tree/REXX/brownian-tree.rexx
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*REXX program animates and displays Brownian motion of dust in a field (with one seed).*/
|
||||
mote = '·' /*character for a loose mote (of dust).*/
|
||||
hole = ' ' /* " " an empty spot in field.*/
|
||||
seedPos = 0 /*if =0, then use middle of the field.*/
|
||||
/* " -1, " " a random placement.*/
|
||||
/*otherwise, place the seed at seedPos.*/
|
||||
/*use RANDSEED for RANDOM repeatability*/
|
||||
parse arg sd sw motes tree randSeed . /*obtain optional arguments from the CL*/
|
||||
if sd=='' | sd=="," then sd= 0 /*Not specified? Then use the default.*/
|
||||
if sw=='' | sw=="," then sw= 0 /* " " " " " " */
|
||||
if motes=='' | motes=="," then motes= '18%' /*The % dust motes in the field, */
|
||||
/* [↑] either a # ─or─ a # with a %.*/
|
||||
if tree=='' | tree==mote then tree= "*" /*the character used to show the tree. */
|
||||
if length(tree)==2 then tree=x2c(tree) /*tree character was specified in hex. */
|
||||
if datatype(randSeed,'W') then call random ,,randSeed /*if an integer, use the seed.*/
|
||||
/* [↑] set the first random number. */
|
||||
if sd==0 | sw==0 then _= scrsize() /*Note: not all REXXes have SCRSIZE BIF*/
|
||||
if sd==0 then sd= word(_, 1) - 2 /*adjust usable depth for the border.*/
|
||||
if sw==0 then sw= word(_, 2) - 1 /* " " width " " " */
|
||||
seedAt= seedPos /*assume a seed position (initial pos).*/
|
||||
if seedPos== 0 then seedAt= (sw % 2) (sd % 2) /*if it's a zero, start in the middle.*/
|
||||
if seedPos==-1 then seedAt= random(1, sw) random(1,sd) /*if negative, use random.*/
|
||||
parse var seedAt xs ys . /*obtain the X and Y seed coördinates*/
|
||||
/* [↓] if right─most ≡ '%', then use %*/
|
||||
if right(motes, 1)=='%' then motes= sd * sw * strip(motes, , '%') % 100
|
||||
@.= hole /*create the Brownian field, all empty.*/
|
||||
do j=1 for motes /*sprinkle a # of dust motes randomly.*/
|
||||
rx= random(1, sw); ry= random(1, sd); @.rx.ry= mote
|
||||
end /*j*/ /* [↑] place a mote at random in field*/
|
||||
/*plant a seed from which the tree will grow from*/
|
||||
@.xs.ys= tree /*dust motes that affix themselves to the tree. */
|
||||
call show; loX= 1; hiX= sw /*show field before we mess it up again*/
|
||||
loY= 1; hiY= sd /*used to optimize the mote searching.*/
|
||||
/*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ soooo, this is Brownian motion.*/
|
||||
do Brownian=1 until \motion; call show /*show Brownion motion until no motion.*/
|
||||
minx= loX; maxX= hiX; loX= sw; hiX= 1 /*as the tree grows, the search for the*/
|
||||
minY= loY; maxY= hiY; loY= sd; hiy= 1 /*dust motes gets faster due to croping*/
|
||||
call BM /*invoke the Brownian movement routine.*/
|
||||
if loX>1 & hiX<sw & loY>1 & hiY<sd then iterate /*Need cropping? No, then keep moving*/
|
||||
call crop /*delete motes (moved off petri field).*/
|
||||
end /*Brownian*/ /*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
|
||||
exit 0 /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
crop: do yc=-1 to sd+1 by sd+2; do xc=-1 to sw+1; @.xc.yc= hole; end /*xc*/
|
||||
end /*yc*/
|
||||
do xc=-1 to sw+1 by sw+2; do yc=-1 to sd+1; @.xc.yc= hole; end /*yc*/
|
||||
end /*xc*/; return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
show: 'CLS'; motion= 0; do ys=sd for sd by -1; aRow=
|
||||
do xs=1 for sw; aRow= aRow || @.xs.ys
|
||||
end /*xs*/
|
||||
say aRow
|
||||
end /*ys*/; return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
BM: do x =minX to maxX; xm= x - 1; xp= x + 1 /*two handy─dandy values. */
|
||||
do y=minY to maxY; if @.x.y\==mote then iterate /*Not a mote: keep looking.*/
|
||||
if x<loX then loX=x; if x>hiX then hiX= x /*faster than hiX=max(X,hiX)*/
|
||||
if y<loY then loY=y; if y>hiY then hiY= y /* " " hiY=max(y,hiY)*/
|
||||
if @.xm.y ==tree then do; @.x.y= tree; iterate; end /*there a neighbor of tree? */
|
||||
if @.xp.y ==tree then do; @.x.y= tree; iterate; end /* " " " " " */
|
||||
ym= y - 1
|
||||
if @.x.ym ==tree then do; @.x.y= tree; iterate; end /* " " " " " */
|
||||
if @.xm.ym==tree then do; @.x.y= tree; iterate; end /* " " " " " */
|
||||
if @.xp.ym==tree then do; @.x.y= tree; iterate; end /* " " " " " */
|
||||
yp = y + 1
|
||||
if @.x.yp ==tree then do; @.x.y= tree; iterate; end /* " " " " " */
|
||||
if @.xm.yp==tree then do; @.x.y= tree; iterate; end /* " " " " " */
|
||||
if @.xp.yp==tree then do; @.x.y= tree; iterate; end /* " " " " " */
|
||||
motion= 1 /* [↓] Brownian motion is coming. */
|
||||
xb= x + random(1, 3) - 2 /* apply Brownian motion for X. */
|
||||
yb= y + random(1, 3) - 2 /* " " " " Y. */
|
||||
if @.xb.yb\==hole then iterate /*can the mote actually move to there ?*/
|
||||
@.x.y= hole /*"empty out" the old mote position. */
|
||||
@.xb.yb= mote /*move the mote (or possibly not). */
|
||||
if xb<loX then loX= max(1, xb); if xb>hiX then hiX= min(sw, xb)
|
||||
if yb<loY then loY= max(1, yb); if yb>hiY then hiY= min(sd, yb)
|
||||
end /*y*/ /* [↑] limit mote's movement to field.*/
|
||||
end /*x*/; return
|
||||
124
Task/Brownian-tree/Racket/brownian-tree.rkt
Normal file
124
Task/Brownian-tree/Racket/brownian-tree.rkt
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
#lang racket
|
||||
(require 2htdp/image)
|
||||
|
||||
;; The unsafe fixnum ops are faster than the checked ones,
|
||||
;; but if you get anything wrong with them, they'll bite.
|
||||
;; If you experience any problems reactivate the
|
||||
;; (require racket/fixnum) and instead of the unsafe requirement
|
||||
;; below...
|
||||
|
||||
;; we have tested this...
|
||||
#;(require racket/fixnum)
|
||||
;; so we can use this...
|
||||
(require racket/require
|
||||
(only-in racket/fixnum make-fxvector in-fxvector)
|
||||
(filtered-in
|
||||
(? (name) (regexp-replace #rx"unsafe-" name ""))
|
||||
racket/unsafe/ops))
|
||||
|
||||
;;; This implementation uses a 1d, mutable, fixnum vector
|
||||
;;; there's a lot of work done making the tree, so this optimisation
|
||||
;;; at the expense of clarity has been made. Sorry, guys!
|
||||
(define (brownian-tree w h collisions n-particles seed-tree
|
||||
generate-particle walk-particle)
|
||||
(define w*h (fx* w h))
|
||||
(define V (make-fxvector w*h))
|
||||
(define (collision? x.y) (fx> (fxvector-ref V x.y) 0))
|
||||
|
||||
;; The main loop
|
||||
(define (inner-b-t collisions particles)
|
||||
(cond
|
||||
[(fx= 0 collisions) V]
|
||||
[else
|
||||
(define-values (new-particles new-collisions)
|
||||
(for/fold
|
||||
((prtcls null)
|
||||
(clsns 0))
|
||||
((x.y particles)
|
||||
#:break (fx= collisions clsns))
|
||||
(define new-particle (walk-particle x.y w h w*h))
|
||||
(cond
|
||||
[(not new-particle) ; it died!
|
||||
(values (cons (generate-particle V w h w*h) prtcls) clsns)]
|
||||
[(collision? new-particle)
|
||||
(fxvector-set! V x.y 1)
|
||||
(values (cons (generate-particle V w h w*h) prtcls) (add1 clsns))]
|
||||
[else
|
||||
(values (cons new-particle prtcls) clsns)])))
|
||||
(when (fx> new-collisions 0)
|
||||
(define remain (fx- collisions new-collisions))
|
||||
(unless (fx= (exact-floor (* 10 (log collisions)))
|
||||
(exact-floor (* 10 (log (fxmax 1 remain)))))
|
||||
(eprintf "~a (e^~a)~%" remain (log (fxmax 1 remain))))
|
||||
(log-info "~a new collisions: ~a remain~%" new-collisions remain))
|
||||
(inner-b-t (fxmax 0 (fx- collisions new-collisions)) new-particles)]))
|
||||
|
||||
;; Seed the tree
|
||||
(seed-tree V w h)
|
||||
(inner-b-t collisions
|
||||
(build-list n-particles
|
||||
(lambda (x) (generate-particle V w h w*h)))))
|
||||
|
||||
;; See below for why we do the (fxremainder ...) test
|
||||
(define (uniform-particle-generator v w h w*h)
|
||||
(define x.y (random w*h))
|
||||
(define valid-x.y?
|
||||
(and
|
||||
(fx= (fxvector-ref v x.y) 0) ; start on empty cell
|
||||
(fx> (fxremainder x.y w) 0))) ; not on left edge
|
||||
; if it's valid take it otherwise regenerate
|
||||
(if valid-x.y? x.y (uniform-particle-generator v w h w*h)))
|
||||
|
||||
;; The boundaries to the walker are to remain within the limits of
|
||||
;; the vector... however, unless we stop particles going off the
|
||||
;; east/west edges, the tree will be formed on a cylinder as the
|
||||
;; particles wrap. So we kill particles that reach the left edge
|
||||
;; either by decrement from the right or by incrementing and wrapping.
|
||||
;; This is is tested with (= 0 (remainder x.y w)).
|
||||
(define (brownian-particle-walker x.y w h w*h)
|
||||
(define dx (fx- (random 3) 1))
|
||||
(define dy (fx- (random 3) 1))
|
||||
(define new-x.y (fx+ x.y (fx+ dx (fx* w dy))))
|
||||
(and (fx> new-x.y 0) (fx< new-x.y w*h)
|
||||
(fx> (fxremainder new-x.y w) 0)
|
||||
new-x.y))
|
||||
|
||||
;; These seed functions modify v however you want!
|
||||
(define (seed-middle v w h)
|
||||
(fxvector-set! v (+ (quotient w 2) (* w (quotient h 2))) 1))
|
||||
|
||||
(define (seed-circle v w h)
|
||||
(for ((a (in-range 0 360 120)))
|
||||
(define x (exact-floor (* w 1/8 (+ 4 (sin (* pi 1/180 a))))))
|
||||
(define y (exact-floor (* h 1/8 (+ 4 (cos (* pi 1/180 a))))))
|
||||
(fxvector-set! v (+ x (* w y)) 1)))
|
||||
|
||||
;; SCALE is a general purpose knob for modifying the size of the problem
|
||||
;; complexity increases with the sqaure of SCALE (at least)
|
||||
(define SCALE 1)
|
||||
(define tree-W (* SCALE 320))
|
||||
(define tree-H (* SCALE 240))
|
||||
(define tree-W.H (* tree-W tree-H))
|
||||
;; play with tree-PARTICLES -- small values will lead to a smaller tree
|
||||
;; as the tree moves towards the edges, more particles might affect its shape
|
||||
(define tree-PARTICLES (quotient tree-W.H 4))
|
||||
;; these are the particles that are bimbling around at any one time. If it's
|
||||
;; too low, you might get bored waiting for a collision... if it's too high
|
||||
;; you might get inappropriate collisions
|
||||
(define working-PARTICLES (quotient tree-W.H 300))
|
||||
|
||||
(define b-t (time
|
||||
(brownian-tree
|
||||
tree-W tree-H tree-PARTICLES working-PARTICLES
|
||||
seed-middle
|
||||
uniform-particle-generator
|
||||
brownian-particle-walker)))
|
||||
|
||||
(define (b-t-value->color c) (case c ((1) "black") (else "white")))
|
||||
(define img (color-list->bitmap
|
||||
(for*/list ((x (in-fxvector b-t)))
|
||||
(b-t-value->color x))
|
||||
tree-W tree-H))
|
||||
|
||||
img
|
||||
(save-image img "brownian-tree.png")
|
||||
67
Task/Brownian-tree/Raku/brownian-tree.raku
Normal file
67
Task/Brownian-tree/Raku/brownian-tree.raku
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
constant size = 100;
|
||||
constant particlenum = 1_000;
|
||||
|
||||
|
||||
constant mid = size div 2;
|
||||
|
||||
my $spawnradius = 5;
|
||||
my @map;
|
||||
|
||||
sub set($x, $y) {
|
||||
@map[$x][$y] = True;
|
||||
}
|
||||
|
||||
sub get($x, $y) {
|
||||
return @map[$x][$y] || False;
|
||||
}
|
||||
|
||||
set(mid, mid);
|
||||
my @blocks = " ","\c[UPPER HALF BLOCK]", "\c[LOWER HALF BLOCK]","\c[FULL BLOCK]";
|
||||
|
||||
sub infix:<█>($a, $b) {
|
||||
@blocks[$a + 2 * $b]
|
||||
}
|
||||
|
||||
sub display {
|
||||
my $start = 0;
|
||||
my $end = size;
|
||||
say (for $start, $start + 2 ... $end -> $y {
|
||||
(for $start..$end -> $x {
|
||||
if abs(($x&$y) - mid) < $spawnradius {
|
||||
get($x, $y) █ get($x, $y+1);
|
||||
} else {
|
||||
" "
|
||||
}
|
||||
}).join
|
||||
}).join("\n")
|
||||
}
|
||||
|
||||
for ^particlenum -> $progress {
|
||||
my Int $x;
|
||||
my Int $y;
|
||||
my &reset = {
|
||||
repeat {
|
||||
($x, $y) = (mid - $spawnradius..mid + $spawnradius).pick, (mid - $spawnradius, mid + $spawnradius).pick;
|
||||
($x, $y) = ($y, $x) if (True, False).pick();
|
||||
} while get($x,$y);
|
||||
}
|
||||
reset;
|
||||
|
||||
while not get($x-1|$x|$x+1, $y-1|$y|$y+1) {
|
||||
$x = ($x-1, $x, $x+1).pick;
|
||||
$y = ($y-1, $y, $y+1).pick;
|
||||
if (False xx 3, True).pick {
|
||||
$x = $x >= mid ?? $x - 1 !! $x + 1;
|
||||
$y = $y >= mid ?? $y - 1 !! $y + 1;
|
||||
}
|
||||
if abs(($x | $y) - mid) > $spawnradius {
|
||||
reset;
|
||||
}
|
||||
}
|
||||
set($x,$y);
|
||||
if $spawnradius < mid && abs(($x|$y) - mid) > $spawnradius - 5 {
|
||||
$spawnradius = $spawnradius + 1;
|
||||
}
|
||||
}
|
||||
|
||||
display;
|
||||
98
Task/Brownian-tree/Ring/brownian-tree.ring
Normal file
98
Task/Brownian-tree/Ring/brownian-tree.ring
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# Project : Brownian tree
|
||||
|
||||
load "stdlib.ring"
|
||||
load "guilib.ring"
|
||||
|
||||
paint = null
|
||||
|
||||
new qapp
|
||||
{
|
||||
win1 = new qwidget() {
|
||||
setwindowtitle("")
|
||||
setgeometry(100,100,800,600)
|
||||
label1 = new qlabel(win1) {
|
||||
setgeometry(10,10,800,600)
|
||||
settext("")
|
||||
}
|
||||
new qpushbutton(win1) {
|
||||
setgeometry(150,500,100,30)
|
||||
settext("draw")
|
||||
setclickevent("draw()")
|
||||
}
|
||||
show()
|
||||
}
|
||||
exec()
|
||||
}
|
||||
|
||||
func draw
|
||||
p1 = new qpicture()
|
||||
color = new qcolor() {
|
||||
setrgb(0,0,255,255)
|
||||
}
|
||||
pen = new qpen() {
|
||||
setcolor(color)
|
||||
setwidth(1)
|
||||
}
|
||||
paint = new qpainter() {
|
||||
begin(p1)
|
||||
color = new qcolor()
|
||||
color.setrgb(255,0,0,255)
|
||||
pen = new qpen() {
|
||||
setcolor(color)
|
||||
setwidth(1)}
|
||||
setpen(pen)
|
||||
|
||||
browniantree()
|
||||
|
||||
endpaint()
|
||||
}
|
||||
label1 { setpicture(p1) show() }
|
||||
return
|
||||
|
||||
func browniantree()
|
||||
numparticles = 3000
|
||||
canvas = newlist(210,210)
|
||||
canvas[randomf() * 100][randomf() * 200] = 1
|
||||
for i = 1 to numparticles
|
||||
x = floor((randomf() * 199)) + 1
|
||||
y = floor((randomf() * 199)) + 1
|
||||
if x = 1
|
||||
x = 2
|
||||
ok
|
||||
if y = 1
|
||||
y = 2
|
||||
ok
|
||||
while canvas[x+1][y+1]+canvas[x][y+1]+canvas[x+1][y]+canvas[x-1][y-1]+canvas[x-1][y]+canvas[x][y-1] = 0
|
||||
x = x + floor((randomf() * 2)) + 1
|
||||
y = y + floor((randomf() * 2)) + 1
|
||||
if x = 1
|
||||
x = 2
|
||||
ok
|
||||
if y = 1
|
||||
y = 2
|
||||
ok
|
||||
if x < 1 or x > 200 or y < 1 or y > 200
|
||||
x = floor((randomf() * 199)) + 1
|
||||
y = floor((randomf() * 199)) + 1
|
||||
if x = 1
|
||||
x = 2
|
||||
ok
|
||||
if y = 1
|
||||
y = 2
|
||||
ok
|
||||
ok
|
||||
end
|
||||
canvas[x][y] = 1
|
||||
paint.drawpoint(x,y)
|
||||
paint.drawpoint(x,y+1)
|
||||
paint.drawpoint(x,y+2)
|
||||
next
|
||||
|
||||
func randomf()
|
||||
decimals(10)
|
||||
str = "0."
|
||||
for i = 1 to 10
|
||||
nr = random(9)
|
||||
str = str + string(nr)
|
||||
next
|
||||
return number(str)
|
||||
56
Task/Brownian-tree/Ruby/brownian-tree.rb
Normal file
56
Task/Brownian-tree/Ruby/brownian-tree.rb
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
require 'rubygems'
|
||||
require 'RMagick'
|
||||
|
||||
NUM_PARTICLES = 1000
|
||||
SIZE = 800
|
||||
|
||||
def draw_brownian_tree world
|
||||
# set the seed
|
||||
world[rand SIZE][rand SIZE] = 1
|
||||
|
||||
NUM_PARTICLES.times do
|
||||
# set particle's position
|
||||
px = rand SIZE
|
||||
py = rand SIZE
|
||||
|
||||
loop do
|
||||
# randomly choose a direction
|
||||
dx = rand(3) - 1
|
||||
dy = rand(3) - 1
|
||||
|
||||
if dx + px < 0 or dx + px >= SIZE or dy + py < 0 or dy + py >= SIZE
|
||||
# plop the particle into some other random location
|
||||
px = rand SIZE
|
||||
py = rand SIZE
|
||||
elsif world[py + dy][px + dx] != 0
|
||||
# bumped into something
|
||||
world[py][px] = 1
|
||||
break
|
||||
else
|
||||
py += dy
|
||||
px += dx
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
world = Array.new(SIZE) { Array.new(SIZE, 0) }
|
||||
srand Time.now.to_i
|
||||
|
||||
draw_brownian_tree world
|
||||
|
||||
img = Magick::Image.new(SIZE, SIZE) do
|
||||
self.background_color = "black"
|
||||
end
|
||||
|
||||
draw = Magick::Draw.new
|
||||
draw.fill "white"
|
||||
|
||||
world.each_with_index do |row, y|
|
||||
row.each_with_index do |colour, x|
|
||||
draw.point x, y if colour != 0
|
||||
end
|
||||
end
|
||||
|
||||
draw.draw img
|
||||
img.write "brownian_tree.bmp"
|
||||
21
Task/Brownian-tree/Run-BASIC/brownian-tree.basic
Normal file
21
Task/Brownian-tree/Run-BASIC/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
numParticles = 3000
|
||||
dim canvas(201,201)
|
||||
graphic #g, 200,200
|
||||
#g fill("blue")
|
||||
canvas(rnd(1) * 100 , rnd(1) * 200) = 1 'start point
|
||||
for i = 1 To numParticles
|
||||
x = (rnd(1) * 199) + 1
|
||||
y = (rnd(1) * 199) + 1
|
||||
while canvas(x+1, y+1)+canvas(x, y+1)+canvas(x+1, y)+canvas(x-1, y-1)+canvas(x-1, y)+canvas(x, y-1) = 0
|
||||
x = x + (rnd(1)* 2) + 1
|
||||
y = y + (rnd(1)* 2) + 1
|
||||
If x < 1 Or x > 200 Or y < 1 Or y > 200 then
|
||||
x = (rnd(1) * 199) + 1
|
||||
y = (rnd(1) * 199) + 1
|
||||
end if
|
||||
wend
|
||||
canvas(x,y) = 1
|
||||
#g "color green ; set "; x; " "; y
|
||||
next i
|
||||
render #g
|
||||
#g "flush"
|
||||
104
Task/Brownian-tree/Rust/brownian-tree.rust
Normal file
104
Task/Brownian-tree/Rust/brownian-tree.rust
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
extern crate image;
|
||||
extern crate rand;
|
||||
|
||||
use image::ColorType;
|
||||
|
||||
use std::cmp::{min, max};
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::process;
|
||||
use rand::Rng;
|
||||
|
||||
fn help() {
|
||||
println!("Usage: brownian_tree <output_path> <mote_count> <edge_length>");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let mut output_path = Path::new("out.png");
|
||||
let mut mote_count: u32 = 10000;
|
||||
let mut width: usize = 512;
|
||||
let mut height: usize = 512;
|
||||
|
||||
match args.len() {
|
||||
1 => {}
|
||||
4 => {
|
||||
output_path = Path::new(&args[1]);
|
||||
mote_count = args[2].parse::<u32>().unwrap();
|
||||
width = args[3].parse::<usize>().unwrap();
|
||||
height = width;
|
||||
}
|
||||
_ => {
|
||||
help();
|
||||
process::exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(width >= 2);
|
||||
|
||||
// Base 1d array
|
||||
let mut field_raw = vec![0u8; width * height];
|
||||
populate_tree(&mut field_raw, width, height, mote_count);
|
||||
|
||||
// Balance image for 8-bit grayscale
|
||||
let our_max = field_raw.iter().fold(0u8, |champ, e| max(champ, *e));
|
||||
let fudge = std::u8::MAX / our_max;
|
||||
let balanced: Vec<u8> = field_raw.iter().map(|e| e * fudge).collect();
|
||||
|
||||
match image::save_buffer(output_path,
|
||||
&balanced,
|
||||
width as u32,
|
||||
height as u32,
|
||||
ColorType::L8) {
|
||||
Err(e) => println!("Error writing output image:\n{}", e),
|
||||
Ok(_) => println!("Output written to:\n{}", output_path.to_str().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn populate_tree(raw: &mut Vec<u8>, width: usize, height: usize, mc: u32) {
|
||||
// Vector of 'width' elements slices
|
||||
let mut field_base: Vec<_> = raw.as_mut_slice().chunks_mut(width).collect();
|
||||
// Addressable 2d vector
|
||||
let field: &mut [&mut [u8]] = field_base.as_mut_slice();
|
||||
|
||||
// Seed mote
|
||||
field[width / 2][height / 2] = 1;
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
for i in 0..mc {
|
||||
if i % 100 == 0 {
|
||||
println!("{}", i)
|
||||
}
|
||||
|
||||
let mut x=rng.gen_range(1usize..width-1);
|
||||
let mut y=rng.gen_range(1usize..height-1);
|
||||
|
||||
// Increment field value when motes spawn on top of the structure
|
||||
if field[x][y] > 0 {
|
||||
field[x][y] = min(field[x][y] as u32 + 1, std::u8::MAX as u32) as u8;
|
||||
continue;
|
||||
}
|
||||
|
||||
loop {
|
||||
let contacts = field[x - 1][y - 1] + field[x][y - 1] + field[x + 1][y - 1] +
|
||||
field[x - 1][y] + field[x + 1][y] +
|
||||
field[x - 1][y + 1] + field[x][y + 1] +
|
||||
field[x + 1][y + 1];
|
||||
|
||||
if contacts > 0 {
|
||||
field[x][y] = 1;
|
||||
break;
|
||||
} else {
|
||||
let xw = rng.gen_range(-1..2) + x as i32;
|
||||
let yw = rng.gen_range(-1..2) + y as i32;
|
||||
if xw < 1 || xw >= (width as i32 - 1) || yw < 1 || yw >= (height as i32 - 1) {
|
||||
break;
|
||||
}
|
||||
x = xw as usize;
|
||||
y = yw as usize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
Task/Brownian-tree/Scala/brownian-tree.scala
Normal file
50
Task/Brownian-tree/Scala/brownian-tree.scala
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import java.awt.Graphics
|
||||
import java.awt.image.BufferedImage
|
||||
|
||||
import javax.swing.JFrame
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
object BrownianTree extends App {
|
||||
val rand = scala.util.Random
|
||||
|
||||
class BrownianTree extends JFrame("Brownian Tree") with Runnable {
|
||||
setBounds(100, 100, 400, 300)
|
||||
val img = new BufferedImage(getWidth, getHeight, BufferedImage.TYPE_INT_RGB)
|
||||
|
||||
override def paint(g: Graphics): Unit = g.drawImage(img, 0, 0, this)
|
||||
|
||||
override def run(): Unit = {
|
||||
class Particle(var x: Int = rand.nextInt(img.getWidth),
|
||||
var y: Int = rand.nextInt(img.getHeight)) {
|
||||
|
||||
/* returns false if either out of bounds or collided with tree */
|
||||
def move: Boolean = {
|
||||
val (dx, dy) = (rand.nextInt(3) - 1, rand.nextInt(3) - 1)
|
||||
if ((x + dx < 0) || (y + dy < 0) ||
|
||||
(y + dy >= img.getHeight) || (x + dx >= img.getWidth)) false
|
||||
else {
|
||||
x += dx
|
||||
y += dy
|
||||
if ((img.getRGB(x, y) & 0xff00) == 0xff00) {
|
||||
img.setRGB(x - dx, y - dy, 0xff00)
|
||||
false
|
||||
} else true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var particles = ListBuffer.fill(20000)(new Particle)
|
||||
while (particles.nonEmpty) {
|
||||
particles = particles.filter(_.move)
|
||||
repaint()
|
||||
}
|
||||
}
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)
|
||||
img.setRGB(img.getWidth / 2, img.getHeight / 2, 0xff00)
|
||||
setVisible(true)
|
||||
}
|
||||
|
||||
new Thread(new BrownianTree).start()
|
||||
}
|
||||
108
Task/Brownian-tree/Scheme/brownian-tree.ss
Normal file
108
Task/Brownian-tree/Scheme/brownian-tree.ss
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
; Save bitmap to external file
|
||||
(define (save-pbm bitmap filename)
|
||||
(define f (open-output-file filename))
|
||||
(simple-format f "P1\n~A ~A\n"
|
||||
(list-ref (array-dimensions bitmap) 0)
|
||||
(list-ref (array-dimensions bitmap) 1))
|
||||
(do ((c 0 (+ c 1))) ((eqv? c (list-ref (array-dimensions bitmap) 1)))
|
||||
(do ((r 0 (+ r 1))) ((eqv? r (list-ref (array-dimensions bitmap) 0)))
|
||||
(display (array-ref bitmap r c) f))
|
||||
(newline f))
|
||||
(close-output-port f)
|
||||
)
|
||||
|
||||
; Return a random coordinate in the bitmap that isn't filled yet along with a direction
|
||||
(define (new-particle bitmap)
|
||||
(define x (random (list-ref (array-dimensions bitmap) 0)))
|
||||
(define y (random (list-ref (array-dimensions bitmap) 1)))
|
||||
(define dx (- (random 3) 1))
|
||||
(define dy (- (random 3) 1))
|
||||
;Repeat until we find an unused location
|
||||
(if (> (array-ref bitmap x y) 0)
|
||||
(new-particle bitmap)
|
||||
(list (list x y) (list dx dy))))
|
||||
|
||||
; Check neighboring coordinates to see if a collision occured
|
||||
(define (collision-check bitmap p)
|
||||
(define c #f)
|
||||
(define oob #f)
|
||||
(define x (list-ref (car p) 0))
|
||||
(define y (list-ref (car p) 1))
|
||||
(define dx (list-ref (cadr p) 0))
|
||||
(define dy (list-ref (cadr p) 1))
|
||||
(define w (list-ref (array-dimensions bitmap) 0))
|
||||
(define h (list-ref (array-dimensions bitmap) 1))
|
||||
|
||||
; If the particle hasn't gone out of bounds keep checking for a collision
|
||||
(if (or (> 0 x) (> 0 y) (<= w x) (<= h y))
|
||||
(set! oob #t)
|
||||
(do ((x (- (list-ref (car p) 0) 1) (+ x 1))) ((eqv? x (+ (list-ref (car p) 0) 2)))
|
||||
(do ((y (- (list-ref (car p) 1) 1) (+ y 1))) ((eqv? y (+ (list-ref (car p) 1) 2)))
|
||||
; Check existing neighbors for collisions
|
||||
(if (and (<= 0 x) (<= 0 y) (> w x) (> h y))
|
||||
(if (not (zero? (array-ref bitmap x y)))
|
||||
(set! c #t))))))
|
||||
(if oob
|
||||
#f ; Return false if out of bounds
|
||||
(if c
|
||||
p ; Return the point of collision if a collision occured
|
||||
(if (and (zero? dx) (zero? dy))
|
||||
#f ; Return false if particle is motionless with no collision
|
||||
(collision-check bitmap (particle-move p))))))
|
||||
|
||||
; Plot a particle on the bitmap
|
||||
(define (particle-plot! bitmap p)
|
||||
(array-set! bitmap 1 (list-ref (car p) 0) (list-ref (car p) 1)))
|
||||
|
||||
; Move a particle along its slope
|
||||
(define (particle-move p)
|
||||
(list (list
|
||||
(+ (list-ref (car p) 0) (list-ref (cadr p) 0))
|
||||
(+ (list-ref (car p) 1) (list-ref (cadr p) 1)))
|
||||
(cadr p)))
|
||||
|
||||
; Grow a brownian tree
|
||||
(define (grow-brownian-tree! bitmap collisions)
|
||||
(define w (list-ref (array-dimensions bitmap) 0))
|
||||
(define h (list-ref (array-dimensions bitmap) 1))
|
||||
|
||||
; Generate a new particle at a random location
|
||||
(define p (new-particle bitmap))
|
||||
|
||||
; Find a collision or lack of one and plot it on the bitmap
|
||||
(set! p (collision-check bitmap p))
|
||||
(if p (begin
|
||||
; Display collision number and the place it happened
|
||||
(display collisions)(display ": ")(display (car p))(newline)
|
||||
(set! collisions (- collisions 1))
|
||||
; Plot the point
|
||||
(particle-plot! bitmap p)))
|
||||
|
||||
; If we're done say so
|
||||
(if (zero? collisions)
|
||||
(display "Done\n"))
|
||||
|
||||
; Keep going until we have enough collisions
|
||||
; or have filled the bitmap
|
||||
(if (and (< 0 collisions) (memq 0 (array->list (array-contents bitmap))))
|
||||
(grow-brownian-tree! bitmap collisions)))
|
||||
|
||||
; Plot a random point to seed the brownian tree
|
||||
(define (seed-brownian-tree! bitmap)
|
||||
(define p (new-particle bitmap))
|
||||
(particle-plot! bitmap p))
|
||||
|
||||
;;; Example usage ;;;
|
||||
; Seed the random number generator
|
||||
(let ((time (gettimeofday)))
|
||||
(set! *random-state*
|
||||
(seed->random-state (+ (car time) (cdr time)))))
|
||||
|
||||
; Generate a tree with 320*240 collisions on a bitmap of the size 640x480
|
||||
; The bitmap is zeroed to start and written with a one where a collision occurs
|
||||
(define bitmap (make-array 0 640 480))
|
||||
(seed-brownian-tree! bitmap)
|
||||
(grow-brownian-tree! bitmap (* 320 240))
|
||||
|
||||
; Save to a portable bitmap file
|
||||
(save-pbm bitmap "brownian-tree.pbm")
|
||||
53
Task/Brownian-tree/Seed7/brownian-tree.seed7
Normal file
53
Task/Brownian-tree/Seed7/brownian-tree.seed7
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
$ include "seed7_05.s7i";
|
||||
include "draw.s7i";
|
||||
include "keybd.s7i";
|
||||
|
||||
const integer: SIZE is 300;
|
||||
const integer: SCALE is 1;
|
||||
|
||||
const proc: genBrownianTree (in integer: fieldSize, in integer: numParticles) is func
|
||||
local
|
||||
var array array integer: world is 0 times 0 times 0;
|
||||
var integer: px is 0;
|
||||
var integer: py is 0;
|
||||
var integer: dx is 0;
|
||||
var integer: dy is 0;
|
||||
var integer: i is 0;
|
||||
var boolean: bumped is FALSE;
|
||||
begin
|
||||
world := fieldSize times fieldSize times 0;
|
||||
world[rand(1, fieldSize)][rand(1, fieldSize)] := 1; # Set the seed
|
||||
for i range 1 to numParticles do
|
||||
# Set particle's initial position
|
||||
px := rand(1, fieldSize);
|
||||
py := rand(1, fieldSize);
|
||||
bumped := FALSE;
|
||||
repeat
|
||||
# Randomly choose a direction
|
||||
dx := rand(-1, 1);
|
||||
dy := rand(-1, 1);
|
||||
if dx + px < 1 or dx + px > fieldSize or dy + py < 1 or dy + py > fieldSize then
|
||||
# Plop the particle into some other random location
|
||||
px := rand(1, fieldSize);
|
||||
py := rand(1, fieldSize);
|
||||
elsif world[py + dy][px + dx] <> 0 then
|
||||
# Bumped into something
|
||||
world[py][px] := 1;
|
||||
rect(SCALE * pred(px), SCALE * pred(py), SCALE, SCALE, white);
|
||||
DRAW_FLUSH;
|
||||
bumped := TRUE;
|
||||
else
|
||||
py +:= dy;
|
||||
px +:= dx;
|
||||
end if;
|
||||
until bumped;
|
||||
end for;
|
||||
end func;
|
||||
|
||||
const proc: main is func
|
||||
begin
|
||||
screen(SIZE * SCALE, SIZE * SCALE);
|
||||
KEYBOARD := GRAPH_KEYBOARD;
|
||||
genBrownianTree(SIZE, 20000);
|
||||
readln(KEYBOARD);
|
||||
end func;
|
||||
47
Task/Brownian-tree/SequenceL/brownian-tree-1.sequencel
Normal file
47
Task/Brownian-tree/SequenceL/brownian-tree-1.sequencel
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import <Utilities/Random.sl>;
|
||||
import <Utilities/Sequence.sl>;
|
||||
|
||||
POINT ::= (X: int, Y: int);
|
||||
RET_VAL ::= (World: int(2), Rand: RandomGenerator<int, int>, Point: POINT);
|
||||
|
||||
randomWalk(x, y, world(2), rand) :=
|
||||
let
|
||||
randX := getRandom(rand);
|
||||
randY := getRandom(randX.Generator);
|
||||
nextX := x + (randX.Value mod 3) - 1;
|
||||
nextY := y + (randY.Value mod 3) - 1;
|
||||
newStartX := (randX.Value mod (size(world) - 2)) + 2;
|
||||
newStartY := (randY.Value mod (size(world) - 2)) + 2;
|
||||
|
||||
numNeighbors := world[y-1,x-1] + world[y-1,x] + world[y-1,x+1] +
|
||||
world[y,x-1] + world[y,x+1] +
|
||||
world[y+1,x-1] + world[y+1,x] + world[y+1,x+1];
|
||||
|
||||
outOfBounds := nextX <= 1 or nextY <= 1 or nextX >= size(world) or nextY >= size(world);
|
||||
in
|
||||
randomWalk(newStartX, newStartY, world, randY.Generator) when world[y,x] = 1 or outOfBounds
|
||||
else
|
||||
(X: x, Y: y) when numNeighbors > 0
|
||||
else
|
||||
randomWalk(nextX, nextY, world, randY.Generator);
|
||||
|
||||
step(rand, world(2)) :=
|
||||
let
|
||||
walkSeed := getRandom(rand);
|
||||
newParticle := randomWalk(size(world)/2,size(world)/2, world, seedRandom(walkSeed.Value));
|
||||
|
||||
newWorld[j] :=
|
||||
world[j] when j /= newParticle.Y
|
||||
else
|
||||
setElementAt(world[j], newParticle.X, 1);
|
||||
in
|
||||
(World: newWorld, Rand: walkSeed.Generator, Point: newParticle);
|
||||
|
||||
|
||||
initialWorld(worldSize, seed) :=
|
||||
let
|
||||
world[i,j] := 1 when i = worldSize / 2 and j = worldSize / 2 else 0
|
||||
foreach i within 1 ... worldSize,
|
||||
j within 1 ... worldSize;
|
||||
in
|
||||
(World: world, Rand: seedRandom(seed), Point: (X: worldSize / 2, Y: worldSize / 2));
|
||||
44
Task/Brownian-tree/SequenceL/brownian-tree-2.sequencel
Normal file
44
Task/Brownian-tree/SequenceL/brownian-tree-2.sequencel
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#include <time.h>
|
||||
#include <cstdlib>
|
||||
#include "CImg.h"
|
||||
#include "SL_Generated.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cimg_library;
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
int threads = 0;
|
||||
int worldSize = 300; if(argc > 1) worldSize = atoi(argv[1]);
|
||||
int seed = time(NULL); if(argc > 2) seed = atoi(argv[2]);
|
||||
int scale = 2; if(argc > 3) scale = atoi(argv[3]);
|
||||
|
||||
sl_init(threads);
|
||||
|
||||
_sl_RET_VAL current;
|
||||
_sl_RET_VAL result;
|
||||
|
||||
const unsigned char black[] = {0};
|
||||
|
||||
CImg<unsigned char> visu(worldSize * scale, worldSize * scale, 1, 1, 0);
|
||||
CImgDisplay draw_disp(visu);
|
||||
cout << "Brownian Tree in SequenceL" << endl << "Threads: " << threads << endl;
|
||||
draw_disp.set_title("Brownian Tree in SequenceL: %d Threads", threads);
|
||||
|
||||
visu.fill(255);
|
||||
|
||||
sl_initialWorld(worldSize, seed, threads, current);
|
||||
|
||||
while(!draw_disp.is_closed())
|
||||
{
|
||||
visu.draw_circle((current.Point.val().Y - 1) * scale, (current.Point.val().X - 1) * scale, scale/2, black, 1);
|
||||
visu.display(draw_disp);
|
||||
sl_step(current.Rand.val(), current.World, threads, result);
|
||||
current = result;
|
||||
draw_disp.wait(1);
|
||||
}
|
||||
|
||||
sl_done();
|
||||
|
||||
return 0;
|
||||
}
|
||||
78
Task/Brownian-tree/Sidef/brownian-tree.sidef
Normal file
78
Task/Brownian-tree/Sidef/brownian-tree.sidef
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
const size = 100
|
||||
const mid = size>>1
|
||||
const particlenum = 1000
|
||||
|
||||
var map = []
|
||||
var spawnradius = 5
|
||||
|
||||
func set(x, y) {
|
||||
map[x][y] = 1
|
||||
}
|
||||
|
||||
func get(x, y) {
|
||||
map[x][y] \\ 0
|
||||
}
|
||||
|
||||
set(mid, mid)
|
||||
|
||||
var blocks = [
|
||||
" ",
|
||||
"\N{UPPER HALF BLOCK}",
|
||||
"\N{LOWER HALF BLOCK}",
|
||||
"\N{FULL BLOCK}"
|
||||
]
|
||||
|
||||
func block(a, b) {
|
||||
blocks[2*b + a]
|
||||
}
|
||||
|
||||
func display {
|
||||
0..size `by` 2 -> map {|y|
|
||||
0..size -> map {|x|
|
||||
if ([x, y].all { .-mid < spawnradius }) {
|
||||
block(get(x, y), get(x, y+1))
|
||||
} else { " " }
|
||||
}.join
|
||||
}.join("\n").say
|
||||
}
|
||||
|
||||
for progress in (^particlenum) {
|
||||
var (x=0, y=0)
|
||||
|
||||
var reset = {
|
||||
do {
|
||||
(x, y) = (
|
||||
(mid-spawnradius .. mid+spawnradius -> pick),
|
||||
[mid-spawnradius, mid+spawnradius] -> pick
|
||||
)
|
||||
(x, y) = (y, x) if (1.rand < 0.5)
|
||||
} while(get(x, y))
|
||||
}
|
||||
|
||||
reset.run
|
||||
|
||||
while ([[-1, 0, 1]]*2 -> cartesian.any {|pair|
|
||||
get(x+pair[0], y+pair[1])
|
||||
} -> not) {
|
||||
x = [x-1, x, x+1].pick
|
||||
y = [y-1, y, y+1].pick
|
||||
|
||||
if (1.rand < 0.25) {
|
||||
x = (x >= mid ? (x-1) : (x+1))
|
||||
y = (y >= mid ? (y-1) : (y+1))
|
||||
}
|
||||
|
||||
if ([x,y].any { .-mid > spawnradius }) {
|
||||
reset.run
|
||||
}
|
||||
}
|
||||
|
||||
set(x, y)
|
||||
display() if (progress %% 50)
|
||||
|
||||
if ((spawnradius < mid) && [x,y].any { .-mid > spawnradius-5 }) {
|
||||
++spawnradius
|
||||
}
|
||||
}
|
||||
|
||||
display()
|
||||
67
Task/Brownian-tree/Simula/brownian-tree.simula
Normal file
67
Task/Brownian-tree/Simula/brownian-tree.simula
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
BEGIN
|
||||
INTEGER NUM_PARTICLES;
|
||||
INTEGER LINES, COLUMNS;
|
||||
INTEGER SEED;
|
||||
|
||||
NUM_PARTICLES := 1000;
|
||||
LINES := 46;
|
||||
COLUMNS := 80;
|
||||
SEED := ININT;
|
||||
BEGIN
|
||||
|
||||
PROCEDURE DRAW_BROWNIAN_TREE(WORLD); INTEGER ARRAY WORLD;
|
||||
BEGIN
|
||||
INTEGER PX, PY; COMMENT PARTICLE VALUES ;
|
||||
INTEGER DX, DY; COMMENT OFFSETS ;
|
||||
INTEGER I;
|
||||
|
||||
COMMENT SET THE SEED ;
|
||||
PX := RANDINT(0,LINES-1,SEED);
|
||||
PY := RANDINT(0,COLUMNS-1,SEED);
|
||||
WORLD(PX,PY) := 1;
|
||||
|
||||
FOR I := 0 STEP 1 UNTIL NUM_PARTICLES - 1 DO BEGIN
|
||||
COMMENT SET PARTICLE'S INITIAL POSITION ;
|
||||
PX := RANDINT(0,LINES-1,SEED);
|
||||
PY := RANDINT(0,COLUMNS-1,SEED);
|
||||
|
||||
WHILE TRUE DO BEGIN
|
||||
COMMENT RANDOMLY CHOOSE A DIRECTION ;
|
||||
DX := RANDINT(-1,1,SEED);
|
||||
DY := RANDINT(-1,1,SEED);
|
||||
|
||||
IF DX + PX < 0 OR DX + PX >= LINES
|
||||
OR DY + PY < 0 OR DY + PY >= COLUMNS THEN
|
||||
BEGIN
|
||||
COMMENT PLOP THE PARTICLE INTO SOME OTHER RANDOM LOCATION ;
|
||||
PX := RANDINT(0,LINES-1,SEED);
|
||||
PY := RANDINT(0,COLUMNS-1,SEED);
|
||||
END ELSE IF WORLD(PX + DX, PY + DY) <> 0 THEN BEGIN
|
||||
COMMENT BUMPED INTO SOMETHING ;
|
||||
WORLD(PX, PY) := 1;
|
||||
GO TO BREAK;
|
||||
END ELSE BEGIN
|
||||
PY := PY + DY;
|
||||
PX := PX + DX;
|
||||
END IF;
|
||||
END WHILE;
|
||||
BREAK:
|
||||
END FOR;
|
||||
END DRAW_BROWNIAN_TREE;
|
||||
|
||||
INTEGER ARRAY WORLD(0:LINES-1,0:COLUMNS-1);
|
||||
INTEGER I,J;
|
||||
|
||||
DRAW_BROWNIAN_TREE(WORLD);
|
||||
|
||||
FOR I := 0 STEP 1 UNTIL LINES-1 DO
|
||||
BEGIN
|
||||
FOR J := 0 STEP 1 UNTIL COLUMNS-1 DO
|
||||
BEGIN
|
||||
OUTCHAR(IF WORLD(I,J)=0 THEN '.' ELSE '*');
|
||||
END;
|
||||
OUTIMAGE;
|
||||
END;
|
||||
|
||||
END;
|
||||
END.
|
||||
24
Task/Brownian-tree/Sinclair-ZX81-BASIC/brownian-tree.basic
Normal file
24
Task/Brownian-tree/Sinclair-ZX81-BASIC/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
10 DIM A$(20,20)
|
||||
20 LET A$(10,10)="1"
|
||||
30 FOR Y=42 TO 23 STEP -1
|
||||
40 FOR X=0 TO 19
|
||||
50 PLOT X,Y
|
||||
60 NEXT X
|
||||
70 NEXT Y
|
||||
80 UNPLOT 9,33
|
||||
90 FOR I=1 TO 80
|
||||
100 LET X=INT (RND*18)+2
|
||||
110 LET Y=INT (RND*18)+2
|
||||
120 IF A$(X,Y)="1" THEN GOTO 100
|
||||
130 UNPLOT X-1,43-Y
|
||||
140 IF A$(X+1,Y+1)="1" OR A$(X+1,Y)="1" OR A$(X+1,Y-1)="1" OR A$(X,Y+1)="1" OR A$(X,Y-1)="1" OR A$(X-1,Y+1)="1" OR A$(X-1,Y)="1" OR A$(X-1,Y-1)="1" THEN GOTO 230
|
||||
150 PLOT X-1,43-Y
|
||||
160 LET X=X+INT (RND*3)-1
|
||||
170 LET Y=Y+INT (RND*3)-1
|
||||
180 IF X=1 THEN LET X=19
|
||||
190 IF X=20 THEN LET X=2
|
||||
200 IF Y=1 THEN LET Y=19
|
||||
210 IF Y=20 THEN LET Y=2
|
||||
220 GOTO 130
|
||||
230 LET A$(X,Y)="1"
|
||||
240 NEXT I
|
||||
27
Task/Brownian-tree/TI-83-BASIC/brownian-tree.basic
Normal file
27
Task/Brownian-tree/TI-83-BASIC/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
:StoreGDB 0
|
||||
:ClrDraw
|
||||
:FnOff
|
||||
:AxesOff
|
||||
:Pxl-On(31,47)
|
||||
:For(I,1,50)
|
||||
:randInt(1,93)→X
|
||||
:randInt(1,61)→Y
|
||||
:1→A
|
||||
:While A
|
||||
:randInt(1,4)→D
|
||||
:Pxl-Off(Y,X)
|
||||
:If D=1 and Y≥2
|
||||
:Y-1→Y
|
||||
:If D=2 and X≤92
|
||||
:X+1→X
|
||||
:If D=3 and Y≤60
|
||||
:Y+1→Y
|
||||
:If D=4 and X≥2
|
||||
:X-1→X
|
||||
:Pxl-On(Y,X)
|
||||
:If pxl-Test(Y+1,X) or pxl-Test(Y+1,X+1) or pxl-Test(Y+1,X-1) or pxl-Test(Y,X+1) or pxl-Test(Y,X-1) or pxl-Test(Y-1,X) or pxl-Test(Y-1,X-1) or pxl-Test(Y-1,X+1)
|
||||
:0→A
|
||||
:End
|
||||
:End
|
||||
:Pause
|
||||
:RecallGDB 0
|
||||
52
Task/Brownian-tree/Tcl/brownian-tree.tcl
Normal file
52
Task/Brownian-tree/Tcl/brownian-tree.tcl
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package require Tcl 8.5
|
||||
package require Tk
|
||||
|
||||
set SIZE 300
|
||||
|
||||
image create photo brownianTree -width $SIZE -height $SIZE
|
||||
interp alias {} plot {} brownianTree put white -to
|
||||
brownianTree put black -to 0 0 [expr {$SIZE-1}] [expr {$SIZE-1}]
|
||||
proc rnd {range} {expr {int(rand() * $range)}}
|
||||
|
||||
proc makeBrownianTree count {
|
||||
global SIZE
|
||||
# Set the seed
|
||||
plot [rnd $SIZE] [rnd $SIZE]
|
||||
for {set i 0} {$i<$count} {incr i} {
|
||||
# Set a random particle's initial position
|
||||
set px [rnd $SIZE]
|
||||
set py [rnd $SIZE]
|
||||
|
||||
while 1 {
|
||||
# Randomly choose a direction
|
||||
set dx [expr {[rnd 3] - 1}]
|
||||
set dy [expr {[rnd 3] - 1}]
|
||||
|
||||
# If we are going out of bounds...
|
||||
if {$px+$dx < 0 || $px+$dx >= $SIZE || $py+$dy < 0 || $py+$dy>=$SIZE} {
|
||||
# Out of bounds, so move back in
|
||||
set dx [expr {[rnd 3] - 1}]
|
||||
set dy [expr {[rnd 3] - 1}]
|
||||
continue
|
||||
}
|
||||
|
||||
set ox $px
|
||||
set oy $py
|
||||
# Move/see if we would hit anything
|
||||
incr px $dx
|
||||
incr py $dy
|
||||
if {[lindex [brownianTree get $px $py] 0]} {
|
||||
# Hit something, so plot where we were
|
||||
plot $ox $oy
|
||||
break
|
||||
}
|
||||
}
|
||||
## For display while things are processing, uncomment next line
|
||||
#update;puts -nonewline .;flush stdout
|
||||
}
|
||||
}
|
||||
|
||||
pack [label .l -image brownianTree]
|
||||
update
|
||||
makeBrownianTree 1000
|
||||
brownianTree write tree.ppm
|
||||
129
Task/Brownian-tree/Visual-Basic-.NET/brownian-tree.vb
Normal file
129
Task/Brownian-tree/Visual-Basic-.NET/brownian-tree.vb
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
Imports System.Drawing.Imaging
|
||||
|
||||
Public Class Form1
|
||||
|
||||
ReadOnly iCanvasColor As Integer = Color.Black.ToArgb
|
||||
ReadOnly iSeedColor As Integer = Color.White.ToArgb
|
||||
|
||||
Dim iCanvasWidth As Integer = 0
|
||||
Dim iCanvasHeight As Integer = 0
|
||||
|
||||
Dim iPixels() As Integer = Nothing
|
||||
|
||||
Private Sub BrownianTree()
|
||||
|
||||
Dim oCanvas As Bitmap = Nothing
|
||||
Dim oRandom As New Random(Now.Millisecond)
|
||||
Dim oXY As Point = Nothing
|
||||
Dim iParticleCount As Integer = 0
|
||||
|
||||
iCanvasWidth = ClientSize.Width
|
||||
iCanvasHeight = ClientSize.Height
|
||||
|
||||
oCanvas = New Bitmap(iCanvasWidth, iCanvasHeight, Imaging.PixelFormat.Format24bppRgb)
|
||||
|
||||
Graphics.FromImage(oCanvas).Clear(Color.FromArgb(iCanvasColor))
|
||||
|
||||
iPixels = GetData(oCanvas)
|
||||
|
||||
' We'll use about 10% of the total number of pixels in the canvas for the particle count.
|
||||
iParticleCount = CInt(iPixels.Length * 0.1)
|
||||
|
||||
' Set the seed to a random location on the canvas.
|
||||
iPixels(oRandom.Next(iPixels.Length)) = iSeedColor
|
||||
|
||||
' Run through the particles.
|
||||
For i As Integer = 0 To iParticleCount
|
||||
Do
|
||||
' Find an open pixel.
|
||||
oXY = New Point(oRandom.Next(oCanvas.Width), oRandom.Next(oCanvas.Height))
|
||||
Loop While iPixels(oXY.Y * oCanvas.Width + oXY.X) = iSeedColor
|
||||
|
||||
' Jitter until the pixel bumps another.
|
||||
While Not CheckAdjacency(oXY)
|
||||
oXY.X += oRandom.Next(-1, 2)
|
||||
oXY.Y += oRandom.Next(-1, 2)
|
||||
|
||||
' Make sure we don't jitter ourselves out of bounds.
|
||||
If oXY.X < 0 Then oXY.X = 0 Else If oXY.X >= oCanvas.Width Then oXY.X = oCanvas.Width - 1
|
||||
If oXY.Y < 0 Then oXY.Y = 0 Else If oXY.Y >= oCanvas.Height Then oXY.Y = oCanvas.Height - 1
|
||||
End While
|
||||
|
||||
iPixels(oXY.Y * oCanvas.Width + oXY.X) = iSeedColor
|
||||
|
||||
' If you'd like to see updates as each particle collides and becomes
|
||||
' part of the tree, uncomment the next 4 lines (it does slow it down slightly).
|
||||
' SetData(oCanvas, iPixels)
|
||||
' BackgroundImage = oCanvas
|
||||
' Invalidate()
|
||||
' Application.DoEvents()
|
||||
Next
|
||||
|
||||
oCanvas.Save("BrownianTree.bmp")
|
||||
BackgroundImage = oCanvas
|
||||
|
||||
End Sub
|
||||
|
||||
' Check adjacent pixels for an illuminated pixel.
|
||||
Private Function CheckAdjacency(ByVal XY As Point) As Boolean
|
||||
|
||||
Dim n As Integer = 0
|
||||
|
||||
For y As Integer = -1 To 1
|
||||
' Make sure not to drop off the top or bottom of the image.
|
||||
If (XY.Y + y < 0) OrElse (XY.Y + y >= iCanvasHeight) Then Continue For
|
||||
|
||||
For x As Integer = -1 To 1
|
||||
' Make sure not to drop off the left or right of the image.
|
||||
If (XY.X + x < 0) OrElse (XY.X + x >= iCanvasWidth) Then Continue For
|
||||
|
||||
' Don't run the test on the calling pixel.
|
||||
If y <> 0 AndAlso x <> 0 Then
|
||||
n = (XY.Y + y) * iCanvasWidth + (XY.X + x)
|
||||
If iPixels(n) = iSeedColor Then Return True
|
||||
End If
|
||||
Next
|
||||
Next
|
||||
|
||||
Return False
|
||||
|
||||
End Function
|
||||
|
||||
Private Function GetData(ByVal Map As Bitmap) As Integer()
|
||||
|
||||
Dim oBMPData As BitmapData = Nothing
|
||||
Dim oData() As Integer = Nothing
|
||||
|
||||
oBMPData = Map.LockBits(New Rectangle(0, 0, Map.Width, Map.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)
|
||||
|
||||
Array.Resize(oData, Map.Width * Map.Height)
|
||||
|
||||
Runtime.InteropServices.Marshal.Copy(oBMPData.Scan0, oData, 0, oData.Length)
|
||||
|
||||
Map.UnlockBits(oBMPData)
|
||||
|
||||
Return oData
|
||||
|
||||
End Function
|
||||
|
||||
Private Sub SetData(ByVal Map As Bitmap, ByVal Data As Integer())
|
||||
|
||||
Dim oBMPData As BitmapData = Nothing
|
||||
|
||||
oBMPData = Map.LockBits(New Rectangle(0, 0, Map.Width, Map.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb)
|
||||
|
||||
Runtime.InteropServices.Marshal.Copy(Data, 0, oBMPData.Scan0, Data.Length)
|
||||
|
||||
Map.UnlockBits(oBMPData)
|
||||
|
||||
End Sub
|
||||
|
||||
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
|
||||
DoubleBuffered = True
|
||||
BackgroundImageLayout = ImageLayout.Center
|
||||
Show()
|
||||
Activate()
|
||||
Application.DoEvents()
|
||||
BrownianTree()
|
||||
End Sub
|
||||
End Class
|
||||
91
Task/Brownian-tree/Wren/brownian-tree.wren
Normal file
91
Task/Brownian-tree/Wren/brownian-tree.wren
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import "graphics" for Canvas, Color
|
||||
import "dome" for Window
|
||||
import "random" for Random
|
||||
|
||||
var Rand = Random.new()
|
||||
|
||||
var N8 = [
|
||||
[-1, -1], [-1, 0], [-1, 1],
|
||||
[ 0, -1], [ 0, 1],
|
||||
[ 1, -1], [ 1, 0], [ 1, 1]
|
||||
]
|
||||
|
||||
class BrownianTree {
|
||||
construct new(width, height, particles) {
|
||||
Window.title = "Brownian Tree"
|
||||
Window.resize(width, height)
|
||||
Canvas.resize(width, height)
|
||||
_w = width
|
||||
_h = height
|
||||
_n = particles
|
||||
}
|
||||
|
||||
init() {
|
||||
Canvas.cls(Color.brown)
|
||||
// off center seed position makes pleasingly asymetrical tree
|
||||
Canvas.pset(_w/3, _h/3, Color.white)
|
||||
var x = 0
|
||||
var y = 0
|
||||
var a = 0
|
||||
while (a < _n) {
|
||||
// generate random position for new particle
|
||||
x = Rand.int(_w)
|
||||
y = Rand.int(_h)
|
||||
var outer = false
|
||||
var p = Canvas.pget(x, y)
|
||||
if (p == Color.white) {
|
||||
// as position is already set, find a nearby free position.
|
||||
while (p == Color.white) {
|
||||
x = x + Rand.int(3) - 1
|
||||
y = y + Rand.int(3) - 1
|
||||
var ok = x >= 0 && x < _w && y >= 0 && y < _h
|
||||
if (ok) {
|
||||
p = Canvas.pget(x, y)
|
||||
} else { // out of bounds, consider particle lost
|
||||
outer = true
|
||||
a = a + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// else particle is in free space
|
||||
// let it wonder until it touches tree
|
||||
while (!hasNeighbor(x, y)) {
|
||||
x = x + Rand.int(3) - 1
|
||||
y = y + Rand.int(3) - 1
|
||||
var ok = x >= 0 && x < _w && y >= 0 && y < _h
|
||||
if (ok) {
|
||||
p = Canvas.pget(x, y)
|
||||
} else { // out of bounds, consider particle lost
|
||||
outer = true
|
||||
a = a + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (outer) continue
|
||||
// x, y now specify a free position touching the tree
|
||||
Canvas.pset(x, y, Color.white)
|
||||
a = a + 1
|
||||
// progress indicator
|
||||
if (a % 100 == 0) System.print("%(a) of %(_n)")
|
||||
a = a + 1
|
||||
}
|
||||
}
|
||||
|
||||
hasNeighbor(x, y) {
|
||||
for (n in N8) {
|
||||
var xn = x + n[0]
|
||||
var yn = y + n[1]
|
||||
var ok = xn >= 0 && xn < _w && yn >= 0 && yn < _h
|
||||
if (ok && Canvas.pget(xn, yn) == Color.white) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
update() {}
|
||||
|
||||
draw(alpha) {}
|
||||
}
|
||||
|
||||
var Game = BrownianTree.new(200, 150, 7500)
|
||||
18
Task/Brownian-tree/XPL0/brownian-tree.xpl0
Normal file
18
Task/Brownian-tree/XPL0/brownian-tree.xpl0
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
include c:\cxpl\codes; \intrinsic 'code' declarations
|
||||
def W=128, H=W; \width and height of field
|
||||
int X, Y;
|
||||
[SetVid($13); \set 320x200 graphic video mode
|
||||
Point(W/2, H/2, 6\brown\); \place seed in center of field
|
||||
loop [repeat X:= Ran(W); Y:= Ran(H); \inject particle
|
||||
until ReadPix(X,Y) = 0; \ in an empty location
|
||||
loop [Point(X, Y, 6\brown\); \show particle
|
||||
if ReadPix(X-1,Y) or ReadPix(X+1,Y) or \particle collided
|
||||
ReadPix(X,Y-1) or ReadPix(X,Y+1) then quit;
|
||||
Point(X, Y, 0\black\); \erase particle
|
||||
X:= X + Ran(3)-1; \(Brownian) move particle
|
||||
Y:= Y + Ran(3)-1;
|
||||
if X<0 or X>=W or Y<0 or Y>=H then quit; \out of bounds
|
||||
];
|
||||
if KeyHit then [SetVid(3); quit]; \restore text mode
|
||||
];
|
||||
]
|
||||
16
Task/Brownian-tree/ZX-Spectrum-Basic/brownian-tree.basic
Normal file
16
Task/Brownian-tree/ZX-Spectrum-Basic/brownian-tree.basic
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
10 LET np=1000
|
||||
20 PAPER 0: INK 4: CLS
|
||||
30 PLOT 128,88
|
||||
40 FOR i=1 TO np
|
||||
50 GO SUB 1000
|
||||
60 IF NOT ((POINT (x+1,y+1)+POINT (x,y+1)+POINT (x+1,y)+POINT (x-1,y-1)+POINT (x-1,y)+POINT (x,y-1))=0) THEN GO TO 100
|
||||
70 LET x=x+RND*2-1: LET y=y+RND*2-1
|
||||
80 IF x<1 OR x>254 OR y<1 OR y>174 THEN GO SUB 1000
|
||||
90 GO TO 60
|
||||
100 PLOT x,y
|
||||
110 NEXT i
|
||||
120 STOP
|
||||
1000 REM Calculate new pos
|
||||
1010 LET x=RND*254
|
||||
1020 LET y=RND*174
|
||||
1030 RETURN
|
||||
33
Task/Brownian-tree/Zkl/brownian-tree.zkl
Normal file
33
Task/Brownian-tree/Zkl/brownian-tree.zkl
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
w:=h:=400; numParticles:=20_000;
|
||||
bitmap:=PPM(w+2,h+2,0); // add borders as clip regions
|
||||
|
||||
bitmap[w/2,h/2]=0xff|ff|ff; // plant seed
|
||||
bitmap.circle(w/2,h/2,h/2,0x0f|0f|0f); // plant seeds
|
||||
|
||||
fcn touching(x,y,bitmap){ // is (x,y) touching another pixel?
|
||||
// (x,y) isn't on the border/edge of bitmap so no edge conditions
|
||||
var [const] box=T(T(-1,-1),T(0,-1),T(1,-1),
|
||||
T(-1, 0), T(1, 0),
|
||||
T(-1, 1),T(0, 1),T(1, 1));
|
||||
box.filter1('wrap([(a,b)]){ bitmap[a+x,b+y] }); //-->False: not touching, (a,b) if is
|
||||
}
|
||||
|
||||
while(numParticles){
|
||||
c:=(0x1|00|00).random(0x1|00|00|00) + (0x1|00).random(0x1|00|00) + (0x1).random(0x1|00);
|
||||
reg x,y;
|
||||
do{ x=(1).random(w); y=(1).random(h); }while(bitmap[x,y]); // find empty spot
|
||||
while(1){ // stagger around until bump into a particle, then attach barnicle
|
||||
if(touching(x,y,bitmap)){
|
||||
bitmap[x,y]=c;
|
||||
bitmap.write(f:=File("brownianTree.zkl.ppm","wb")); // tell ImageViewer to update image
|
||||
numParticles-=1;
|
||||
break;
|
||||
}
|
||||
x+=(-1).random(2); y+=(-1).random(2); // [-1,0,1]
|
||||
if( not ((0<x<w) and (0<y<h)) ){ // next to border --> color border
|
||||
bitmap[x,y]=c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
bitmap.writeJPGFile("brownianTree.zkl.jpg"); // the final image
|
||||
Loading…
Add table
Add a link
Reference in a new issue