Silverback9

#야생으로

Creative Coding 독학 제294일 2024년01월15일(수)

지금 지평선 위로 노란 해가 떠 올라 있어요~^^*

들판에 은은하게 퍼져나가는 노란빛 주황빛^^*

네~^^* 아침입니다~^^*

지금 저는 이동을 하고 있습니다~^^* 그래서요~^^*

우리 아침엔 음악만 함께 듣고~^^* 오후에 다시 만날까요~^^*

네~^^* 고마워요~^^*

지금 어느 곳은 저녁 어둠이 내리고 있겠네요^^* 네, 지구는 둥그니까요~^^*

피아노 건반을 콕콕콕 누르면~^^* 동글동글한 공들이 퐁퐁 튀어오르는 것 같아요^^*

피아노가 쏘아올린 작은 공들로 저글링도 하면서~^^* 노란 아침 여유를 누리시기 바래요~^^*

조용한 곳에서 튕겨지는 기타의 현은 작은 웃음소리를 닮은 것 같아요~^^*

저는 차창 밖을 바라보며 마음의 기지개를 켤게요~^^*

조용하고 아늑한 집 안에서 두 팔을 펴고 기지개를 부드럽게 주욱~^^* 켜 보시겠어요~^^*

Good Morning~^^*

오늘도 멋진 아침 보내시고요~^^*

저는 오후에 다시 돌아올게요~^^* 또 만나요~~^^* 쓩~~^^*

네~^^*

멋진 하루를 보내고 계신가요^^*

노랗던 아침 해는~^^*

이제 회색 빛이 더해진 맑은 하얀 빛 융단을 하늘 위에 펼쳐 놓고 자신의 얼굴을 그 안에 가리고 있어요.

네~^^* 쌀 씻어 밥 짓기 딱 좋은 시간입니다~^^*

저녁 맛있게 드시고 다시 만나요, 우리~~^^* 쓩~^^*

네~^^*

오늘은 Travelling Salesman의 여정의 총 거리의 합이 가장 짧은 기록 recordDistance가 갱신될 때마다, 그 여정 경로를 보여주는 코딩작업을 해 볼게요~^^*

여정 경로는 배열 구조로 되어 있었지요~^^*?

여정의 최단거리 기록 recordDistance가 갱신될 때마다, 그 여정 배열을 복사하여 좀 더 진하고 굵은 선으로 표현해 보도록 하면 어떨까요?

배열을 복사하는 함수 slice()를 사용해 보겠습니다~^^*

하나. 현재기준으로 가장 좋은 경로를 담을 변수 bestEver를 준비하겠습니다.

둘. 맨 처음 만들어진 여행경로 cities 배열을 복사하여 bestEver에 저장하겠습니다~

var bestEver;

function setup() {
  createCanvas(400, 400);
  for( var i = 0; i < totalCities; i++ ) {
    var v = createVector(random(width), random(height));
    cities[i] = v; 
  }
  var d = calcDistance(cities);
  recordDistance = d;
  bestEver = cities.slice();
}

셋. 여정의 최단거리 기록 recordDistance가 갱신될 때마다, 그때의 cities 배열을 복사하여 bestEver에 저장하겠습니다.

function draw() {
   .
   .
   .
  var d = calcDistance(cities);
  if (d < recordDistance) {
    recordDistance = d;
    bestEver = cities.slice();
    console.log(recordDistance);
  }
}

넷. 현재기준 최단경로의 여정인 bestEver을 Hot Pink 굵은 선으로 그려보겠습니다.

function draw() {
   .
   .
   .
  stroke(255, 0, 255);
  strokeWeight(4);
  noFill();
  beginShape();
  for( var i = 0; i < bestEver.length; i++ ) {
    vertex(bestEver[i].x, bestEver[i].y);
  }
  endShape();
   .
   .
   .
}

자 그럼 우리 전체 코드를 한 번 살펴 볼까요~^^*

var cities = [];
var totalCities = 10;

var recordDistance;
var bestEver;
//여행경로 최단거리 신기록을 기록해 보고자 합니다.
//최단거리 경로를 함께 나타내 보겠습니다. 핫! 핑크! 어때요~^^*

function setup() {
  createCanvas(400, 400);
  for( var i = 0; i < totalCities; i++ ) {
    var v = createVector(random(width), random(height));
    cities[i] = v; 
  }
  var d = calcDistance(cities);
  recordDistance = d;
  bestEver = cities.slice();
}
//다양한 좌표위치를 가진 벡터를 생성하여, 도시들을 담는 배열 cities[]에 저장하겠습니다.
// 첫 번째로 구성된 도시 배열의 거리 총합을 구해서 변수 d에 담습니다. 
// 이 d의 값이 첫 번째 최단 이동 거리의 신기록 recordDistance가 되겠네요^^*
// 첫 번째 cities[]이 맨  최단거리경로 bestEver가 되겠네요^^*

function draw() {
  background(0);
  fill(255);
  for( var i = 0; i < cities.length; i++ ) {
    ellipse(cities[i].x, cities[i].y, 8, 8);
  }
  //도시들을 담는 배열 cities[]의 구성요소들의 위치좌표에 지름 8의 원을 그리겠습니다. 
  
  stroke(255);
  strokeWeight(2);
  noFill();
  beginShape();
  for( var i = 0; i < cities.length; i++ ) {
    vertex(cities[i].x, cities[i].y);
  }
  endShape();
  //도시들의 위치좌표를 꼭지점으로 하여, 꼭지점들을 연결해 보겠습니다. 
  //beginShape() - vertex() - endShape() 구조를 복습하고 가실게요~^^*
  
  stroke(255, 0, 255);
  strokeWeight(4);
  noFill();
  beginShape();
  for( var i = 0; i < bestEver.length; i++ ) {
    vertex(bestEver[i].x, bestEver[i].y);
  }
  endShape();
  //핫핑크 굵은 선으로 현재기준 최단거리 경로 bestEver를 그려보겠습니다~^^*
  //신선한 핑크 빛 혈액이 흐르는 믿음직한 굵은 핏줄이 보이겠네요^^*
  
  
  var i = floor(random(cities.length));
  var j = floor(random(cities.length));
  swap(cities, i, j); 
  //도시들을 담은 배열 cities[]의 구성원을 무작위로 두 개 선정하여, 서로의 정보를 맞바꾸겠습니다. 
  //간혹 이 두 도시가 우연히 동일할 수도 있겠지만, 무작위 선택을 계속 무한반복 하기 때문에 큰 문제는 없을 것 같아요...
  
  
  var d = calcDistance(cities);
  if (d < recordDistance) {
    recordDistance = d;
    bestEver = cities.slice();
    console.log(recordDistance);
  }
}
  //도시가 무작위 swap()되어 새롭게 된 도시 이동경로의 거리 총합 d가 
  //최단거리 신기록 recordDistance보다 작다면
  //신기록 갱신~~^^*!!!
  //신기록이 갱신되었으니, 이때의 cities[]를 복사하여 최단거리 경로 bestEver에 저장하겠습니다. 
  //콘솔창에 현재의 최단거리 신기록을 보여주도록 하겠습니다~^^*

   

function swap( a, i, j) {
  var temp;
  temp = a[i];
  a[i] = a[j];
  a[j] = temp;
}

function calcDistance(points) {
  var sum = 0;
  for (var i = 0 ; i < points.length - 1; i++) {
    var d = dist(points[i].x, points[i].y, points[i+1].x, points[i+1].y);
    sum += d;
  }
  return sum;
 
} 
//도시배열 마지막 바로 앞 도시 point.length - 2까지 반복한다는 것에 우리 주의를 기울여 볼까요? 
//도시 배열은, [0] ~ [point.length - 1]까지의 구성요소를 가지고 있지요? 
//배열 length 길이가 3이면, 구성요소는 [0], [1], [ 2 (= length-1) ]가 있겠네요?
//이때 배열 마지막 바로 앞의 구성요소는 [ 1 (= length -2) ]가 되겠네요?
//그래서, 도시 배열 마지막 바로 앞 도시와 그 다음 도시(마지막 도시) 사이의 거리를 구하기 위해서는~^^*
//i가 point.length -1 보다 작을 때까지만, 
// 즉, i가 point.length - 2가 될 때까지만 
// for 구문을 안의 작업문을 반복해 보면 어떨까요?~~^^* 

도시 10개를 잇는 최단거리 경로 bestEver를 보러 가실까요~~^^*

10개의 경우 컴퓨터가 최단거리를 찾아내기 위해 살펴봐야 할 경우의 수가 3,628,800개라서, 우리 눈으로 볼 떄 금방 찾아볼 수 있는 효율적인 경로를 컴퓨터가 찾아내기까지는 시간이 많이 걸릴 것 같네요.

4개의 도시의 경우는 금방 잘 찾아낼 것 같은데요~^^*

5개의 도시의 경우도 무난하게~~^^*

네~^^* 오늘 저와 함께 Travelling Salesman Problem 코드를 완성해 주셔서 감사합니다!

네~^^* 저와 함께 Brute Force Solution <<모든 경우의 수를 다 시도해 보기>> 방법을 통해 Travelling Salesman Problem을 해결해 주셔서 감사합니다!!!

Travelling Salesman! 소중한 보부상!

첫 번째 방법도 시간이 좀 걸려서 그렇지 참 재미있었죠~~^^*

내일부터는 새로운 방법으로 최.적.경.로.를 또 찾아 볼게요! YEAH~~^^*

오늘도 따뜻하고 뿌듯한 밤 코~^^* 하시고요~^^*

내일 우리 또 만나서 새로운 도전 이어가 보기로 해요~~^^*

네~~^^* 꿈은 이루어 집니다~~^^*

댓글 남기기