250303 회고 💬

날이 갑자기 더워졌다. 아침에는 패딩이 아직은 필요한데 저녁에는 지하철이 찜통이다. 집에오면 땀에 젖어서 샤워를 하게 된다. 날씨는 뭐 그렇다 치고 중요한건 따로있다. 바로 몬스터헌터 신작이 발매됐다. 몇년만의 신작인지,,, 🤪 게임할 시간 없는데 있는 시간을 쪼개서 게임을 하고있다... 미련한 사람... 😢 간만에 게임으로 주말을 날려버린 2월의 마지막 주를 되돌아본다.

Keep 👍

  • 알고리즘 문제 풀이를 계속하고 있다. 이번 주 삼성 기출 문제는 인구 이동이다. BFS 좀 풀었다 하면 금방 풀 수 있는 문제다. 시간 복잡도도 크지 않아서 로직이 단순하다.
  • 멀티스레드 강의를 듣고 있다. 내용이 어렵다.
    - 원자적 연산
    - AtomicInteger
    - CAS 연산
    - 동시성 컬렉션
    - Future
  • 저번 주에 개인 프로젝트 진행을 하나도 못한 부분에 반성할겸 이번 주에 하루 시간을 내어서 기능 작업을 했다. 프론트에서 비디오 목록을 보여주는 기능을 작업 중이다. 백에서 비디오 목록 쏴주는 기능은 어렵지 않은데 프론트에서 이 데이터를 이쁘게 가공하는 작업에 공수가 많이 들어간다.
  • CS 스터디를 진행했다. 이번 주에는 메모리와 컴퓨터 주변 기기들을 학습했다.
    - 멀티스레드
    - 생산자 소비자 문제

Try 🧚

  • SSAFY B형 대비 문제 풀이하기
  • 삼성 기출 문제집 문제 풀이
  • 토이 프로젝트 비디오 업로드 로직 완성
    - 백엔드
    - 개인 프로필 로직 제작
    - 비디오 업로드 로직
    - 프론트엔드
    - 개인 프로필 화면 제작
    - 비디오 화면 제작

독서 목록

서평 완료 목록

서평 예정 목록 (읽는 중)

  • 면접을 위한 CS 전공지식 노트

독서 예정 목록

  • 오브젝트
  • HTTP 완벽 가이드
  • 자바/스프링 개발자를 위한 실용주의 프로그래밍
  • 모던 자바 인 액션
  • 자바 성능 튜닝 이야기
  • 헤드 퍼스트 서블릿
  • 파이브 라인스 오브 코드

Extras 😀

인구 이동


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

public class Main {

	public static void main(String[] args) {
		new Main().run();
	}

	private void run() {
		try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {

			Solution s = new Solution();
			Input ip = readInput(br);
			System.out.println(s.solution(ip.lowerBound, ip.upperBound, ip.field));

		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	private Input readInput(BufferedReader br) throws IOException {
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int lowerBound = Integer.parseInt(st.nextToken());
		int upperBound = Integer.parseInt(st.nextToken());
		int[][] field = new int[n][n];

		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < n; j++) {
				field[i][j] = Integer.parseInt(st.nextToken());
			}
		}

		return new Input(lowerBound, upperBound, field);
	}

	private static class Input {

		final int lowerBound;
		final int upperBound;
		final int[][] field;

		public Input(int lowerBound, int upperBound, int[][] field) {
			this.lowerBound = lowerBound;
			this.upperBound = upperBound;
			this.field = field;
		}
	}
}

class Solution {

	private Field field;

	public int solution(int lowerBound, int upperBound, int[][] field) {
		init(lowerBound, upperBound, field);
		return calc();
	}

	private void init(int lowerBound, int upperBound, int[][] field) {
		this.field = new Field(lowerBound, upperBound, field);
	}

	private int calc() {
		int days = 0;

		while (field.hasDistributeTargets()) {
			field.distribute();
			days++;
		}
		return days;
	}
}

class Field {

	private static final int[][] DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};

	private int lowerBound;
	private int upperBound;
	private int[][] map;
	private boolean[][] visited;
	private List<DistributeTarget> targets;

	public Field(int lowerBound, int upperBound, int[][] map) {
		this.lowerBound = lowerBound;
		this.upperBound = upperBound;
		this.map = map;
	}

	public boolean hasDistributeTargets() {
		search();
		return !targets.isEmpty();
	}

	private void search() {
		int n = map.length;
		visited = new boolean[n][n];
		targets = new ArrayList<>();
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if(visited[i][j]) continue;
				explore(i, j);
			}
		}
	}

	private void explore(int x, int y) {
		Queue<int[]> q = new ArrayDeque<>();
		q.offer(new int[]{x, y});
		visited[x][y] = true;

		DistributeTarget target = new DistributeTarget(getPopulationOf(x, y), new int[] {x, y});

		while (!q.isEmpty()) {
			int[] cur = q.poll();

			for (int[] direction : DIRECTIONS) {
				int nx = cur[0] + direction[0];
				int ny = cur[1] + direction[1];

				if(isOutOfBounds(nx, ny)) continue;
				if(visited[nx][ny]) continue;
				if(isNotMeetingCondition(getPopulationOf(cur[0], cur[1]), getPopulationOf(nx, ny))) continue;

				q.offer(new int[]{nx, ny});
				visited[nx][ny] = true;
				target.addLocation(new int[]{nx, ny});
				target.addPopulation(getPopulationOf(nx, ny));
			}
		}

		if (target.isValid()) {
			targets.add(target);
		}
	}

	private int getPopulationOf(int x, int y) {
		return map[x][y];
	}

	private boolean isOutOfBounds(int x, int y) {
		return x < 0 || x >= map.length || y < 0 || y >= map.length;
	}

	private boolean isNotMeetingCondition(int pop1, int pop2) {
		return upperBound < Math.abs(pop1 - pop2) || Math.abs(pop1 - pop2) < lowerBound;
	}

	public void distribute() {
		for (DistributeTarget target : targets) {
			int newPop = target.getCalcedPop();
			for (int[] location : target.getLocations()) {
				setPopulationOf(location, newPop);
			}
		}
	}

	private void setPopulationOf(int[] location, int pop) {
		map[location[0]][location[1]] = pop;
	}
}

class DistributeTarget {

	private int population;
	private List<int[]> locations;

	public DistributeTarget(int population, int[] location) {
		this.population = population;
		this.locations = new ArrayList<>();
		locations.add(location);
	}

	public void addPopulation(int pop) {
		population += pop;
	}

	public void addLocation(int[] location) {
		locations.add(location);
	}

	public boolean isValid() {
		return locations.size() > 1;
	}

	public int getCalcedPop() {
		return population / locations.size();
	}

	public List<int[]> getLocations() {
		return locations;
	}
}
profile
What doesn't kill you, makes you stronger

0개의 댓글

Powered by GraphCDN, the GraphQL CDN