Dragon curve
From Rosetta Code
| This page uses content from Wikipedia. The original article was at Drachenkurve. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU Free Documentation License. |
Programming Task
This is a programming task. It lays out a problem which Rosetta Code users are encouraged to solve, using languages they know.
Contents |
[edit] BASIC
Works with: FreeBASIC
Works with: QuickBasic version 4.5
DIM SHARED angle AS DOUBLE SUB turn (degrees AS DOUBLE) angle = angle + degrees*3.14159265/180 END SUB SUB forward (length AS DOUBLE) LINE - STEP (COS(angle)*length, SIN(angle)*length), 7 END SUB SUB dragon (length AS DOUBLE, split AS INTEGER, d AS DOUBLE) IF split=0 THEN forward length ELSE turn d*45 dragon length/1.4142136, split-1, 1 turn -d*90 dragon length/1.4142136, split-1, -1 turn d*45 END IF END SUB ' Main program SCREEN 12 angle = 0 PSET (150,180), 0 dragon 400, 12, 1 SLEEP
[edit] Common Lisp
Library: CLIM
This implementation uses nested transformations rather than turtle motions. with-scaling, etc. establish transformations for the drawing which occurs within them.
The recursive dragon-part function draws a curve connecting (0,0) to (1,0); if depth is 0 then the curve is a straight line. bend-direction is either 1 or -1 to specify whether the deviation from a straight line should be to the right or left.
(defpackage #:dragon
(:use #:clim-lisp #:clim)
(:export #:dragon #:dragon-part))
(in-package #:dragon)
(defun dragon-part (depth bend-direction)
(if (zerop depth)
(draw-line* *standard-output* 0 0 1 0)
(with-scaling (t (/ (sqrt 2)))
(with-rotation (t (* pi -1/4 bend-direction))
(dragon-part (1- depth) 1)
(with-translation (t 1 0)
(with-rotation (t (* pi 1/2 bend-direction))
(dragon-part (1- depth) -1)))))))
(defun dragon (&optional (depth 7) (size 100))
(with-room-for-graphics ()
(with-scaling (t size)
(dragon-part depth 1))))
[edit] D
A text version of Dragon curve.
The Dragon curve drawn using an L-system.
- variables : X Y F
- constants : + −
- start : FX
- rules : (X → X+YF+),(Y → -FX-Y)
- angle : 90°
module txdraco ; // text dragon curve import std.stdio ; const int[][] dirs = [[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]] ; const char[] trace = r"-\|/-\|/" ; struct Board { char[][] b = [[0]] ; // set at least 1x1 board int shiftx = 0 ; int shifty = 0 ; const char spc = ' ' ; void clear() { shiftx = shifty = 0 ; b = [[0]] ; } void check(int x, int y) { while( y + shifty < 0) { char[] newr = new char[b[0].length] ; newr[] = spc ; b = newr ~ b ; shifty++ ; } while( y + shifty >= b.length) { char[] newr = new char[b[0].length] ; newr[] = spc ; b ~= newr ; } while( x + shiftx < 0) { foreach(inout c ; b) c = [spc] ~ c ; shiftx++ ; } while ( x + shiftx >= b[0].length ) foreach(inout c ; b) c ~= [spc] ; } char opIndexAssign(char value, int x, int y) { check(x,y) ; b[y + shifty][x + shiftx] = value ; return value ; } string toString() { string s ; foreach(c ; b) s ~= std.format.format("%s\n", c) ; return s ; } } struct TState { int x = 0, y = 0, heading = 0; } struct Turtle { TState t ; void reset() { t.x = t.y = t.heading = 0 ; } void turn(int dir) { t.heading = (t.heading + 8 + dir) % 8 ; } void forward(inout Board b) { with(t) { x += dirs[heading][0] ; y += dirs[heading][1] ; b[x,y] = trace[heading] ; x += dirs[heading][0] ; y += dirs[heading][1] ; b[x,y] = b.spc ; } } } void dragonX(int n, inout Turtle t, inout Board b) { if(n >= 0) { // X -> X+YF+ dragonX(n - 1, t, b) ; t.turn(2) ; dragonY(n - 1, t, b) ; t.forward(b) ; t.turn(2) ; } } void dragonY(int n, inout Turtle t, inout Board b) { if(n >= 0) { // Y -> -FX-Y t.turn(-2) ; t.forward(b) ; dragonX(n - 1, t, b) ; t.turn(-2) ; dragonY(n - 1, t, b) ; } } void main() { Turtle t ; Board b ; // initiator : FX t.forward(b) ; // <- F dragonX(8, t, b) ; // <- X writefln(b) ; } |
[edit] Logo
to dcr :step :length make "step :step - 1 make "length :length / 1.41421 if :step > 0 [rt 45 dcr :step :length lt 90 dcl :step :length rt 45] if :step = 0 [rt 45 fd :length lt 90 fd :length rt 45] end to dcl :step :length make "step :step - 1 make "length :length / 1.41421 if :step > 0 [lt 45 dcr :step :length rt 90 dcl :step :length lt 45] if :step = 0 [lt 45 fd :length rt 90 fd :length lt 45] end
The program can be started using dcr 4 300 or dcl 4 300.
Or removing duplication:
to dc :step :length :dir if :step = 0 [fd :length stop] rt :dir dc :step-1 :length/1.41421 45 lt :dir lt :dir dc :step-1 :length/1.41421 -45 rt :dir end to dragon :step :length dc :step :length 45 end
An alternative approach by using sentence-like grammar using four productions o->on, n->wn, w->ws, s->os. O, S, N and W mean cardinal points.
to O :step :length if :step=1 [Rt 90 fd :length Lt 90] [O (:step - 1) (:length / 1.41421) N (:step - 1) (:length / 1.41421)] end to N :step :length if :step=1 [fd :length] [W (:step - 1) (:length / 1.41421) N (:step - 1) (:length / 1.41421)] end to W :step :length if :step=1 [Lt 90 fd :length Rt 90] [W (:step - 1) (:length / 1.41421) S (:step - 1) (:length / 1.41421)] end to S :step :length if :step=1 [Rt 180 fd :length Lt 180] [O (:step - 1) (:length / 1.41421) S (:step - 1) (:length / 1.41421)] end
[edit] Pascal
using Compas (Pascal with Logo-expansion):
procedure dcr(step,dir:integer;length:real); begin; step:=step -1; length:= length/sqrt(2); if dir > 0 then begin if step > 0 then begin turnright(45); dcr(step,1,length); turnleft(90); dcr(step,0,length); turnright(45); end else begin turnright(45); forward(length); turnleft(90); forward(length); turnright(45); end; end else begin if step > 0 then begin turnleft(45); dcr(step,1,length); turnright(90); dcr(step,0,length); turnleft(45); end else begin turnleft(45); forward(length); turnright(90); forward(length); turnleft(45); end; end; end;
main program:
begin init; penup; back(100); pendown; dcr(step,direction,length); close; end.
[edit] Python
Translation of: Logo
Library: turtle
from turtle import * def dragon(step, length): dcr(step, length) def dcr(step, length): step -= 1 length /= 1.41421 if step > 0: right(45) dcr(step, length) left(90) dcl(step, length) right(45) else: right(45) forward(length) left(90) forward(length) right(45) def dcl(step, length): step -= 1 length /= 1.41421 if step > 0: left(45) dcr(step, length) right(90) dcl(step, length) left(45) else: left(45) forward(length) right(90) forward(length) left(45)
This is an idiomatic python version:
from turtle import * def dragon(step, length, zig=right, zag=left): if step <= 0: forward(length) return step -= 1 length /= 1.41421 zig(45) dragon(step, length, right, left) zag(90) dragon(step, length, left, right) zig(45)
Categories: Recursion | Programming Tasks | Fractals | BASIC | Common Lisp | CLIM | D | Logo | Pascal | Python | Turtle

