1. 개요

- Vue, React 는 대표적 Single Page Application(SPA) 프레임워크으로 Client Side Rendering(CSR) 방식으로 View를 만든다.

- PHP 는 Multi Page Application(MPA)으로 Server Side Rendering(SSR)방식으로 View를 만든다.

 

2. SPA, MPA 접속

1) MPA
 -> http://13.124.193.201:8500/a
 -> http://13.124.193.201:8500/b
2) SPA
-> http://13.124.193.201:8200/a
-> http://13.124.193.201:8200/b

 -> 각 service에서 a <-> b 로 page전환 시, browser에 보이는 화면의 차이는 없어보인다.

 -> 하지만 내부 동작은 다르다.

 

3. CSR vs SSR

CSR : Client Side Rendering
Browser(Client)에서 js에 의해 View(HTML)을 동적으로 생산한다. 때문에 page전환이 SSR보다 상대적으로 빠르다. 대신 최초 접속 시, 모든 js(java script)와 static파일(HTML, image)를 가져와야 한다. 때문에 최초 접속시 로딩은 SSR에 비해 늦다.
SSR : Server Side Rendering
Web Server에서 View를 생성한다. page가 전활될 때 마다, client가 server에 View 요청을 하고, server는 그것을 생성한 후 client에게 보내준다. 때문에 View 전환 속도가 CSR에 비해 상대적으로 늦다. 그리고 page 요청이 빈번해 질수록 CSR에 비해 server 부하가 더 커진다.

 

4. Wire Shark

 -> SPA, MPA에서 page 전환 시, 네트워크 요청 & 응답이 어떻게 되는지 살펴보자,

 -> 네트워크 packet를 capture하기 위해 Wire Shark 설치.

 -> 네트워크 아답터를 선택해야 하므로 Capture->Options (이부분 확인안하면 확인불가/ 본인은 Wifi 선택함)

 

 1) MPA접속

  -> a <-> b 페이지 전환시, client/ server 간에 View를 요청/응답하는 packet 생성 확인

  -> server 응답에 View 포함 확인

 

 2) SPA 접속

  -> 최초 접속 시, js 및 static file 다운로드 확인

3. HTTP Packet 분석

 

- 도커란

 -> 리눅스에서 제공하는 컨테이너를 이용하여 애플리케이션을 묶어서 실행, 배포 할 수 있게 해주는 오픈소스SW

 -> 개발, 테스트, 서비스 서버 등의 다양한 환경을 쉽게 관리 할 수 있게 해줌

 

- 도커의 장점

 -> 기존 가상 머신에 비해 성능 오버헤드가 적음

 -> 빠르고 쉬운 애플리케이션 배포

 -> 이미지 버젼 관리 쉬움

 -> 각 컨테이너 사이에 독립적인 동작 환경 제공

 

- 기존 방식(가상 머신)

 -> OS를 가상 머신마다 중복으로 설치하기 때문에 이미지 크기가 커짐

 -> 이미지가 커서 네트워크로 배포하는 것이 어려움

 -> 배포 및 버전 관리가 어려움

    => OS를 포함하고 있어 용량이 크기때문에 네트워크를 통해 배포하기가 어려움

    => 이미지의 버전관리 즉 변경사힝 추적이 거의 불가능

 -> 가상 머신은 OS안에 OS를 포함하여 가상화하여 매우 느리고 비효율적임

 

- 컨테이너(위의 문제를 해결)

 -> OS를 중복으로 설치하지 않아 이미지 크기가 작고 배포에 용이

 -> OS를 가상화하지 않고 직접 호스트의 OS 자원을 사용하기 때문에 가상머신에 비해 월등히 빠름

 

- 이미지와 컨테이너

 -> 서버 구성에 필요한 파일들을 묶어 놓은 것

 -> 실행 파일, 라이브러리, 설정 파일 등을 포함

 -> 배포의 단위로 저장소에 올리고 받을 수 있음(push/pull)

 -> 컨테이너는 이미지를 실행한 형태

 -> 실행파일과(이미지) 프로세스(컨테이너)의 관계

 

 

- 도커 설치(Window)

https://www.docker.com/products/docker-desktop

 

Docker Desktop for Mac and Windows | Docker

Learn why Docker Desktop is the preferred choice for millions of developers building containerized applications. Download for Mac or Windows.

www.docker.com

 

 -> 도커 데스크탑 설치 오류(WSL2) 발생시

 

WSL 2 installation is incomplete, 윈도우10 도커 설치시 리눅스 커널 업데이트, Docker Linux Kernel Update on Windows 10

1. 파워쉘 관리자권한으로 실행

2. 리눅스 서브시스템 활성 명령어 입력

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

3. 가상 머신 플랫폼 기능 활성화 명령어 입력

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

4. x64 머신용 최신 WSL2 Linux 커널 업데이트 패키지 다운로드, 설치

wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

5. Docker Desktop - Restart

-> 재시작 없어도 윈도우 재부팅하기

 

- 도커 개발환경 설정

- 도커 버전 확인
docker -v

- 테스트용 Hello world 도커 컨테이너 실행
docker run hello-world
// "Hello from Docker!" 메시지 출력되면 성공
// 도커 이미지만 다운로드시 
docker pull hello-world

 

- 도커 기본 명령어 실습

- 컨테이너 조회
docker ps -a
// -a 옵션은 실행 종료된 컨테이너까지 조회

- Hello world 컨테이너 삭제
docker rm [컨테이너 ID 또는 NAME]

- 도커 이미지 조회
docker images

- Hello world 도커 이미지 삭제
docker rmi [이미지 ID 또는 이미지명:TAG 명]
//latest태그명은 생략 가능

 

//프로젝트 코드 다운로드 git clone

 

- FE 도커이미지 제작(영화프로젝트 - Vue.js)

1. 로컬에서 FE 실행 및 웹 브라우저로 접속(http://localhost:8080) 확인

yarn install
yarn serve

 

2. Dockerfile 작성

# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
RUN npm run build

# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

3. 도커 이미지 빌드

docker build -t vue-app .
// . -> Dockfile 위치

//실행 이미지 확인
docker images

//docker container 실행
docker run -it -p 8080:80 --rm --name vue-app-1 vue-app

//실행된 컨테이너 확인
docker ps

//docker container 정지
docker stop vue-app-1

- 이미지 TAG 추가/ 삭제

docker tag front:0.1 front:latest

docker rmi front
Untagged: front:latest

 

- BE 도커 이미지 제작(data visualization - Node.js)

1. Dockerfile 생성

FROM node:12-alpine
WORKDIR /app 
COPY package*.json /app
RUN npm install
COPY . /app
CMD [ "npx", "nodemon", "serve" ]
EXPOSE 8080

1. Docker Hub에 있는 node:12-alpine 이미지 사용
2. 이미지 안에 애플리케이션 코드를 넣기 위한 디렉터리 생성. 애플리케이션의 작업 dir가 된다
3. node:12 이미지에 node.js와 npm은 설치되어 있으므로 npm바이너리로 앱 의존성만 설치
4. npm 설치 (RUN은 새로운 레이어 위에서 명령어를 실행 주로 패키지 설치용)
5. Docker 이미지 안에 앱의 소스코드를 넣기 위함
6. CMD는 도커가 실행될때 실행되는 명령어를 정의
7. 8080번 포트로 실행

2. .dockerignore파일 생성

-> Docker image의 파일 시스템의 node_modules 디렉토리가 현재 로컬작업 디렉토리의 node_modules 디렉토리로 덮어지지 않도록 하기 위함.

node_modules
npm-debug.log

3. 도커 이미지 빌드

docker bulid -t node-docker-test .

docker images

docker run -it -p 5000:8080 --rm --name node-docker-test-1 node-docker-test
//host포트 5000로 들어온는 트래픽을 container의 포트 8080으로 포워딩

docker ps

docker stop node-docker-test-1

 

docker ps                   // 실행중인 컨테이너 조회
docker ps -a                // 중지중인 컨테이너까지 모두 조회
docker images               // 이미지 조회
docker rm 컨테이너ID        // 컨테이너 삭제, 중지된 것만 삭제가능
docker stop 컨테이너ID      // 컨테이너 중지
docker rmi 이미지명         // 이미지 삭제

docker start 컨테이너ID     // 컨테이너 시작
docker restart 컨테이너ID   // 컨테이너 재부팅

docker attatch 컨테이너ID   // 실행 중인 컨테이너에 접속

- 최종 실행 확인 (data visualization PJT - Vue.js/ Node.js)

docker build -t node-docker-test .

docker run -it -p 8080:8080 --rm --name node-docker-test-1 node-docker-test

docker stop node-docker-test-1
docker build -t vue-docker-test .

docker run -it -p 8081:80 --rm --name vue-docker-test-1 vue-docker-test

docker stop vue-docker-test-1

https://programmers.co.kr/learn/courses/30/lessons/42578

 

코딩테스트 연습 - 위장

 

programmers.co.kr

#include <string>
#include <vector>
#include <iostream>
#include <map>

using namespace std;

int solution(vector<vector<string>> clothes) {
    
    int answer = 1;

    map <string, int> myclothes;
    
    for (int i = 0; i < clothes.size(); i++) {
        myclothes[clothes[i][1]] += 1;
    }

    for (auto item : myclothes) {
        answer *= (item.second + 1);
    }

    return answer - 1;
}

https://programmers.co.kr/learn/courses/30/lessons/62048

 

코딩테스트 연습 - 멀쩡한 사각형

가로 길이가 Wcm, 세로 길이가 Hcm인 직사각형 종이가 있습니다. 종이에는 가로, 세로 방향과 평행하게 격자 형태로 선이 그어져 있으며, 모든 격자칸은 1cm x 1cm 크기입니다. 이 종이를 격자 선을

programmers.co.kr

 

 

- 직사각형의 대각선이 가로지르는 사각형들은 일정한 패턴이 반복된다.

이 패턴이 반복되는 횟수가 가로 세로의  GCD

  -> GCD(12, 8) = 4

- 이 패턴의 가로 세로 길이가 각각 w / gcd, h / gcd 이다.

  -> 8 / 4 = 2, 12 / 4 = 3

- 대각선이 지나는 칸은 한줄에 1칸 ~ 2칸 존재할 수 있다.

- 대각선이므로 세로줄기준 최소 1칸은 차지할수 밖에 없다.

  -> h / gcd = 12 / 4 = 3

- 하지만 가로줄기준 2칸을 차지하는 경우는 w/gcd -1 이다.

  -> w / gcd - 1 = 8 / 4 -1 = 2 - 1 = 1

 

=> 최종식

- w * h - [ { ( w / gcd ) + ( h / gcd ) - 1 } * gcd ]

- w * h - ( w + h - gcd )

 

 

 

 

 

- GCD구현하기 (유클리드호제법)

        long long a=W, b=H, c;
        
        while (b != 0) {
            c = a % b;
            a = b;
            b = c;        }

        long long gcd = a;

 

- 제출코드 (가로, 세로가 int로 주어지기때문에 계산시 형변환 해주거나 변수 재설정)

#include <string>
#include <vector>
#include <iostream>

using namespace std;

long long solution(int w, int h) {
    long long answer;

    long long W = w;
    long long H = h;

    if (w == h) {
        answer = (W * H) - W;
    }

    else {
        long long a=W, b=H, c;
        
        while (b != 0) {
            c = a % b;
            a = b;
            b = c;
        }

        long long gcd = a;

        answer = (W * H) - (((W / gcd) + (H / gcd) - 1) * gcd);
    }


    return answer;
}

int main() {
    cout << solution(8, 12);//80
	
    return 0;
}

 

https://programmers.co.kr/learn/courses/30/lessons/17678

 

코딩테스트 연습 - [1차] 셔틀버스

10 60 45 ["23:59","23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59"] "18:00"

programmers.co.kr

- TC 18번 미통과

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

using namespace std;

string solution(int n, int t, int m, vector<string> timetable) {
	string answer = "";

	//1. 시간대별 대기인원의 수 확인 필요없고
	//2. 마지막 탑승차량에 탈건데 제일 늦게나올려면 몇시에 나와야하나
	//3. 막차 이전까지의 탑승객 제외
	//4. 막차 이후 탑승객 제외
	//5. 진짜 막차 기다리는 사람들만 비교

	sort(timetable.begin(), timetable.end());

	//stirng 시간 int 분단위로 변경 vector 저장
	vector<int>people;
	for (int i = 0; i < timetable.size(); i++) {
		timetable[i].erase(2, 1);
		int hour = stoi(timetable[i].substr(0, 2)) * 60;
		int minute = stoi(timetable[i].substr(2, 2));
		int num = hour + minute;
		people.push_back(num);
	}

	// 막차전에 보낼사람 먼저 보내기
	for (int i = 0; i < n - 1; i++) {
		int time = 9 * 60;
		time = time + (t * i);

		int cnt = 0;
		while (1) {
			if (cnt == m) break;
			if (people[0] <= time) {
				people.erase(people.begin());
				cnt++;
			}
			else break;
		}
	}

	// 막차시간
	int lastTime = (9 * 60) + (t * (n - 1));

	// 막차후에 사람들 버리기
	for (int i = 0; i < people.size(); i++) {
		if (people[i] > lastTime)
			people.erase(people.begin() + i);
	}

	// 막차대기인원
	int lastPeople = people.size();
	
	int result;
	// 막차대기인원이 수용가능인원보다 적다면 막차시간에 나오면 됨
	if (lastPeople < m)result = lastTime;

	// 막차대기인원이 수용가능인원보다 많다면 수용가능인원의 마지막 대기순서보다 1분 빨리나오기
	else result = people[m-1] - 1;
	
	int hour = result / 60;
	int minute = result % 60;
	if (hour < 10) answer += "0";
	answer += to_string(hour);
	
	answer += ':';

	if (minute < 10)answer += "0";
	answer += to_string(minute);

	return answer;
}


int main() {
	//cout << solution(1, 1, 5, { "08:00", "08:01", "08:02", "08:03" }) << endl;//	"09:00"
	//cout << solution(2, 10, 2, { "09:10", "09:09", "08:00" }) << endl;//	"09:09"
	//cout << solution(2, 1, 2, { "09:00", "09:00", "09:00", "09:00" }) << endl;//	"08:59"
	//cout << solution(1, 1, 5, { "00:01", "00:01", "00:01", "00:01", "00:01" }) << endl;//	"00:00"
	//cout << solution(1, 1, 1, { "23:59" }) << endl;//	"09:00"
	//cout << solution(10, 60, 45, { "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59", "23:59" });//	"18:00"
	//cout << solution(2, 10, 3, { "09:05", "09:09", "09:13" });// "09:10"
	cout << solution(1, 1, 5, { "00:01", "00:01", "00:01", "00:01", "00:01", "00:02", "00:03", "00:04" }); /// "00:00"
	return 0;
}

https://programmers.co.kr/learn/courses/30/lessons/49191

 

코딩테스트 연습 - 순위

5 [[4, 3], [4, 2], [3, 2], [1, 2], [2, 5]] 2

programmers.co.kr

#include <string>
#include <vector>
#include <iostream>

using namespace std;

int solution(int n, vector<vector<int>> results) {
    int answer = 0;

    int arr[101][101] = { 0 };

    for (int i = 0; i < results.size(); i++)
        arr[results[i][0]][results[i][1]] = 1;

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            for (int k = 1; k <= n; k++) {
                if (arr[i][k] == 1 && arr[j][i])
                    arr[j][k] = 1;
            }
        }
    }

    for (int i = 1; i <= n; i++) {
        int cnt = 0;
        for (int j = 1; j <= n; j++) {
            if (arr[i][j]==1 || arr[j][i]==1) cnt++;
        }
        if (cnt == n - 1) 
            answer++;
    }
    return answer;
}

int main() {
    //cout << solution(5, { {4, 3},{4, 2},{3, 2},{1, 2},{2, 5} });
    cout << solution(5, { {1, 2},{4, 5},{3, 4},{2, 3} }); // 5
	
    return 0;
}

https://programmers.co.kr/learn/courses/30/lessons/17677

 

코딩테스트 연습 - [1차] 뉴스 클러스터링

뉴스 클러스터링 여러 언론사에서 쏟아지는 뉴스, 특히 속보성 뉴스를 보면 비슷비슷한 제목의 기사가 많아 정작 필요한 기사를 찾기가 어렵다. Daum 뉴스의 개발 업무를 맡게 된 신입사원 튜브

programmers.co.kr

 

- 교집합 카운팅 후 삭제히여 교집합+남은갯수=합집합 확인하기

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

using namespace std;

int solution(string str1, string str2) {
	int answer = 0;

	vector<string>vec1;
	vector<string>vec2;

	int a = -1;
	while (1) {
		a++;
		if (a == str1.size() - 1) break;
		string tmp1 = str1.substr(a, 2);

		if (tmp1[0] >= 'a' && tmp1[0] <= 'z')
			tmp1[0] += 'A' - 'a';

		if (tmp1[1] >= 'a' && tmp1[1] <= 'z')
			tmp1[1] += 'A' - 'a';

		if (tmp1[0] < 'A' || tmp1[1] < 'A' || tmp1[0]>'Z' || tmp1[1]>'Z' || tmp1[0] == ' ' || tmp1[1] == ' ')
			continue;

		vec1.push_back(tmp1);
	}

	a = -1;
	while (1) {
		a++;
		if (a == str2.size() - 1) break;
		string tmp2 = str2.substr(a, 2);
		if (tmp2[0] >= 'a' && tmp2[0] <= 'z')
			tmp2[0] += 'A' - 'a';
		
		if (tmp2[1] >= 'a' && tmp2[1] <= 'z')
			tmp2[1] += 'A' - 'a';

		if (tmp2[0] < 'A' || tmp2[1] < 'A' || tmp2[0]>'Z' || tmp2[1]>'Z' || tmp2[0] == ' ' || tmp2[1] == ' ')
			continue;
		
		vec2.push_back(tmp2);
	}


	if (vec1.empty() && vec2.empty()) 
		return answer = 65536;

	int A = 0, B = 0;

	for (int i = 0; i < vec1.size(); i++) {
		for (int j = 0; j < vec2.size(); j++) {
			if (vec1[i] == vec2[j]) {
				A++;
				vec1.erase(vec1.begin() + i);
				vec2.erase(vec2.begin() + j);
				i--;
				break;
			}
		}
	}
	
	B = vec1.size() + vec2.size() + A;
	
	float tmp = float(A) / float(B);
	answer = tmp * 65536;
	return answer;
}

int main() {
	cout << solution("aa1 + aa2", "AA12") << endl;//	32768
	cout << solution("FRANCE", "french") << endl;//	16384
	cout << solution("handshake", "shake hands") << endl;//	65536
	cout << solution("aa1 + aa2", "AAAA12") << endl;//	43690
	cout << solution("E = M * C ^ 2", "e = m * c ^ 2");//	65536
	return 0;
}

https://programmers.co.kr/learn/courses/30/lessons/1836

 

코딩테스트 연습 - 리틀 프렌즈 사천성

리틀 프렌즈 사천성 언제나 맛있는 음식들이 가득한 평화로운 푸드 타운. 푸드 타운에서 행복하게 사는 리틀 프렌즈들은 마을에 있는 매직 스푼을 보물처럼 보관하고 있다. 매직 스푼은 재료만

programmers.co.kr

- TC 4개는 통과/ 제출실패

#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>

using namespace std;

struct node {
    int y, x, bang, le;
};

string solution(int m, int n, vector<string> board) {
    string answer = "";

    int direct[4][2] = {
        -1,0,
        1,0,
        0,-1,
        0,1
    };

    vector<vector<char>>Check(10);
    
    //map<char, pair<int,int>>map;
    vector<vector<pair<int, int>>>pairVec(100);

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            char target = board[i][j];
            pairVec[target].push_back(make_pair(i, j));
        }
    }

    int sun = 0;
    while (1) {
        bool exist = false;
        for (int i = 'A'; i <= 'Z'; i++) {
            if (pairVec[i].size() == 2) {
                char target = i;
                int sty = pairVec[i][0].first;
                int stx = pairVec[i][0].second;
                int endy = pairVec[i][1].first;
                int endx = pairVec[i][1].second;

                queue<node>q;
                int used[100][100] = { 0 };
                q.push({ sty, stx,-1,0 });
                used[sty][stx] = 1;

                int flag = 0;
                while (!q.empty()) {
                    if (flag == 1) break;

                    node now = q.front();
                    q.pop();

                    for (int x = 0; x < 4; x++) {
                        int dy = now.y + direct[x][0];
                        int dx = now.x + direct[x][1];
                        if (dy < 0 || dx < 0 || dy >= m || dx >= n) continue;
                        if (used[dy][dx] == 1) continue;
                        if (board[dy][dx] != '.' && board[dy][dx] != target) continue;

                        if (now.bang != x) {
                            if (now.le + 1 > 2) break;
                            else q.push({ dy, dx, x, now.le + 1 });
                        }
                        else if (now.bang == x) q.push({ dy, dx, x, now.le });

                        used[dy][dx] = 1;

                        if (dy == endy && dx == endx) {
                            exist = true;
                            Check[sun].push_back(i);
                            board[sty][stx] = board[endy][endx] = '.';
                            pairVec[i].clear();
                            flag = 1;
                            break;
                        }
                    }
                }
            }
        }
        sun++;
        if (!exist) break;
    }

    if (Check[0].empty()) 
        answer = "IMPOSSIBLE";

    for (int i = 0; i < Check.size(); i++) {
        if (Check[i].empty()) break;
        sort(Check[i].begin(), Check[i].end());
        for (int j = 0; j < Check[i].size(); j++)
            answer += Check[i][j];
    }

    return answer;
}

 

- A-Z탐색 반복 X, A부터 탐색하다가 짝이 맞았을때 다시 A부터 재탐색

#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>

using namespace std;

struct node {
    int y, x, bang;
};

string solution(int m, int n, vector<string> board) {
    string answer = "";

    int direct[4][2] = {
        -1,0,
        1,0,
        0,-1,
        0,1
    };
	    
    //map<char, pair<int,int>>map;
    map<char, node > pairVec;

	//알파벳별 시작위치만 저장 (도착지 bfs탐색)
    for (int i = 0; i < m; i++) { 
        for (int j = 0; j < n; j++) {
            char target = board[i][j];
            if(target>='A' && target<='Z')
				pairVec[target] = { i, j };
		}
	}

	int sun = 0;
	while (1) {
		bool exist = false;
		for (int i = 'A'; i <= 'Z';i++) {
			if (pairVec.count(i) <= 0) continue;
			char target = i;
			int sty = pairVec[i].y;
			int stx = pairVec[i].x;

			queue<node>q;
			vector<vector<int>> turnCheck(m, vector<int>(n, 999)); // 꺾은 횟수 저장

			q.push({ sty, stx, -1 });
			turnCheck[sty][stx] = 0;

			int flag = 0;
			while (!q.empty()) {

				node now = q.front();
				q.pop();

				if (flag == 1 && board[now.y][now.x] == target) {
					exist = true;
					answer += target;
					board[sty][stx] = board[now.y][now.x] = '.';
					pairVec.erase(target);
					i = 'A'-1;
					break;
				}

				flag = 1;

				for (int x = 0; x < 4; x++) {
					int dy = now.y + direct[x][0];
					int dx = now.x + direct[x][1];
					int cnt = turnCheck[now.y][now.x];

					if (now.bang != -1 && now.bang != x)
						cnt++;

					if (dy < 0 || dx < 0 || dy >= m || dx >= n) continue;
					//if (used[dy][dx] == 1) continue;
					if (board[dy][dx] != '.' && board[dy][dx] != target) continue;

					if (cnt >= 2) continue;

					if (turnCheck[dy][dx] >= cnt) {
						q.push({ dy,dx,x });
						turnCheck[dy][dx] = cnt;
					}
				}
			}
		}
		if (exist) continue;

		if (!pairVec.empty())
			answer = "IMPOSSIBLE";

		return answer;
	}
}

int main() {
	cout << solution(5, 5, { "FGHEI", "BAB..", "D.C*.", "CA..I", "DFHGE" }) << '\n'; //ABCDFHGIE
    //cout << solution(2, 4, { "NRYN", "ARYA" }) << '\n'; //RYAN
    //cout << solution(2, 2, { "AB", "BA" }) << '\n';
    //cout << solution(2, 2, { "ZA", "ZA" }) << '\n'; //"AZ"
    //cout << solution(1, 2, { "AA" }) << '\n'; // "A"
	return 0;
}

+ Recent posts