반응형

 

유튜브

어느 날 알고리즘에 이 영상이 올라왔다.

수학을 못하는 나.. 코딩은 자신 있으니 엑셀이 아닌 C++로 만들어보고 싶었다.

(근데 수업 때 이런걸로 수업해주셨으면.. 수학에 관심 있었을텐데..)

 

준비

일단 제작 방법을 생각해보자!

2중 포문으로 100 * 100의 블럭을 출력하면 될 것 같다.

2중 포문에선 먼저 계산을 해서 배열에 저장하고 나중에 출력하면 될 것 같다.

 

그리고 색까지 넣어서 이쁘게 꾸미는 것을 목표로 한다.

 

제작

#include <iostream>
#include <math.h>
#include <windows.h>
#include <algorithm>

#define x 101 //가로 캔버스 크기
#define y 101 //세로 캔버스 크기
#define outline 15 //아웃라인 색깔

using namespace std;

void textcolor(int color); //텍스트 컬러 지정
void top_bottom_block(int color); //위쪽 아래쪽 아웃라인 블럭 지정
void left_right_blck(int color); //왼쪽 오른쪽 아웃라인 블럭 지정

double a[x][y] = {};

int main() {
	ios::sync_with_stdio(false);
	cout.tie(NULL);

	for (int i = 0; i < x; i++)
		for (int j = 0; j < y; j++)
			a[i][j] = sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2)); //식 입력

	top_bottom_block(outline); //15는 흰색

	for (int i = 0; i < x; i++) {
		left_right_blck(15); //15는 흰색
		for (int j = 0; j < y; j++) {
			textcolor(a[i][j]);
			cout << "■";
		}
		left_right_blck(15); //15는 흰색
		cout << endl;
	}

	top_bottom_block(outline); //15는 흰색
}


void textcolor(int color) {
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}

void top_bottom_block(int color) {
	textcolor(color);

	for (int i = 0; i < x + 2; i++)
		cout << "■";
	cout << endl;
}

void left_right_blck(int color) {
	textcolor(color);
	cout << "■";
}

일단 기본 적인 구조는 만들어 보았다.

캔버스의 크기가 101로 되어있는 이유는 100으로 하게 되면 원의 중심점이 제대로 잡혀지지 않기 때문에 101 홀수로 맞춰서 잡아주었다.

 

 

sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2))

식 입력 부분에 위 코드를 집어넣으니 원이 출력되었다.

어떤 원리인진 자세하게는 모르겠지만 어쨌든 신기하다!

 

그 다음은 영상에서 나온 원과 배경을 구분하여 출력하는 것이다.

min((double)1, max((double)0, 25 - sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2))))

나는 일단 색은 그대로 두었다. 만약 이 색이 마음에 안들면 출력 2중 포문 안쪽 textcolor(a[i][j]); 에서 a[i][j] 뒤에 + 5 이런걸로 해서 색을 지정하든지 일정 값마다 색을 다르게 하는 코드를 추가해서 해보면 될 것 같다.

 

어쨌든 다음!

min((double)1, max((double)0, 25 + 15 * cos(5 * atan2(j - (x / 2), i - (y / 2))) - sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2))))

신기한건 수학의 식은 한줄이며 이 식만 길어지는 것 뿐인데 그냥 코딩으로 하나씩 포문 여러번 돌리면서 문제를 해결하는 것보다 짧게 되서 수학에 약간 관심이 있어지는 것 같기도..??

 

또 다음!

min((double)1, max((double)0, 20 + 20 * pow((0.5 + 0.5 * cos(5 * atan2(j - (x / 2), i - (y / 2)))), 0.3) - sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2))))

계속 식을 적으면서 불편한 것은.. 영상에서 나온 엑셀의 식을 C++에 적용을 하기 위해 제곱을 pow로 하고 하는 과정들이 조금 불편하지만.. 오우 너무 근데.. 신기하다..

 

다음!

min((double)1, max((double)0, 20 + 20 * pow((0.5 + 0.5 * cos(5 * atan2(j - (x / 2), i - (y / 2)))), 0.3) - sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2)))) + min((double)1, max((double)0, 19 - sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2))))

으어어어... 길다..

 

다음!

min((double)1, max((double)0, 20 + 20 * pow((0.5 + 0.5 * cos(5 * atan2(j - (x / 2), i - (y / 2)))), 0.3) - sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2)))) + min((double)1, max((double)0, 19 - sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2)))) - 2 * min((double)1, max((double)0, 2 - abs(4 - sqrt(pow(abs(j - 50) - 6, 2) + pow(i - 45, 2)) * min((double)1, max((double)0, 46 - i))))) - 2 * min((double)1, max((double)0, 2 - abs(8 - sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2))))) * min(max(i - 50, 0), 1)

드디어 완성!!

영상과는 꽃잎의 회전이 조금 다르지만.. 어쨌든! 성공했다..

으어ㅓㅓㅓ 코드가 너무 길어..!!

 

글을 쓰면서 코드를 적는데 너무 보기도 힘들고 어렵지만.. 다행히 식은 나와있어서.. 다행이였던 것 같다..

내가 혼자 식 만들어서 하라하면.. 절대 못할 듯..

 

어쨌든 추가로 테스트를 더 해봤다.

아래 것 들은 수학을 잘 모르는 상태에서 아무 값이나 이리저리 넣어보면서 테스트 한 것이니.. 뭐라하지 마시길...

 

sqrt(i * j)
tan(i * j)

 

tan(i + j)
20 + 20 * pow((0.5 + 0.5 * cos(5 * atan2(j - (x / 2), i - (y / 2)))), 0.3) - sqrt(pow(j - (x / 2), 2) + pow(i - (y / 2), 2))
cos(i * j)
cos(i + j) * sin(i * j)

내가 테스트로 해본 식들은 그냥 내가 아무거나 식을 적어서 넣어서 출력해본 것이다.

굳이 따지진 말기~

 

근데 진짜 수업시간에 매번 어떻게 쓰는지도 잘 모르는 수학 식으로 수업하는 것보다.. 이렇게 눈으로 그려보면서 수업하는 것도 재밌을 것 같다..

우리 학교는 안해주나...

 

어쨌든 끝입니다!

감사합니다! (2022-05-26 오후 9시 20분 작성완료)

반응형

+ Recent posts