728x90

백준 16956번 늑대와 양


내가 떠올린 풀이 해설

처음 이 문제를 봤을 때 늑대 기준으로 탐색을 하려고 했다. 문제를 해결하려고 했으나 답이 나오지 않아 블로그를 참고했다. 블로그 풀이는

늑대랑 양이랑 한 칸 떨어져 있으면 울타리로 감싸면 됨, 울타리 갯수 제한 없음, 늑대랑 양이랑 바로 옆만 아니면 양은 무조건 지킬 수 있음을 떠올려서 늑대 주변에 울타리만 감싸주었다. 예제 출력이랑 다르게 나오는데 정답이 나왔다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek16956 {
	static int []dx = {1, 0, -1, 0};
	static int []dy = {0, -1, 0, 1};
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		char[][]arr = new char[n][m];
		boolean flag = true;
		
		for(int i = 0; i < n; i++) {
			String tmp = br.readLine();
			for(int j = 0 ; j < m; j++) {
				arr[i][j] = tmp.charAt(j);
			}
		}
		for(int i = 0 ; i < n; i++) {
			for(int j = 0; j < m; j++) {
				if(arr[i][j] == 'W') {
					for(int r = 0; r < 4; r++) {
						int nx = i + dx[r];
						int ny = j + dy[r];
						
						if(nx >= 0 && nx < n && ny >= 0 && ny < m) {
							if(arr[nx][ny] == '.') {
								arr[nx][ny] = 'D';
							}
							else if(arr[nx][ny] ==  'S') {
								flag = false;
								System.out.println(0);
								return;
							}
						}
					}
				}
			}
		}
		if(!flag) {
			System.out.println(0);
		}
		else {
			StringBuilder sb = new StringBuilder();
			System.out.println(1);
			for(int i = 0 ; i < n; i++) {
				sb.append(arr[i]);
				sb.append("\\n");
			}
			System.out.println(sb);
		}
	}
}

백준 1152 단어의 개수


내가 떠올린 풀이 해설

String으로 받아서 StringTokenizer로 공백 기준으로 자르고 StringTokenizer의 개수를 세는 countTokens로 출력해주면 된다.


정확한 풀이

import java.io.*;
import java.util.*;

public class Baek1152 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		String str = br.readLine();
		
		StringTokenizer st = new StringTokenizer(str);
		System.out.println(st.countTokens());

	}
}

백준 1764번 듣보잡


내가 떠올린 풀이 해설

HashSet을 이용해 N번 까지 HashSet에 넣고 정답을 출력하는 ArrayList을 만들고 br.readLine을 담을 수 있는 String tmp 변수를 만들어서 contains으로 HashSet에 tmp가 있으면 ArrayList에 add 하는 방식으로 풀었다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek1764 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		HashSet<String> set = new HashSet<>();
		for(int i = 0; i < n; i++) {
			set.add(br.readLine());
		}
		
		ArrayList<String> answer = new ArrayList<>();
		for(int i = 0; i < m; i++) {
			String tmp = br.readLine();
			if(set.contains(tmp)) {
				answer.add(tmp);
			}
		}
		Collections.sort(answer);
		System.out.println(answer.size());
		for(int i = 0; i < answer.size(); i++) {
			System.out.println(answer.get(i));
		}
	}
}

오늘의 회고

오늘은 문자열과 그래프 문제를 풀었습니다. 쉬운 문제들로 풀려고 했는데 늑대와 양 문제에서 막혔습니다. 3주째 알고리즘을 풀고 있는데 꾸준히 문제를 풀고 있어서 진도에서는 만족을 하는데 실력에서는 아직 불만족입니다. 꾸준히 공부하면 실력도 성장할 것이라 믿고 지치지 않고 꾸준히 알고리즘을 풀어나가겠습니다.

 

참고 블로그

https://go-coding.tistory.com/77

728x90
728x90

36번 잃어버린 괄호


내가 떠올린 풀이 해설

가장 작은 최솟값을 만들기 위해서는 가능한 큰 수를 빼야 된다. 수식이 더하기 빼기로만 되어있기 때문에 더하기 부분에 괄호를 쳐서 먼저 모두 계산한 후 빼기를 실행한다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek1541 {
	static int answer = 0;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		String st = br.readLine();
		String []str = st.split("-");
		
		for(int i = 0; i < str.length; i++) {
			int tmp = mySum(str[i]);
			if(i == 0) {
				answer = answer + tmp;
			}
			else {
				answer = answer - tmp;
			}
		}
		System.out.println(answer);
	}
	private static int mySum(String a) {
		int sum = 0;
		String temp[] = a.split("[+]");
		for(int i = 0; i < temp.length; i++) {
			sum += Integer.parseInt(temp[i]);
		}
		return sum;
	}
}

46번 특정 거리의 도시 찾기


내가 떠올린 풀이 해설

모든 도로 거리가 1이므로 가중치 없는 인접리스트로 표현할 수 있다. 도시의 개수가 300,000, 도로의 최대 크기가 1,000,000이므로 BFS 탐색으로 해결할 수 있다. 최초에는 방문 도시가 1이고, 이동하지 않았으므로 방문 배열에 0을 저장한다. 이후 방문하는 도시는 이전 도시의 방문 배열 값 +1을 방문 배열에 저장한다. 탐색 종료 후 방문 배열에 값이 k와 같은 도시의 번호를 출력한다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek18352 {
	static int [] visit;
	static ArrayList<Integer>[] list;
	static List<Integer> answer;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(st.nextToken());
		int x = Integer.parseInt(st.nextToken());
		
		list = new ArrayList[n + 1];
		visit = new int[n + 1];
		answer = new ArrayList<>();
		
		for(int i = 1; i <= n; i++) {
			list[i] = new ArrayList<>();
		}
		
		for(int i = 0; i < m; i++) {
			st = new StringTokenizer(br.readLine());
			int s = Integer.parseInt(st.nextToken());
			int e = Integer.parseInt(st.nextToken());
			list[s].add(e);
		}
		for(int i = 1; i <= n; i++) {
			visit[i] = -1;
		}
		BFS(x);
		for(int i = 1; i <= n; i++) {
			if(visit[i] == k) {
				answer.add(i);
			}
		}
		if(answer.isEmpty()) {
			System.out.println(-1);
		}
		else {
			Collections.sort(answer);
			for(int b : answer) {
				System.out.println(b);
			}
		}
	}
	private static void BFS(int x) {
		Queue<Integer> que = new LinkedList<>();
		que.add(x);
		visit[x]++;
		while(!que.isEmpty()) {
			int now = que.poll();
			for(int i : list[now]) {
				if(visit[i] == -1) {
					visit[i] = visit[now] + 1;
					que.add(i);
				}
				
			}
		}
		
	}
}

47번 효율적인 해킹


내가 떠올린 풀이 해설

모든 노드를 각각 BFS 탐색 알고리즘을 적용해 탐색한다. 탐색을 수행하면서 탐색되는 노드들의 신뢰도를 증가시켜 준다. 탐색 종료후 신뢰도 배열을 탐색해 신뢰도의 최댓값을 Max값으로 지정하고, 신뢰도 배열을 다시 탐색하면서 Max값을 가진 노드를 오름차순으로 출력한다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek1325 {
	static int []answer;
	static ArrayList<Integer>[] list;
	static boolean []visit;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		list = new ArrayList[n + 1];
		visit = new boolean[n + 1];
		answer = new int [n + 1];
		for(int i = 1; i <= n; i++) {
			list[i] = new ArrayList<>();
		}
		
		for (int i = 0; i < m; i++) {
			st = new StringTokenizer(br.readLine());
			int s = Integer.parseInt(st.nextToken());
			int e = Integer.parseInt(st.nextToken());
			list[s].add(e);
		}
		for(int i = 1; i <= n; i++) {
			visit = new boolean[n + 1];
			BFS(i);
		}
		int max = 0;
		for(int i = 1; i <= n; i++) {
			max = Math.max(max, answer[i]);
		}
		for(int i = 1; i <= n; i++) {
			if(answer[i] == max) {
				System.out.print(i + " ");
			}
		}
 	}
	private static void BFS(int i) {
		Queue<Integer> que = new LinkedList<>();
		que.add(i);
		visit[i] = true;
		while(!que.isEmpty()) {
			int now = que.poll();
			for(int b : list[now]) {
				if(visit[b] == false) {
					visit[b] = true;
					answer[b]++;
					que.add(b);
				}
			}
 		}
	}
}

잘못된 풀이

import java.io.*;
import java.util.*;
public class Main {
	static int n, m;
	static ArrayList<Integer>[] list;
	static int []answer;
	static boolean []visit;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		n = Integer.parseInt(st.nextToken());
		m = Integer.parseInt(st.nextToken());
		
		list = new ArrayList[n + 1];
		answer = new int[n + 1];
		for(int i = 1; i <= n; i++) {
			list[i] = new ArrayList<>();
		}
		for(int i = 0; i < m; i++) {
			st = new StringTokenizer(br.readLine());
			int x = Integer.parseInt(st.nextToken());
			int y = Integer.parseInt(st.nextToken());
			list[x].add(y);
		}
		
		for(int i = 1; i <= n; i++) {
			visit = new boolean[n + 1];
			BFS(i);
		}
		int max = 0;
		for(int i = 1; i <= n; i++) {
			max = Math.max(max, answer[i]);
		}
		for(int i = 1; i <= n; i++) {
			if(answer[i] == max) {
				bw.write(i + " ");
			}
		}
		bw.flush();
		bw.close();
	}
	private static void BFS(int i) {
		Queue<Integer> que = new LinkedList<>();
		que.add(i);
		visit[i] = true;
		while(!que.isEmpty()) {
			int now = que.poll();
			for(int b : list[now]) {
				if(visit[b] == false) {
					answer[b]++;
					que.add(b);
				}
				
			}
		}
	}
}


문제점

이 문제에서 진짜 많이 해멧다 계속 시간 초과가 나는 것이었다. 정답이 된 코드와 잘못된 코드와 다른 게 없는데 계속 시간 초과가 났다. 문제를 모르겠다. 뒤에 정답 된 코드를 제출했더니 정답이 나왔다...

 

오늘의 회고

오늘은 그리디와 그래프 문제를 풀어봤습니다. 그래프 문제는 앞에서 배웠던 DFS, BFS를 활용해서 해결하는 문제였다. 앞에서 배웠지만 직접 구현하기에는 힘든 점이 있었습니다. 이번 주말 일요일에는 다른 공부 하지 않고 알고리즘만 복습하는 시간을 가지겠습니다. 알고리즘 공부를 시작한 지 얼마 안 되었기 때문에 지치지 않고 좌절하지 않고 풀어내는 힘을 길어내는 게 중요한 것 같습니다. 요행을 바라지 말고 정직하게 공부하자.

728x90
728x90

오늘은 스프링 부트에서 MyBatis 연결을 하려고 합니다. 

1-2 스프링 부트 MyBatis 연결

1. 스프링 부트 MyBatis 설정

implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'
runtimeOnly 'mysql:mysql-connector-java'

build.gradle dependencies에 위의 코드를 추가시켜줍니다. 

# database
spring.datasource.url: jdbc:mysql://host:3306/DatabaseName?characterEncoding=utf8
spring.datasource.username: DatabaseName
spring.datasource.password: password
spring.datasource.driver-class-name: com.mysql.cj.jdbc.Driver

# mybatis
mybatis.config=mybatis-config.xml
mybatis.type-aliases-package: com.example.demo.model
mybatis.mapper-locations: mapper/*.xml

application.properties에 위에 코드를 추가 시켜줍니다. url에는 자신의 포트번호와 데이터베이스 이름을 입력해주고, 유저네임과 패스워드도 자신과 맞게 입력해줍니다. mapper-locations도 mapper. xml이 있는 파일로 설정해주면 끝입니다.


2. DataBase연결 Test

이제 DataBase연결이 잘 되었는지 Test를 해보려고 합니다. Test에 dbTest페키지를 만들고 MyBatisTest class파일을 만들어 줍니다.

package com.skylife_Transformation.dbTest;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.DriverManager;

public class MyBatisTest {
    // MySQL Connector 의 클래스. DB 연결 드라이버 정의
    private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
    // DB 경로
    private static final String URL = "jdbc:mysql://localhost:port/name?serverTimezone=UTC&allowPublicKeyRetrieval=true&useSSL=false";
    private static final String USER = "name";
    private static final String PASSWORD = "password";

    @Test
    public void testConnection() throws Exception {
        // DBMS에게 DB 연결 드라이버의 위치를 알려주기 위한 메소드
        Class.forName(DRIVER);
        try {
            Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
            System.out.println(connection);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

MyBatisTest파일에 위의 코드를 추가시켜줍니다. DB 커넥션이 제대로 생성되었는지를 출력해 확인해보는 과정입니다.

DB URL에 allowPublicKeyRetrieval은 클라이언트 옵션을 추가 하여 클라이언트가 서버에서 자동으로 공개 키를 요청할 수 있도록 하는 것입니다. default는 false이고 MySQL 8.0 이상은 이를 true로 지정하지 않을 시 public key retrieval is not allowed 에러가 발생할 수 있습니다. 그 뒤에 userSSL은 default는 true이고 false로 지정 시 SSL 사용을 막을 수 있다. 또한 하지만 개발, 혹은 테스트 중에서만 비활성화시키는 걸 추천합니다. 배포 시엔 useSSL를 false로 지정하기보단 SSL을 설정해주면 됩니다.


위의 Test코드를 실행하면 정상적으로 실행되는 것을 확인 할 수 있다. 


참고 블로그

https://doozi0316.tistory.com/entry/Spring-Boot-MyBatis-MySQL-%EC%97%B0%EB%8F%99-%EB%B0%A9%EB%B2%95


오늘의 회고

오늘은 MyBatis연결부터 연결 테스트 까지 진행하였습니다. URL을 입력할 때 allowPublicKeyRetrieval, userSSL은 기존에 사용했었지만 개념과 사용 이유에 대해 몰랐었는데 새롭게 알게 되었습니다. 리펙토링을 진행하다가 빠진 개념 등 다시 정리하면서 가야 될 것 같습니다.

728x90
728x90

32번 동전 0


내가 떠올린 풀이 해설

동전 값이 큰 동전부터 탐색을 하면서 k와 작거나 같은 동전이 나올 때까지 탐색하고 count 값은 k / (동전 값)으로 추가해주고 k % 동전 값으로 k의 값을 바꿔준다. 끝으로 count를 출력한다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek11047 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int n = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(st.nextToken());
		
		int []arr = new int[n];
		for(int i = 0; i < n; i++) {
			arr[i] = Integer.parseInt(br.readLine());
		}
		int div = 0;
		int cnt = 0;
		int max = 0;
		for(int i = n - 1; i >= 0; i--) {
			if(k >= arr[i]) {
				div = arr[i];
				cnt += k / div;
				k = k % div;
			}
		
		}
		System.out.println(cnt);
	}
}

33번 카드 정렬하기


내가 떠올린 풀이 해설

우선순위 큐를 활용해서 풀어야하는 문제이다. 2개의 값을 합해서 비교해야 한다. 문제의 조건대로 연산을 하면 (10+20) + (30 + 40)이다. 앞의 2개를 더한 값을 바로 사용하므로 더한 값을 큐에 계속 넣어줘야 한다. 그냥 큐를 사용하면 30은 맨 뒤로 들어가 곧바로 연산에 수행될 수 없다. 최소한의 비교를 하기 위해서는 낮은 값부터 먼저 더해야 하므로 오름차순으로 정렬된 상태에서 값을 더하기 위해 우선순위 큐를 사용해야 한다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek1715 {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		PriorityQueue<Integer> pq = new PriorityQueue<>();
		
		for(int i = 0; i < n; i++) {
			int data = Integer.parseInt(br.readLine());
			pq.add(data);
		}
		int data1 = 0;
		int data2 = 0;
		int sum = 0;
		
		while(pq.size() != 1) {
			data1 = pq.remove();
			data2 = pq.remove();
			sum += data1 + data2;
			pq.add(data1 + data2);
		}
		System.out.println(sum);
	}
}

34번 수 묶기


내가 떠올린 풀이 해설

가능한 큰 수들 끼리 묶어야 결괏값이 커진다. 또한 음수끼리 곱하면 양수로 되는 성질을 고려해야 된다. 양수 우선순위 큐와 음수 우선순위 큐와 1의 개수 0의 개수를 카운트하는 변수를 만든다. 데이터를 4개 그룹에 분리해 저장 4개 그룹은 1보다 큰 양수, 1의 개수, 0의 개수, 음수이다. while문을 양수 우선순위 큐 크기가 2보다 작을 때까지 반복하는데 수 2개를 큐에서 뽑고 2 개수를 곱한 값을 결괏값에 더한다.

양수 우선순위 큐에 데이터가 남아있으면 이 데이터를 결과값에 더한다. 음수도 위의 양수와 같이 반복한다 만약 음수 우선순위 큐에 데이터가 남아 있고, 데이터 0이 1개도 없으면 이 데이터를 결과 값에 더한다. 마지막으로 숫자 1의 개수를 결괏값에 더함


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek1744 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		PriorityQueue<Integer> plusPq = new PriorityQueue<>(Collections.reverseOrder());
		PriorityQueue<Integer> minusPq = new PriorityQueue<>();
		
		int one = 0;
		int zero = 0;
		
		for(int i = 0; i < n; i++) {
			int data = Integer.parseInt(br.readLine());
			if(data > 1) {
				plusPq.add(data);
			}
			else if(data == 1) {
				one++;
			} 
			else if(data == 0) {
				zero++;
			}
			else {
				minusPq.add(data);
			}
		}
		int sum = 0;
		while(plusPq.size() > 1) {
			int first = plusPq.remove();
			int second = plusPq.remove();
			sum = sum + first * second;
		}
		if(!plusPq.isEmpty()) {
			sum = sum + plusPq.remove();				
		}
		while(minusPq.size() > 1) {
			int first = minusPq.remove();
			int second = minusPq.remove();
			sum = sum + first * second;
		}
		if(!minusPq.isEmpty()) {
			if(zero == 0) {
				sum = sum + minusPq.remove();				
			}
		}
		sum = sum + one;
		System.out.println(sum);
	}
}

35번 회의실 배정


내가 떠올린 풀이

예전에 풀었던 문제와 비슷한 문제여서 어렵지 않게 풀었다. 끝나는 시간으로 정렬을 하고 시작시간으로 정렬을 한다. 끝나는 시간을 기준으로 겹치지 않는 회의실을 선택한다. 


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek1931 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		ArrayList<Meet> list = new ArrayList<>();
		
		for(int i = 0; i < n; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());	
			int x = Integer.parseInt(st.nextToken());
			int y = Integer.parseInt(st.nextToken());
			list.add(new Meet(x, y));
		}
		int cnt = 0;
		Collections.sort(list);
		int et = 0;
		for(Meet b : list) {
			if(b.x > et) {
				cnt++;
				et = b.y;
			}
		}
		System.out.println(cnt);
	}
}
class Meet implements Comparable<Meet> {
	int x;
	int y;
	Meet(int x, int y) {
		this.x = x;
		this.y = y;
	}
	@Override
	public int compareTo(Meet o) {
		if(this.x == o.x) {
			return this.y - o.y;
		}
		return this.x - o.x;
	}
}

오늘의 회고

오늘은 그리디 알고리즘에 배워보는 시간이였습니다. 오늘 문제들도 쉽지 않은 문제들로 구성이 돼있어 힘들었습니다. 알고리즘을 풀면서 고민해도 답을 못 풀 경우에 답을 보고 다시 풀어야 되나 아니면 계속 고민해야 되나 라는 고민이 생기는데 계속 고민해 보는 것이 가장 좋은 방법이라고 생각하는데 저는 시간의 제약 때문에 답을 보고 다시 풀고 복습하고 공부하는 식으로 내 것으로 만들고 있습니다. 아직 풀 수 있는 문제가 많진 않지만 계속해서 공부하겠습니다.

728x90
728x90

header

🎬 Cobye 프로젝트

Cobye 코로나 종식을 희망하며 코로나 감염자 수에 대한 정보를 제공하는 서비스입니다.

프로젝트 기획 중 갑작스러운 코로나 감염자 수 증가로 인한 수도권 거리 두기 4단계가 진행되었습니다.
코로나 장기화와 지속적인 거리 두기로 인해 자영업자, 항공업종사자, 의료인, 의료종사자분 등 많은 피해가
지속되고 아이들은 태어나자마자 영문도 모른 채 마스크를 쓰고 있습니다.
코로나로 인해 더이상 피해입는 사람들이 발생하지 않고 하루빨리 코로나가 종식되길 희망하며 만든 프로젝트입니다.

 


📆 작업 기간

2021.7.21 ~ 2021.7.28 (8일간)

👩‍💻 팀원 구성

박현성, 김다슬, 고정현, 유승준

🎯 기술 스택

Front-end

HTML5 JavaScript Bootstrap jQuery

Back-end

Java Spring

Communication Tools

GitHub Discord Notion

📜 API 사용내역

1. 시도별 통계,성별/연령별 통계 시도별 API

2. 일별, 누적 확진자수 API

3. 선별진료소 카카오 맵 API

4. 예방접종 의료기관 안내 API


📄 기능 구현 사항

1. 메인 페이지(일별/누적 확진자)

  • (1) 실시간, 어제,누적 확진자, 누적 사망자 수
  • (2) 전일대비 확진자 비교(전일대비 증감률)
  • (3) 최근 10일 일별 코로나 확진 현황(그래프)
  • (4) 최근 코로나 누적 확진 현황

2. 지역/성별/연령별 확진자 페이지

  • (1) 성별/연령별 확진자
  • (2) 연령별 확진자 수(그래프)
  • (3) 연령별 확진률, 확진자, 사망률, 사망자(표)
  • (4) 지역별 확진자 수(그래프)
  • (5) 지역별 등록 일시, 전체 확진자, 전일대비, 격리중, 격리 해제 사망자, 지역 발생, 해외 유입(표)

3. 선별진료소 페이지

  • (1) 지도 (현위치, 선별진료소, 임시 선별진료소 정보)
  • (2) 길찾기

4. 예방접종 의료기관

  • (1) 거주지 검색
  • (2) 주변 병원 정보
  • (3) 지도 위치 정보
    5. (BETA)실시간 확진자
  • (1) 실시간 추가 확진자
  • (2) 어제 확진자
  • (3) 실시간 코로나 확진 현황(재난문자)
728x90
728x90

이전에 진행했던 팀 프로젝트 입니다. Git에서 Readme만 가지고 왔습니다.

 

header

🎬 SkyLife 프로젝트

SkyLife는 예매의 편리함과 커뮤니티를 제공하여 정보를 공유할 수 있게 만들어진 항공 예매 플랫폼 서비스입니다.

여행을 즐기는 사람들이 증가하게 되면서 자연스레 항공을 이용하는 빈도 또한 높아지고 있다.
그러나 항공 이용객의 증가 추세에 비하여 항공권 예매 플랫폼 서비스에는 미흡한 부분이 있다.
원하는 시간과 가격 등을 반영한 항공권 티켓을 예매하기위해 항공권을 검색하면
검색 결과에는 원치않는 정보가 많아 가독성이 떨어진다.
이에 항공권 검색 과정의 가독성을 높여 예매의 편리함을 제공하고,
주변 여행지 추천 및 커뮤니티를 제공하여 여행 준비의 편리함과
여행 지역의 정보를 공유할 수 있는 항공 예매 플랫폼 서비스를 만들고자 한다.


📆 작업 기간

2021.6.27 ~ 2021.7.20 (24일간)

👩‍💻 팀원 구성

박현성, 김다슬, 고정현, 유승준

🎯 기술 스택

Front-end

HTML5 JavaScript Bootstrap jQuery

Back-end

Java Spring MySQL

Communication Tools

GitHub Discord Notion

💻 DB 명세서

📜 API 사용내역

1. 카카오 로그인, 맵, 페이 API

2. 구글 로그인 API

3. 항공조회, 주차장조회 API(공공데이터포탈)


📄 기능 구현 사항 (유튜브로 이동)

1. 메인 페이지

  • (1) 항공편, 주차장 조회

2. 항공 조회 페이지

  • (1) 항공사별 카테고리
  • (2) 페이징 처리
  • (3) 찜 기능
  • (4) 카카오 페이 결제 API
  • (5) 결제 상세보기

구현기능 : 1, 2


구현기능 : 3, 4, 5


3. 회원가입, 로그인 페이지

  • (1) 이용약관 동의
  • (2) 아이디, 이메일 중복체크, 인증번호 인증
  • (3) 카카오 로그인 API
  • (4) 구글 로그인 API

구현기능 : 1, 2


구현기능 : 3


구현기능 : 4


4. 서비스 페이지(지도 API, 주차장 API)

  • (1) 지도 카테고리별 위치, 현재 위치 표시, 검색기능
  • (2) 각 공항별 주차장 실시간 정보

구현기능 : 1

구현기능 : 2


5. 게시판

  • (1) 글 작성, 수정/삭제, 상세보기, 조회수, 페이징 처리, 검색
  • (2) 댓글 작성, 수정/삭제, 페이징 처리

구현기능 : 1


구현기능 : 2


6. 공지사항

  • (1) 관리자 공지사항 추가, 수정/삭제

7. 마이 페이지

  • (1) 회원정보 조회/수정, 탈퇴
  • (2) 찜, 결제 목록 조회/삭제
  • (3) 목록 조회
  • (4) 카카오 페이 결제 API

8. 관리자 페이지

  • (1) 회원 목록 조회/삭제, 결제목록 조회/통계(월별 매출)
  • (2) 공지사항 작성, 수정, 삭제
  • (3) 게시글, 댓글 삭제

구현기능 : 1


구현기능 : 2


구현기능 : 3

728x90
728x90

백준 2417번 정수 제곱근


내가 떠올린 풀이 해설

처음 이 문제를 봤을 때 이분 탐색 문제라는 것을 떠올리지 못했다. 최솟값을 구하기 위해 min에다 long의 최댓값을 선언하고 start를 0 end를 입력 숫자 n으로 잡고 mid를 (start + end) / 2로 정해준다. value라는 변수를 하나 더 만들어 Math.pow(mid, 2) pow 메소드는 제곱근을 구할 수 있는 메소드이다. 제곱근이 0보다 커야 되니 if(value > 0)에서 if(value >= n) 일 때 최솟값 min = Math(min, mid)로 최솟값으로 바꿔준다.  if(value >= n) 일 때 end 값을 mid - 1 value가 n 보다 작으면 start 값을 mid + 1로 바꿔준다. while문 밖에서 min의 값을 출력해준다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek2417 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		long n = Long.parseLong(br.readLine());
		long start = 0;
		long end = n;
		long min = Long.MAX_VALUE;
		while(start <= end) {
			long mid = (start + end) / 2;
			long value = (long)Math.pow(mid, 2);
			if(value >= 0) {
				if(value >= n) {
					min = Math.min(min, mid);
					end = mid - 1;
				}
				else {
					start = mid + 1;
				}
			}
		}
		System.out.println(min);
	}
}

백준 10815번 숫자 카드


내가 떠올린 풀이 해설

어제 풀었던 29번 수 찾기 문제와 비슷한 접근을 하면 풀리는 문제입니다. 기본 이분 탐색 문제입니다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek10815 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		int [] arr = new int[n];
		StringTokenizer st = new StringTokenizer(br.readLine());
		for(int i = 0; i < n; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(arr);
		int m = Integer.parseInt(br.readLine());
		st = new StringTokenizer(br.readLine());
		for(int i = 0; i < m; i++) {
			int look = Integer.parseInt(st.nextToken());
			int start = 0;
			int end = arr.length - 1;
			boolean result = false;
			while(start <= end) {
				int mid = (start + end) / 2;
				int midV = arr[mid];
				if(midV < look) {
					start = mid + 1;
				}
				else if(midV > look){
					end = mid - 1;
				}
				else {
					result = true;
					break;
				}
			}
			if(result) {
				System.out.print(1 + " ");
			}
			else {
				System.out.print(0 + " ");
			}
		}	
	}
}

백준 2805번 나무 자르기


내가 떠올린 풀이 해설

이 문제는 이분 탐색 문제인데 언제 이분 탐색을 사용하는지 못 떠올리다가 문제를 풀면서 떠올리게 되었습니다. arr배열에 넣으면서 end값을 최댓값으로 구한다. while(start < end) sum 변수를 만들고 mid 값을 (start + end) / 2 넣어준다. for문을 배열만큼 탐색하면서 arr [i] - mid값이 0보다 클 때 sum에 계속 더해준다. for문 밖에서 만약 sum이 m 보다 작으면 end에 mid를 넣어주고 작지 않으면 start에 mid + 1을 넣어주고 while문 밖에서 start - 1을 출력해준다.


정확한 풀이

import java.io.*;
import java.util.*;
public class Baek2805 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		int []arr = new int[n];
		int start = 0;
		int end = 0;
		st = new StringTokenizer(br.readLine());
		for(int i = 0; i < n; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
			if(end < arr[i]) {
				end = arr[i];
			}
		}
		while(start < end) {
			long sum = 0;
			int mid = (start + end) / 2;
			for(int i = 0; i < n; i++) {
				if(arr[i] - mid > 0) {
					sum += arr[i] - mid;
				}
			}
			if(sum < m) {
				end = mid;
			}
			else{
				start = mid + 1;
			}
		}
		System.out.println(start - 1);
	}
}

오늘의 회고

오늘은 이분 탐색 기본 문제를 풀었습니다. 이분 탐색을 공부하면서 젤 어려운 점이 이분 탐색을 언제 적용해야 되는지 떠올리는데 어려움이 있었습니다. 아직까지 많이 부족하다고 생각하고 알고리즘을 풀면서 계속 복습하고 새로운 문제를 풀겠습니다. 하루하루 열심히 꾸준히 노력하겠습니다.

728x90
728x90

개요

skyLife_Transformation 프로젝트로 기존에 스프링으로 진행했던 프로젝트에서 성능반복되는 코드고려하지 않고 그저 기능이 구현되고 돌아가기 위한 코드를 작성했던 프로젝트를 스프링 부트로 바꾸고 성능을 개선하는 프로젝트를 진행하려고 합니다. 천천히 단계별로 개선을 시켜나갈 생각입니다.


1-1 스프링에서 스프링 부트

1. 스프링 부트 프로젝트 만들기

https://start.spring.io/ 에서 스프링 부트를 쉽게 만들 수 있습니다.

저는 Build Tool은 Gradle, 스프링 부트 버전은 2.7.0, Packaging은 Jar, Java 11 버전을 사용할 것입니다.

Dependencies는 Lombok, Spring Web, Spring Security, MyBatis Framework, MySQL Driver, Spring REST Docs를 추가해주었습니다.


2.  스프링 부트 JSP를 위한 수정사항

일단 저는 기존에 진행했던 프로젝트에서 뷰는 수정을 하지 않으려고 합니다.

기존 프로젝트는 jsp로 진행을 해서 스프링 부트에서 jsp를 사용해주려면 설정해줘야 하는 것들이 있습니다.

우선 JSP도 템플릿 엔진이기 때문에 사용하기 위해서는 별도의 라이브러리가 필요합니다.

implementation "org.apache.tomcat.embed:tomcat-embed-jasper"

build.gradle를 파일에 dependencies 부분에 위의 코드를 추가를 해줍니다.

또한 JSP를 사용하기 위해서는 webapp와 WEB-INF 폴더를 포함한 구조로 프로젝트를 변경해야 합니다.

스프링 부트에서 사용하는 뷰 리졸버의 경로를 변경해야 합니다. 뷰 리졸버의 경로는 application.properties에서 변경합니다.

spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp

위의 코드를 application.properties에 추가시켜줍니다. Controller 코드까지 작성하면 스프링 부트에서 jsp를 사용할 수 있습니다.

프로젝트의 메인화면입니다. 성공적으로 나오는 것을 확인할 수 있습니다.


3. 인텔리제이와 Github연동

인텔리제이 상단 메뉴에서 VCS를 누르고 Enable Version Control Integration을 클릭하면 밑에 사진과 같은 창이 나옵니다.

위의 창에서 ok를 클릭합니다.

위에서 ok를 클릭하면 상단 메뉴가 Git으로 바뀐 것을 확인하실 수 있습니다. Git 메뉴에서 Manage Remotes를 클릭하면 오른쪽 사진과 같은 창이 나옵니다. 오른쪽 사진에서 Add를 눌어주면 URL을 입력할 수 있는 밑에와 같은 창이 나옵니다.

URL 입력 창에 깃허브에서 레파지토리 주소를 복사해서 붙여 넣어줍니다.

밑에 Commit Message를 적을 수 있는 칸이 있고 Commit Message를 작성한 후 Commit and Push를 클릭해 주시면 깃허브에 잘 올라가는 것을 확인하실 수 있습니다.


오늘의 회고

오늘은 스프링 부트에서 프로젝트 메인화면을 띄우는 것부터 진행하였습니다. 뷰를 만들고 필요 없는 코드와 반복되는 코드들을 수정하고 프로젝트 설계부터 효율적인 방법을 고려해 진행할 예정입니다.

728x90

+ Recent posts