반응형

1. DevOps란 무엇인가?


DevOps란, 개발(Dev) 과 운영(Ops)이 결합해 탄생한 문화 또는 개발 방법론으로 빠른 시간에 사용자의 요구를 반영 할 수 있도록 소프트웨어를 만들고자 하는 목적을 갖고 있다.


2. DevOps 이전의 문제


이전 회사에서 나는 기획으로부터 업무를 부여 받고 개발을 완료하면 테스트를 거치고 배포 전담 팀에서 배포를 진행하는 방식으로 진행하였다. 이와 같은 방식은 문제가 발생했을 때 본인이 아는 범위 밖에서 문제가 발생하게 되면 운영, 개발 팀 간 서로에게 떠넘기는 상황이 발생한다는 것이다.

이를 해결하기 위해 개발과 운영을 단일팀으로 병합하고 빠르고 쉽게 사용자의 요구 사항을 처리할 수 있도록 처리하는 것이 DevOps이다.


3. DevOps 특징


몇 가지 DevOps의 특징을 정리해보면

Cross Functional Team

각 프로세스를 담당하는 사람들을 하나의 팀으로 모으라는 뜻으로 개발, 배포, 테스트 등 하나의 팀에서 처리해야 한다는 특징이다.

Widely Shared Metrics

서비스를 이용하는 사용자의 반응, 서비스의 안정성, 서비스 운영이 잘 돌아가고 있는지 등을 나타내는 하나의 공유된 지표가 필요하다는 것

Automating repetitive tasks

반복적인 수작업을 줄이고 CI/CD를 활용해 자동화된 툴을 이용하는 것을 의미한다.

Post Mortems

시스템 장애가 발생 했을때 팀원들과 소통하며 공유해야 한다.

Teamwork Over Individual Work

팀워크가 중요하며 서로를 존중하되 아이디어에 동의하지 않아야 한다.

또한, 피드백을 주고 받으며 필요 시 도움을 청할 수 있어야 한다.


참고

반응형

'프로그래밍 > TIL' 카테고리의 다른 글

[C#] NICE API 본인인증 소스 및 정리  (2) 2022.11.08
반응형

빙산이 2개 이상의 덩어리로 분리될때의 년도 Count를 구하는 문제이다.

풀이 접근 방법은 먼저

(1) dfs로(bfs로도 적용할 수 있다) 덩어리 Count를 구하는 부분과,

(2) 1년이란 시간이 흘렀을때 빙산의 변화된 모습을 Map[n][m] 에 어떻게 처리할지를 고민했다.

위 두 가지 케이스 처리를 위해 (1), (2) 번을 2덩어리로 분리될때까지 while문으로 감싸서 처리했다.

일단 2덩어리로 분리되는 dfs 풀이는 정말 기본 적인 dfs 재귀함수를 통해 재귀함수가 종료될때

덩어리 Count+1 을 해주었다.

//divCnt : 빙산 덩어리 Count

for(int i=0;i<n;i++) {
    for(int j=0;j<m;j++) {
        if(map[i][j] > 0 && visit[i][j] == 0) {
            flag = true;
            GetDFS(i, j);
            divCnt++;
        }
    }
}

// 분리된 빙산 체크
public static void GetDFS(int x, int y){
    visit[x][y] = 1;

    int[] xx = {-1, 0, 1, 0};
    int[] yy = {0, 1, 0 ,-1};

    for(int i=0;i<4;i++) {
        int ax = x + xx[i];
        int ay = y + yy[i];

        if(ax >= 0 && ay >= 0 && ax<n && ay<m && map[ax][ay] > 0 && visit[ax][ay] == 0 ) {
            GetDFS(ax, ay);
        }
    }
}

빙산의 1년 후 모습은 동,서,남,북 방면의 ‘0’ 개수만큼 melt[n][m] 배열에 +1씩 해주고

실제 빙산 지도에서 melt[n][m] 를 빼주는 방식으로 처리하였다.

// 녹는거 처리
for(int i=0;i<n;i++) {
    for(int j=0;j<m;j++) {
        if(map[i][j] > 0) {
            for(int k=0;k<4;k++) {
                int ax = i + xx[k];
                int ay = j + yy[k];

                if(ax>=0 && ay>=0 && ax<n && ay<m && map[ax][ay] == 0) {
                    melt[i][j]++;
                }
            }
        }
    }
}

for(int i=0;i<n;i++) {
    for(int j=0;j<m;j++) {
        if(melt[i][j] > 0) {                        
            map[i][j] = map[i][j] - melt[i][j] < 0 ? 0 : map[i][j] - melt[i][j];
        }
    }
}

이제

(1) dfs로(bfs로도 적용할 수 있다) 덩어리 Count를 구하기

(2) 1년이란 시간이 흘렀을때 빙산의 변화된 모습을 Map[n][m] 처리

(1), (2) 번을 모두 처리하였으며, 문제에서 주어진

‘만일 전부 다 녹을 때까지 두 덩어리 이상으로 분리되지 않으면 프로그램은 0을 출력한다.’

처리는 flag 변수를 통해 처리했다.

[풀이]

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class BOJ2573 {

    static int n;
    static int m;
    static int[][] map;
    static int[][] visit;
    static int[][] melt; 
    static int year = 0;


    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());

        map = new int[n][m];

        int[] xx = {-1, 0, 1, 0};
        int[] yy = {0, 1, 0, -1};

        // 빙산 입력받기
        for(int i=0; i<n; i++) {
            st = new StringTokenizer(br.readLine(), " ");
            for(int j=0; j<m; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        boolean flag = true;

        while(true) {
            visit = new int[n][m];
            melt = new int[n][m];
            int divCnt = 0;

            // 분리 체크
            flag = false;

            for(int i=0;i<n;i++) {
                for(int j=0;j<m;j++) {
                    if(map[i][j] > 0 && visit[i][j] == 0) {
                        flag = true;
                        GetDFS(i, j);
                        divCnt++;
                    }
                }
            }

            if(divCnt > 1) {
                System.out.println(year);
                return;
            }

            if(!flag) {
                System.out.println(0);
                return;
            };

            // 녹는거 처리
            for(int i=0;i<n;i++) {
                for(int j=0;j<m;j++) {
                    if(map[i][j] > 0) {
                        for(int k=0;k<4;k++) {
                            int ax = i + xx[k];
                            int ay = j + yy[k];

                            if(ax>=0 && ay>=0 && ax<n && ay<m && map[ax][ay] == 0) {
                                melt[i][j]++;
                            }
                        }
                    }
                }
            }

            for(int i=0;i<n;i++) {
                for(int j=0;j<m;j++) {
                    if(melt[i][j] > 0) {                        
                        map[i][j] = map[i][j] - melt[i][j] < 0 ? 0 : map[i][j] - melt[i][j];
                    }
                }
            }

            year++;

        }
    }

    // 분리된 빙산 체크
    public static void GetDFS(int x, int y){
        visit[x][y] = 1;

        int[] xx = {-1, 0, 1, 0};
        int[] yy = {0, 1, 0 ,-1};

        for(int i=0;i<4;i++) {
            int ax = x + xx[i];
            int ay = y + yy[i];

            if(ax >= 0 && ay >= 0 && ax<n && ay<m && map[ax][ay] > 0 && visit[ax][ay] == 0 ) {
                GetDFS(ax, ay);
            }
        }
    }
}
반응형
반응형

움직임이 좌,우,상,하 가 아닌 나이트의 이동을 가진 살짝 이동경로만 변형된 기본적인 BFS 문제입니다.

체스 나이트의 움직임은 위 그림과 같이 움직일 수 있습니다.

기존 좌,우,상,하 움직이는 BFS 문제는

int[4] x = {-1,0,1,0} // x축 기준: 좌, 상, 우, 하
int[4] y = {0,1,0,-1} // y축 기준: 좌, 상, 우, 하
 

처럼 움직인 반면 나이트의 움직임은 배열로 아래 그림 번호 순대로 선언 할 수 있습니다.

int[8] x = {-1, 1, 2, 2, 1, -1, -2, -2}
int[8] y = {2, 2, 1, -1, -2, -2, -1, 1}

이제 나이트의 이동 순서를 알고 있으므로, 기본 BFS 문제와 동일하게

Queue 를 선언하여 현재 위치, 그리고 이동한 위치까지의 움직인 횟 수를 저장하고 반복문을 통해

도착지에 도달하면 도착지까지의 움직임 횟 수를 출력해주면 됩니다.

 

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

class Location7562 {
	int x;
	int y;
	int cnt;
	
	public Location7562(int x, int y, int cnt) {
		// TODO Auto-generated constructor stub
		this.x = x;
		this.y = y;
		this.cnt = cnt;
	}
}

public class BOJ7562 {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Scanner sc = new Scanner(System.in);
		
		int tc = sc.nextInt();
		int[] result = new int[tc];
		int[] xx = {-1, 1, 2, 2, 1, -1, -2, -2};
		int[] yy = {2, 2, 1, -1, -2, -2, -1, 1};
		
		for(int i=0 ;i<tc;i++) {
			int l = sc.nextInt();
			int n = sc.nextInt();
			int m = sc.nextInt();
			int destinationX = sc.nextInt();
			int destinationY = sc.nextInt();
			
			int[][] map = new int[l][l];
			int[][] visit = new int[l][l];
			Queue<Location7562> q = new LinkedList<>();
			
			q.offer(new Location7562(n, m, 0));
			visit[n][m] = 1;
			
			while(!q.isEmpty()) {
				int x = q.peek().x;
				int y = q.peek().y;
				int cnt = q.poll().cnt;
				
				for(int j=0;j<8;j++) {
					int ax = x + xx[j];
					int ay = y + yy[j];
										
					if(ax >= 0 && ay>= 0 && ax< l && ay< l && visit[ax][ay] == 0) {
						if(ax == destinationX && ay == destinationY) {
							result[i] = cnt+1;
							q.clear();
							break;
						}
						
						visit[ax][ay] = 1;
						q.offer(new Location7562(ax, ay, cnt+1));
					}
				}
			}
		}
		
		for(int i=0;i<result.length;i++) {
			System.out.println(result[i]);
		}
	}

}
반응형

'알고리즘 > Baekjoon' 카테고리의 다른 글

[Baekjoon] #6359 만취한 상범  (0) 2024.03.08
[Baekjoon] #2573 빙산  (0) 2022.07.14
[Baekjoon] #2869 달팽이는 올라가고 싶다  (0) 2022.07.04
[Baekjoon] #10872 팩토리얼  (0) 2022.07.03
[Baekjoon] #1520 내리막 길  (0) 2022.06.29
반응형

while문을 통해 처음 문제를 접근하였지만, 기본 수학 문제로 반복문이 아닌 식을 통해 문제를 풀도록 유도 하는 문제이다.

while문 등 아래와 같이 반복문을 통해 풀게 될 경우 문제의 조건인 (1 ≤ B < A ≤ V ≤ 1,000,000,000)

10억이란 숫자로 반복문을 처리하게 되어 시간 초과가 발생한다.


        int cur = 0;
        int days = 1;

        while(true) {
            cur = cur + a;

            if(cur >= v) {
                System.out.println(days);
                return;
            }

            cur = cur -b;
            days++;
        }

즉, 수학적 접근으로 아래와 같은 식을 만들 수 있다.

V(나무 막대 높이) / A(오르는 높이) - B (내려가는 높이)

하지만, 위와 같은 식을 처리할 경우 ‘또, 정상에 올라간 후에는 미끄러지지 않는다.’

를 고려해서 식을 바꿔주어야한다.

여기서 접근한 방식은, 높이에서 - 내려가는 높이를 뺀 후, 하루를 올라야하는지 아니면 정상에 도달했는지를 구하는 방식으로 처리하였다.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class BaekjoonAlgo_2869 {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");

        int a = Integer.parseInt(st.nextToken());
        int b = Integer.parseInt(st.nextToken());
        int v = Integer.parseInt(st.nextToken());


        int days = (v-b) / (a - b);

        if(((v-b) % (a - b)) != 0) {
            days++;
        }

        System.out.println(days);
    }
}
  • 추가적으로 Java11에서는 Scanner로 처리 시 시간초과가 발생하여 BufferedReader로 변경하여 제출하였다.
반응형

'알고리즘 > Baekjoon' 카테고리의 다른 글

[Baekjoon] #2573 빙산  (0) 2022.07.14
[Baekjoon] #7562 나이트의 이동  (0) 2022.07.06
[Baekjoon] #10872 팩토리얼  (0) 2022.07.03
[Baekjoon] #1520 내리막 길  (0) 2022.06.29
[Baekjoon] #11651 좌표 정렬하기2  (0) 2022.06.28
반응형

import java.util.Scanner;

public class Main {

	static int result = 1;
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		
		refact(n);
		
		System.out.println(result);
	}
	
	public static void refact(int x) {
		if(x > 0) {
			result *=x;
			refact(x-1);
		}
	}

}
반응형

+ Recent posts