주요 내용
컴퓨터 프로그래밍
코스: 컴퓨터 프로그래밍 > 단원 5
단원 2: 무작위성랜덤 워크
벡터의 복잡도와 물리적 운동을 살펴보기 전에 화면상에서 이동하는 것이 무엇을 의미하는지 잠시 생각해 봅시다. 움직임 중 가장 유명하고 가장 단순한 시뮬레이션인 랜덤 워크(random walk)를 살펴봅시다.
평균대의 중간에 서 있다고 상상해 보세요. 10초마다 동전을 던집니다. 앞면이 나오면 할 걸음 앞으로 나옵니다. 뒷면이 나오면 한 걸음 뒤로 물러납니다. 이것이 랜덤 워크입니다. 랜덤 워크란 연속되는 임의의 단계로 정의되는 경로입니다. 평균대에서 바닥으로 내려와 동일한 동전을 두 번 던져 2차원에서 다음과 같이 여러 방향으로 랜덤 워크를 합니다.
1 회 | 2 회 | 결과 |
---|---|---|
앞면 | 앞면 | 앞으로 걸어갑니다. |
앞면 | 뒷면 | 오른쪽으로 걸어갑니다. |
뒷면 | 앞면 | 왼쪽으로 걸어갑니다. |
뒷면 | 뒷면 | 뒤로 걸어갑니다. |
매우 단순한 알고리즘처럼 보일 수 있습니다. 그럼에도 불구하고 랜덤 워크는 기체 내 분자의 움직임부터 카지노에서 하루를 보내는 도박꾼의 행동까지 현실 세계에서 일어나는 현상을 모델링 하는 데 이용할 수 있습니다. 우리의 경우 세 가지 목표를 염두에 두고 랜덤 워크를 공부함으로써 이 주제를 시작하겠습니다.
랜덤 워커(Random Walker) 객체
우선
Walker
객체를 구축하면서 객체지향적 프로그래밍(OOP)을 살짝 복습해 봅시다. 본문에서는 이 개념을 대략적으로만 살펴볼겁니다. 한번도 OOP를 접해본 적이 없다면 객체지향적 JavaScript단원에 가보세요.JavaScript에서 객체(object)란 일종의 데이터 유형으로, 프로퍼티를 가지고 있고 프로토타입을 통해 기능이 추가될 수 있습니다. 이 단원에서는 데이터 기록(화면에 존재하는 위치)을 유지하고 특정 행동(자기 자신을 그리거나 한 발자국 걸어가는 것과 같은)을 수행할 능력을 갖추는
Walker
객체를 설계하는 것이 목표입니다. Walker
의 인스턴스를 생성하기 위해 Walker
객체를 정의해야 합니다. 이 객체를 쿠키 모양을 찍는 데 쓰는 틀처럼 사용할 것이고 새로운 각 Walker
인스턴스는 쿠키에 해당합니다.Walker
객체 유형을 정의하는 것으로 시작하겠습니다. Walker
는 두 개의 데이터인 자신의 x-위치와 y-위치에 대한 수만 필요합니다. 이 수치를 생성자 함수에 넣고 배경 중심에 오도록 설정해 봅시다.var Walker = function() {
this.x = width/2;
this.y = height/2;
};
x와 y 위치를 계속 따라가는 기능에 추가하여
Walker
객체를 이 위치로 호출할 수 있는 메소드도 가져야 합니다. 첫 번째는 객체가 자신을 검은색 점으로 표시하는 메소드입니다. JavaScript에서는 메소드를 객체의 prototype
에 덧붙임으로써 객체에 메소드를 추가한다는 것을 기억하기 바랍니다. Walker.prototype.display = function() {
stroke(0, 0, 0);
point(this.x, this.y);
};
두 번째 메소드는
Walker
객체가 한 발자국 걸어가도록 지시합니다. 지금부터 흥미로워지는 부분입니다. 무작위 방향으로 걸었던 바닥을 기억하시나요? 이제 배경을 그 경우와 똑같이 이용해 봅시다. 모두 네 개 방향으로 발을 뻗을 수 있습니다. 오른쪽 걸음은 x
를 증가(x++
) 시키고 왼쪽 걸음은 x
를 감소(x--
) 시키며 앞 걸음은 픽셀을 증가(y++
) 시키고 뒤 걸음은 픽셀을 감소(y--
) 시켜서 묘사할 수 있습니다. 이 4 가지 방향을 어떻게 선택해야 할까요? 앞에서는 동전을 두 번 던진다고 했습니다. 그러나 ProcessingJS에서 선택권이 있으면 임의로 골라주는 random()
을 이용할 수 있습니다.Walker.prototype.walk = function() {
var choice = floor(random(4));
};
위 코드는 0과 4 사이에서 임의의 부동 소수를 선택한 후
floor()
를 이용하여 정수로 변환합니다. 결과는 0, 1, 2, 3입니다. 엄밀히 따지면 가장 높은 수는 절대로 4.0이 될 수 없습니다. 얻을 수 있는 최댓값은 3.999999999(소수 자릿수만큼 9가 있음)입니다. floor()
는 어떤 수를 기준으로 작거나 같은 수 중에서 가장 가까운 정수를 반환하기 때문에 가장 높은 수는 3입니다. 그다음 선택된 난수에 따라 적절한 방향으로(왼쪽, 오른쪽, 위 또는 아래) 걷도록 합시다.Walker.prototype.walk = function() {
var choice = floor(random(4));
if (choice === 0) {
this.x++;
} else if (choice === 1) {
this.x--;
} else if (choice === 2) {
this.y++;
} else {
this.y--;
}
};
이제 클래스를 작성했습니다. 이제 프로그램에 실제로
Walker
객체를 만들 때가 되었습니다. 무작위로 한 걸음만 걷는 움직임을 모델링 한다는 가정하에 새로운 연산자를 갖는 생성자 함수를 호출함으로써 하나의 전역 변수 유형의 Walker
를 선언한 후 초기화합니다. var w = new Walker();
이제 walker가 어떤 행동을 실제로 하도록
draw()
함수를 정의하고 walker에게 한 걸음 걷고 호출될 때마다 자기 자신을 그리도록 만들어 봅시다.draw = function() {
w.walk();
w.display();
};
draw 함수에서
background()
를 호출하지 않기 때문에 배경에서 랜덤 워크의 흔적을 볼 수 있습니다.랜덤 워커(Random Walker) 개선하기
랜덤 워커를 몇 가지 방면으로 개선할 수 있습니다. 하나는 현재 우리 walker는 위, 아래, 왼쪽, 오른쪽 4가지 방향으로 걸음이 제한됩니다. 그러나 화면 내의 모든 픽셀은 8가지 방향에 이웃이 있습니다. 같은 자리에 있는 것까지 합하면 모두 9가지 경우의 수가 나옵니다.
Walker
객체가 임의의 이웃하는 픽셀로 걸어가는 (또는 제자리에 있는) 상황을 구현하기 위해 0부터 8까지(9가지 경우의 수) 사이의 수를 선택할 수 있습니다. 그러나 좀 더 효율적인 방법은 코딩할 때 x축에서 갈 수 있는 3 방향(-1, 0, 또는 1)을 선택하고 y-축에서 갈 수 있는 3방향을 선택하게 만드는 것입니다.Walker.prototype.walk = function() {
var stepx = floor(random(3))-1;
var stepy = floor(random(3))-1;
this.x += stepx;
this.y += stepy;
};
더욱 개선하자면,
x
와 y
에 대해 소수를 대신 사용하고 만약 우리가 구축한 환경에서 "2.2"와 "2.4" 사이의 차이를 실제로 출력할 수 있다면 -1과 1 사이의 임의의 값에 따라 이동할 수 있습니다.Walker.prototype.walk = function() {
var stepx = random(-1, 1);
var stepy = random(-1, 1);
this.x += stepx;
this.y += stepy;
};
“전통적인” 랜덤 워크 프로그램을 세 가지 방법으로 변형시켜보았는데 모두 공통점이 있습니다. 아무런 시점에서
Walker
가 어떤 방향으로 걸어갈 확률(움직이지 않을 수도 있습니다)은 Walker
가 다른 방향으로 걸어갈 확률과 동일하다는 것입니다. 다시 말하면 4가지 가능한 걸음이 있을 때 Walker
가 어떤 방향으로 걸어갈 확률은 1/4(또는 25%)입니다. 9개의 방향이 있는 경우 1/9 (또는 11.1%)입니다.이는
random()
함수가 동작하는 방법입니다. 이 함수의 난수 생성기는 수를 "균등한”분포로 생성합니다. 난수가 선택될 때마다 계산하고 이를 바탕으로 막대그래프를 그리는 프로그램을 이용하여 분포가 실제로 균등한지 테스트 해볼 수 있습니다.프로그램을 몇 분간 돌려보세요. 막대기가 높이가 모두 같나요? 아마 그렇지 않을 겁니다. 표본의 크기(즉, 선택된 난수의 수)는 조금 작아서 가끔 특정 숫자가 더 자주 선택되는 불일치가 있습니다. 좋은 난수 생성기를 이용하면 시간이 지나면서 이런 불일치는 사라지게 됩니다.
random()
함수에서 얻은 난수는 진정한 의미의 난수가 아닙니다. 이런 난수를 “의사 난수(pseudo-random)”라고 합니다. 의사 난수는 난수성을 시뮬레이션하는 수학적 함수의 결과입니다. 이 함수는 시간에 따라 일정한 규칙을 생성하지만 시간 주기가 너무 길어서 마치 순수한 난수처럼 보이는 것뿐입니다!다음 장에서는 특정 방향으로 걸어가려는 "경향"을 갖는 walker를 생성할 수 있는 다양한 방법에 관해 논의해 보겠습니다. 다음 단계로 넘어가기 전에 응용 문제가 여러분을 기다리고 있습니다!
본 "내추럴 시뮬레이션" 과정은 다니엘 쉬프만(Daniel Shiffman)이 저술한 "The Nature of Code"의 내용을 차용한 것이며, 본 내용물의 저작권은 Creative Commons Attribution-NonCommercial 3.0 Unported License를 적용합니다.