TIL 240621

인자약·2024년 6월 21일

TIL

목록 보기
14/14

delta

deltaTest

package basic.delta;

import java.util.Arrays;

// 2차원 배열 (문자)
// if - else 구조의 4방 탐색은 개발자의 실수를 많이 유발
// 상, 하, 좌, 우 이동에 대한 변화량을 미리 배열로 계산
// 상(-1, 0) 하(+1, 0) 좌 (0, -1) 우 (0, +1)
public class DataTest1 {

	static char[][] map = new char[5][5];
	public static void main(String[] args) {
		char ch = 'A';
		
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				map[i][j] = ch++;
			}
		}

		// 출력
		for (int i = 0; i <5; i++) {
			System.out.println(Arrays.toString(map[i]));
		}
//		System.out.println(Arrays.deepToString(map).replace("],", "]\n"));
		
		// y = 3, x = 3 자리의 상,하,좌,우 출력
//		print4_no_delta(4, 4);
//		for (int i = 0; i < 5; i++) {
//			for (int j = 0; j < 5; j++) {
//				print4(i, j);
//			}
//		}
		
//		for (int i = 0; i < 5; i++) {
//			for (int j = 0; j < 5; j++) {
//				print4x(i, j);
//			}
//		}
		
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				print8(i, j);
			}
		}
		
	}
	
	static void print4_no_delta(int y, int x) {
		// 상
		if (y - 1 >= 0) {
			System.out.print(map[y - 1][x]);
		}
		// 하
		if (y + 1 < 5) {
			System.out.print(map[y + 1][x]);
		}
		// 좌
		if (x - 1 >= 0) {
			System.out.print(map[y][x - 1]);
		}
		// 우
		if (x + 1 < 5) {
			System.out.print(map[y][x + 1]);
		}
		
		System.out.println();
	}

	// delta
	// 상, 하, 좌, 우
	// 순서가 있다. (문제에 따라 순서를 고정시켜야 하는 경우도 존재)
	static int dy4[] = {-1, 1, 0, 0};
	static int dx4[] = {0, 0, -1, 1};
	
	static void print4(int y, int x) {
		System.out.print(map[y][x] + " : ");
		
		for (int d = 0; d < 4; d++) {
			int ny =  y + dy4[d];
			int nx =  x + dx4[d];
			
			if (ny < 0 || nx < 0 || ny >= 5 || nx >= 5) continue;
			System.out.print(map[ny][nx]);
		}
		System.out.println();
	}
	
	// 대각선
	// 좌상, 우상, 좌하, 우하
	static int dy4x[] = {-1, -1, 1, 1};
	static int dx4x[] = {-1, 1, -1, 1};
	
	static void print4x(int y, int x) {
		System.out.print(map[y][x] + " : ");
		
		for (int d = 0; d < 4; d++) {
			int ny =  y + dy4x[d];
			int nx =  x + dx4x[d];
			
			if (ny < 0 || nx < 0 || ny >= 5 || nx >= 5) continue;
			System.out.print(map[ny][nx]);
		}
		System.out.println();
	}
	
	// 8방
	static int dy8[] = {-1, 1, 0, 0, -1, -1, 1, 1};
	static int dx8[] = {0, 0, -1, 1, -1, 1, -1, 1};
	
	static void print8(int y, int x) {
		System.out.print(map[y][x] + " : ");
		
		for (int d = 0; d < 8; d++) {
			int ny =  y + dy8[d];
			int nx =  x + dx8[d];
			
			if (ny < 0 || nx < 0 || ny >= 5 || nx >= 5) continue;
			System.out.print(map[ny][nx]);
		}
		System.out.println();
	}
}
package basic.delta;

import java.util.Arrays;

// 2차원 배열 (문자)
// if - else 구조의 4방 탐색은 개발자의 실수를 많이 유발
// 상, 하, 좌, 우 이동에 대한 변화량을 미리 배열로 계산
// 상(-1, 0) 하(+1, 0) 좌 (0, -1) 우 (0, +1)
// 한 칸이 이동이 아닌 갈 수 있을 때까지 계속 이동
public class DataTest2 {

	static char[][] map = new char[5][5];
	public static void main(String[] args) {
		char ch = 'A';
		
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				map[i][j] = ch++;
			}
		}

		// 출력
		for (int i = 0; i <5; i++) {
			System.out.println(Arrays.toString(map[i]));
		}
		
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 5; j++) {
				print8(i, j);
			}
		}
		
	}

	// delta
	// 상, 하, 좌, 우
	// 순서가 있다. (문제에 따라 순서를 고정시켜야 하는 경우도 존재)
	static int dy4[] = {-1, 1, 0, 0};
	static int dx4[] = {0, 0, -1, 1};
	
	static void print4(int y, int x) {
		System.out.print(map[y][x] + " : ");
		
		for (int d = 0; d < 4; d++) {
			// 반복문으로 구성, ny = y.. -> ny = ny ..
			int ny = y;
			int nx = x;
			
			while (true) {
				ny =  ny + dy4[d];
				nx =  nx + dx4[d];
				
				if (ny < 0 || nx < 0 || ny >= 5 || nx >= 5) break;
				System.out.print(map[ny][nx]);
			}
			
		}
		System.out.println();
	}
	
	// 대각선
	// 좌상, 우상, 좌하, 우하
	static int dy4x[] = {-1, -1, 1, 1};
	static int dx4x[] = {-1, 1, -1, 1};
	
	static void print4x(int y, int x) {
		System.out.print(map[y][x] + " : ");
		
		for (int d = 0; d < 4; d++) {
			int ny = y;
			int nx = x;
			
			while (true) {
				ny =  ny + dy4x[d];
				nx =  nx + dx4x[d];
				
				if (ny < 0 || nx < 0 || ny >= 5 || nx >= 5) break;
				System.out.print(map[ny][nx]);
			}	
		}
		System.out.println();
	}
	
	// 8방
	static int dy8[] = {-1, 1, 0, 0, -1, -1, 1, 1};
	static int dx8[] = {0, 0, -1, 1, -1, 1, -1, 1};
	
	static void print8(int y, int x) {
		System.out.print(map[y][x] + " : ");
		
		for (int d = 0; d < 8; d++) {
			int ny = y;
			int nx = x;
			
			while (true) {
				ny =  ny + dy8[d];
				nx =  nx + dx8[d];
				
				if (ny < 0 || nx < 0 || ny >= 5 || nx >= 5) break;
				System.out.print(map[ny][nx]);
			}
			
		}
		System.out.println();
	}
}

Recursive

RecursiveCallTest

package basic.recursive;

public class RecursiveCallTest {

	public static void main(String[] args) {
//		m1();
//		m1_2(0);
//		m2();
//		m3();
//		m4();
		m5(5);
	}

//	static int m1_cnt = 0;
//	static void m1() {
//		// local 변수와 값은 항상 초기화
////		int i = 0;
////		System.out.println("m1 " + i);
////		
//		System.out.println("m1 " + m1_cnt++); // static 변수는 공유
//		m1();
//	}
//	
//	static void m1_2(int i) {
//		System.out.println("m1_2 " + i); // parameter 공유
//		i++;
//		m1_2(i);
//	}
	
	static int m2_cnt = 5;
	static void m2() {
		System.out.println("앞 m2 cnt : " + m2_cnt);
		
		if (m2_cnt > 0) {
			m2_cnt--;
			m2();
		}
		
		System.out.println("뒤 m2 cnt : " + m2_cnt);
	}
	
	static int m3_cnt = 5;
	static void m3() {
		System.out.println("앞 m3 cnt : " + m3_cnt); // 기저조건 check 전에 항상 수행
		// 기저 조건
		if (m3_cnt == 0) {
			return;
		}
		m3_cnt--;
		m3();
		
		System.out.println("뒤 m3 cnt : " + m3_cnt); // 기저조건 check 후에 있어서 기저조건에 의해 return 되면 수행 X
	}
	
	static int m4_cnt = 5;
	static void m4() {
		
		// 기저 조건
		if (m4_cnt == 0) {
			return;
		}
		
		// 앞, 뒤 출력을 쌍으로 맞추려면 기저 조건이 맨 위로 이동해야 한다.
		System.out.println("앞 m4 cnt : " + m4_cnt);
				
		m4_cnt--;
		m4();
		m4_cnt++; // 재귀 호출 전후에 동일한 static 변수의 값을 가지려면 변화량의 반대로 처리를 해줘야 한다.
		
		System.out.println("뒤 m4 cnt : " + m4_cnt);
	}
	
	// static 대신 파라미터 공유
	static void m5(int m5_cnt) {
		
		// 기저 조건
		if (m5_cnt == 0) {
			return;
		}
		
		// 앞, 뒤 출력을 쌍으로 맞추려면 기저 조건이 맨 위로 이동해야 한다.
		System.out.println("앞 m5 cnt : " + m5_cnt);

		// 1. 줄였다 원복.	
//		m5_cnt--;
//		m5(m5_cnt);
//		m5_cnt++; // 재귀 호출 전후에 동일한 static 변수의 값을 가지려면 변화량의 반대로 처리를 해줘야 한다.
		
		// 2. 줄이지 않고 줄이는 연산을 통해서 전달
//		m5(m5_cnt - 1);
		
		// 3. -- 연산자
//		m5(m5_cnt--); // stack overflow
		
		// 4. -- 연산자 앞
		m5(--m5_cnt);
		m5_cnt++; // 원복이 필요
		
		System.out.println("뒤 m5 cnt : " + m5_cnt);
	}
}

FactorialTest

package basic.recursive;

public class FactorialTest {

	public static void main(String[] args) {
		
		factorial(5); // 5x4x3x2x1
		int result = factorial2(5);
		System.out.println(result);
		factorial3(5, 1);
	}
	
	// 계산 결과를 static 변수를 이용
	static int result = 1;
	static void factorial(int n) {
		// 기저조건
		// 1. 재귀호출을 끝내야 한다.
		// 2. 문제에서 원하는 상태가 완료되었다.
		if (n == 1) {
			// 계산 결과 출력
			System.out.println(result);
			return;
		}
		// 계산
		result = result * n;
		
		// 재귀 호출
		factorial(n - 1);
	}

	// 5 <- 4 <- 3 <- 2 <- 1
	static int factorial2(int n) {
		// 기저조건
		if (n == 1) {
		// 계산 결과 출력 대신 재귀 호출 종료 처리
			return 1;
		}
		// 계산
		// 3 단계 입장은 4 에게 2 X 1 의 결과에 3 자신을 곱해서 리턴
		// 나보다 1 적은 재귀 호출을 수행하고 그 결과에 나를 곱한 다음 리턴
		return n * factorial2(n - 1);
	}
	
	static void factorial3(int n, int result) { // result : 이전 단계에서 계산되어 전달된 값
		// 기저 조건
		if (n == 1) {
			System.out.println(result);
			return;
		}
		// 계산
		// result 에 자신을 곱한다.
//		int temp = result * n;
		
//		 재귀 호출
//		factorial3(n - 1, temp);
		
		// 재귀 호출 + 계산
		factorial3(n - 1, result * n);
	}
}

Sort

ArraySortTest

package basic.sort;

import java.util.Arrays;
import java.util.Comparator;

// 자바는 정렬 API 를 제공
// 문제에서 정렬이 필요한 경우, 적절하게 대응
public class ArraySortTest {

	public static void main(String[] args) {
		// 정수 정렬
//		int[] intArray = {3, 5, 2, 7, 9, 4};
//		Arrays.sort(intArray);
//		System.out.println(Arrays.toString(intArray));
//		
		// 문자열
//		String[] strArray = {"Hello", "ABC", "World", "UPLUS"};
//		Arrays.sort(strArray);
////		Arrays.sort(strArray, Collections.reverseOrder());
//		System.out.println(Arrays.toString(strArray));
		
		Item[] itemArray = {
				new Item(3, "666"), new Item(2, "777"), new Item(5, "444"), new Item(3, "111")
		};
		// implements Comparable
//		Arrays.sort(itemArray);
//		Arrays.sort(itemArray, Collections.reverseOrder());
//		System.out.println(Arrays.toString(itemArray));
		
		// Comparator interface 객체 전달
		// 정렬 하기 위한 방법 2 : Comparator 객체 전달(익명) // 대상 객체에 Comparable 구현 없어도 된다.	
//		Arrays.sort(itemArray, new Comparator<Item>() {
//
//			@Override
//			public int compare(Item o1, Item o2) {
////				return o1.itemId - o2.itemId;
//				return o1.itemNm.compareTo(o2.itemNm);
//			}
//			
//		});
//		System.out.println(Arrays.toString(itemArray));
		
		// 정렬 하기 위한 방법 3 : Comparator 객체 전달(Lambda) // 대상 객체에 Comparable 구현 없어도 된다.
		Arrays.sort(itemArray, (o1, o2) -> o2.itemId - o1.itemId);
		System.out.println(Arrays.toString(itemArray));
	}
	
	// 정렬이 되기 위한 방법 1 : Comparable interface 를 구현
	
	static class Item implements Comparable<Item> {
		int itemId;
		String itemNm;
		
		Item(int itemId, String itemNm) {
			this.itemId = itemId;
			this.itemNm = itemNm;
		}

		@Override
		public String toString() {
			return "Item [itemId=" + itemId + ", itemNm=" + itemNm + "]";
		}

		@Override
		public int compareTo(Item o) {
//			return this.itemId - o.itemId; // itemId asc, 음수 this 가 앞.
//			return this.itemNm.compareTo(o.itemNm); // itemNm 기준
			// itemId 우선 비교 같으면 itemNm 비교
			return this.itemId == o.itemId ? this.itemNm.compareTo(o.itemNm) : this.itemId - o.itemId;
		}
	}

}

CollectionSortTest

package basic.sort;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionSortTest {
	
	public static void main(String[] args) {
		List<Item> list = new ArrayList<>();
		list.add(new Item(3, "666"));
		list.add(new Item(2, "777"));
		list.add(new Item(5, "444"));
		list.add(new Item(3, "111"));
		// new Item(3, "666"), new Item(2, "777"), new Item(5, "444"), new Item(3, "111")
		
		System.out.println(list);
		
//		Collections.sort(list);
//		System.out.println(list);
		
		Collections.sort(list, (el1, el2) -> el1.itemId - el2.itemId);
		System.out.println(list);
		
		Collections.sort(list, (el1, el2) -> el1.itemNm.compareTo(el2.itemNm));
		System.out.println(list);
		
		Collections.sort(list, (o1, o2) -> o1.itemId == o2.itemId ? o1.itemNm.compareTo(o2.itemNm) : o1.itemId - o2.itemId);
		System.out.println(list);
	}
	
		static class Item implements Comparable<Item> {
			int itemId;
			String itemNm;
			
			Item(int itemId, String itemNm) {
				this.itemId = itemId;
				this.itemNm = itemNm;
			}

			@Override
			public String toString() {
				return "Item [itemId=" + itemId + ", itemNm=" + itemNm + "]";
			}

			@Override
			public int compareTo(Item o) {
//				return this.itemId - o.itemId; // itemId asc, 음수 this 가 앞.
//				return this.itemNm.compareTo(o.itemNm); // itemNm 기준
				// itemId 우선 비교 같으면 itemNm 비교
				return this.itemId == o.itemId ? this.itemNm.compareTo(o.itemNm) : this.itemId - o.itemId;
			}
		}

	}

Perm

package basic.perm;

import java.util.Arrays;
import java.util.Iterator;

// 5 개 수 중 3 개의 수로 만들 수 있는 순열의 종류 그 구성
public class Perm_Basic {
	static int[] src = {1, 2, 3, 4, 5};
	static int[] tgt = new int[3]; // __ __ __ <- tgtIdx
	static boolean[] select = new boolean[src.length]; // src 1,2,3,4,5 각각에 대한 이전 사용 여부
	
	public static void main(String[] args) {
		perm(0); // 첫 번째 자리를 채우면서 시작
	}
	
	static void perm(int tgtIdx) {
		// 기저조건
		if (tgtIdx == tgt.length) {
			// 순열 한 가지가 완성
			System.out.println(Arrays.toString(tgt));
			return;
		}
		// tgtIndex 자리에 채울 수를 고려
		for (int i = 0; i < src.length; i++) {
			
			// tgtIdx 앞자리에 이미 사용된 수만 제외, 사용된 수는 select[] 에 기록
			if (select[i]) continue;
			
			tgt[tgtIdx] = src[i];
			select[i] = true;
			perm(tgtIdx + 1);
			select[i] = false; // for 문의 i가 이전 재귀호출에서 선택되서 고려되었으므로 다음 i 를 고려하기 위해 i 선택 해제
			
		}
	}
	
}

Comb

package basic.comb;

import java.util.Arrays;

public class Comb_Basic {

	static int[] src = {1, 2, 3, 4, 5};
	static int[] tgt = new int[3]; // __ __ __ <- tgtIdx
	// 조합은 select 필요 x
	// src 의 맨 앞에서부터 tgt 의 각 자리를 순차적으로 고려하면서 채운다.
	public static void main(String[] args) {
		comb(0, 0);

	}
	
	static void comb(int srcIdx, int tgtIdx) {
		
		// 기저조건
		if (tgtIdx == tgt.length) {
		// 순열 한 가지가 완성
			System.out.println(Arrays.toString(tgt));
			return;
		}
		
		if (srcIdx == src.length) return;
		
		tgt[tgtIdx] = src[srcIdx]; // tgtIdx 자리에 srcIdx 의 수를 채운다. 선택

		comb(srcIdx + 1, tgtIdx + 1); // 위 선택을 받아들이고 다음 자리를 채우러 재귀 호출
		comb(srcIdx + 1, tgtIdx); // 위 선택 무시 (비선택) srcIdx 증가시켜서 다음 수를 고려하되 tgtIdx 는 그대로 현재 자리를 고려
	}

}

Subset

package basic.subset;

// 부분집합은 조합의 합
public class Subset_Basic {
	
	static int[] src = {1, 2, 3, 4, 5};
	static boolean[] select = new boolean[src.length];
	
	public static void main(String[] args) {
		subset(0);
	}
	
	static void subset(int srcIdx) {
		// 기저조건
		if (srcIdx == src.length) {
			printSubset();
			return;
		}
		
		// 현재 srcIdx 에 대해서 선택, 비선택 이어간다.
		select[srcIdx] = true; // 선택
		subset(srcIdx + 1);
		
		select[srcIdx] = false; // 비선택
		subset(srcIdx + 1);
	}
	
	static void printSubset() {
		StringBuilder sb = new StringBuilder();
		
		for (int i = 0; i < select.length; i++) {
			if (select[i]) sb.append(src[i]).append(" ");
		}
		
		System.out.println(sb);
	}

}
profile
인자약velog

0개의 댓글