재귀
함수는 자신을 지칭하는 코드를 포함할 수도 있는데 다양한 용법으로 쓰이는 이 기법은 재귀라고 부른다. 소프트웨어가 아닌 다른 분야에서 재귀가 발생하는 적절한 예로 2개의 거울이 끊임없이 반사를 만들어내는 것을 들 수 있다. 소프트웨어 에서 재귀는 함수가 자신의 블록 안에서 자신을 호출할 수 있다는 것이다.
거울의 경우와 달리 코딩에서는 이 상황을 없애기 위해 함수에서 나올 만한 방법이 필요하다. 다음 두 프로그램은 다른 방식으로 같은 결과를 도출해냈다. 첫 번째 프로그램은 for 루프를 사용했고 두 번째 프로그램은 재귀를 사용했다.
void setup () {
size (100, 100); drawLines5, 15);}
void drawLines(int x, int num) {
for (int i = 0; i < num; num -= 1) {
line(s, 20, x, 80);
x+= 5;
}
}
void setup () |
size(100, 100);
drawLines(5, 15);
}
void drawLines (int x, int num) (
line(x, 20, x, 80);
if (num > 0) |
drawLines(×+5, num-1);
}
}
이 재귀의 예시들은 컴퓨터 계산능력을 더 사용해 과제를 수행한다. 간단한 계산에는 for 루프 사용을 권하지만 재귀적 접근은 더 복잡한 것을 수행하는 데 적합하다. 다음 두 예시는 drawT() 함수를 이용한 재귀효과를 보여준다.
int x = 50; / / X-coordinate of the center
int y = 100; // Y-coordinate of the bottom
int a = 35; // Half the width of the top bar
void setup() {
size(100, 100);
noLoop();}
void draw() {
drawT(x, y, a);
}
void drawT(int xpos, int ypos, int apex) {
line(xpos, ypos, xpos, ypos-apex);
line(xpos-(apex/ 2), ypos-apex,
xpos+ (apex / 2), ypos-арех);
}
drawT() 함수는 함수 블록 안에 자신을 호출하는 코드를 넣어 재귀를 피했다. 네 번째 매개변수인 mum이 추가되어 제 키 횟수를 설정했다. 이 값은 함수가 호출될 때마다 1씩 감산된다. 이 값이 0보다 크지 않을 때 프로그램은 draw() 함수로 돌아오며 이미지가 화면에 표시된다.
int x = 50; // X-coordinate of the center
int y = 100; / / Y-coordinate of the bottom
int a = 35; // Half the width of the top bar
int n = 3; / / Number of recursions
void setup() {
size(100, 100);
}
void draw() {
background(204);
drawT(x, y, a, n);}
void drawI(int x, int y, int apex, int num) {
line(x, y, x, y-apex);
line(x-apex, y-apex, x+apex, y-apex);
// This relational expression must eventually be
I false to stop the recursion and return to draw)
if (num > 0) {
drawT(x-apex, y-apex, apex/ 2, num-1);
drawT(×+ apex, y-apex, apex/2, num-1);
}
}
위의 이진 나무 구조(각 노드node에서 2개의 가지가 뻗어나가는 모양)는 다른 형태로도 시각화될 수 있다. 이 프로그램 은 각 노드에 원을 그린다. 각 노드의 y 좌표는 같으며 원의 반지름은 각 단계마다 반으로 줄어든다.
int x = 63; / / X-coordinate
int r = 85; // Starting radius
int n = 6; // Number of recursions
void setup() {
size(100, 100);
noStroke();
}
void draw() {
background(204);
drawCircle(x, r, n);
}
void drawCircle(int x, int radius, int num) {
float t = 126 * num/4.0;
fil(tt);
ellipse(×, 50, radius*2, radius*2);
if (num > 0) {
drawCircle(× - radius/2, radius /2, num-1);
drawCircle(x + radius /2, radius/ 2, num-1);
}
}
조금만 수정해도 형태를 크게 변화시킬 수 있다. 각 단계의 원은 이전 형태와 달리 무작위적 위치에 존재한다. 이 변화로 표시되는 이미지는 정돈과 혼란의 균형을 맞춘 형태가 된다.
재귀의 각 단계에서 원의 크기는 작아지고 이전 단계로부터의 거리도 줄고 값은 점점 더 어두워진다. randomSeed() 함수에 사용된 매개변수는 초당 2회 업데이트되어 새로운 컴포지션을 만들어낸다.