알고리즘/Samsung

SW 1928. Base64 Decoder

son_i 2023. 5. 5. 14:42
728x90

SW Expert Academy

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

자바

이거는 문제를 이해하는 것부터 정말 오래걸렸다 ....

 

Base64 == 64진법

<Base64 Encoding>

1. 원본 문자열 3byte를 아스키코드로 변환해서 24비트 버퍼에 넣는다.

2. 6비트씩 끊어서 Base64 테이블의 문자로 변환.

\

<Base64 Decoding>

1. 디코딩된 문자열의 4byte를 Base64테이블을 보고 변환해서 24비트 버퍼에 넣는다.

2. 8비트씩 끊어서 아스키코드표의 문자로 변환.

 

이해하고 나면 이렇게 간단한디 ...

 

작업

- 인코딩되니 문자열을 Base64값으로 변환해서 arr이라는 ArrayList 제일 뒤에 계속해서 넣음.

  뒤에서부터 넣은 이유는 그래야 순서대로 넣어지니까. 뭐 그때 반복문 안의 변수 j로 해도 되겠었다.

 

- 2진수로 바꿔서 6비트씩 저장.

  n이라는 변수 반복문 밖에 선언 -> 한 문자를 2진수로바꾸면 6자리가 되고(0~5인덱스) 그 다음 문자는 인덱스 6부터 저장되어야하니까 그걸 연산하기 위해서 만듦.

반복을 돌면서 맨 앞자리 숫자부터 2로 나눈 값이 1이상이다 => 2진수로 바꿀 수 arr.get(m)이 다 나눠진 거임.

   list라는 ArrayList에 0+n번째에 arr.get(m)을 2로 나눈 나머지를 위에서부터 넣기 시작함.

   arr.set(m,arr.get(m)/2); //원본arr의 m번째 값을 2로 나눈 몫값으로 다시 세팅 ch 증가

ch는 arr.get(m)을 2로 나눈 나머지, 2로 나눈 몫을 다 list에 넣었을 때 몇 자리까지 차지하는 지를 헤아리는 변수

얘가 6이 아니라면 앞에서부터 0을 또 채워서 6자리를 만들어줘야함.

 

- 8자리씩 끊어서 아스키 코드로 변환.

num += (list.get(j*9)+ch)*Math.pow(2,7-ch);

이 작업 반복을 끝내고 num을 (char)로 출력하면 아스키 코드 문자 값이 나옴.

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

/*
   사용하는 클래스명이 Solution 이어야 하므로, 가급적 Solution.java 를 사용할 것을 권장합니다.
   이러한 상황에서도 동일하게 java Solution 명령으로 프로그램을 수행해볼 수 있습니다.
 */
public class Solution
{
	public static void main(String args[]) throws Exception
	{
		//System.setIn(new FileInputStream("C:\\so_Project\\workspace\\BaekJoon\\src\\algorithm\\input.txt"));

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		int T = Integer.parseInt(br.readLine()); //테스트 케이스
		
		StringBuilder sb = new StringBuilder();
		for(int i=1;i<=T;i++) { //하나의 테스트케이스마다 반복
			sb.append("#"+i+" ");
			String str = br.readLine();
			List <Integer>arr = new ArrayList<>(); 
			List <Integer>list = new ArrayList<>(); 

			for(int j=0;j<str.length();j++) { //인코딩 문자열 Base 64 변환
				char c = str.charAt(j);
				
				if(c >='A' && c<='Z') {
					arr.add(arr.size(),c-65);
				}
				else if(c>= 'a' && c<='z') {
					arr.add(arr.size(),c-71);
				}
				else {
					if( c>= '0' && c<= '9') {
						arr.add(arr.size(),c+4);
					}
					else if (c =='+') arr.add(arr.size(),62);
					else arr.add(arr.size(),63);
				}				
			}
			//2진수 6비트씩 저장
			int n=0;
			for(int m=0;m<arr.size();m++) {
				int ch =0;
				while(arr.get(m)/2 >1) {
					list.add(0+n,arr.get(m)%2);
					arr.set(m,arr.get(m)/2);
					ch++;
				}
				list.add(0+n,arr.get(m)%2);
				list.add(0+n,arr.get(m)/2);
				ch+=2;
				while(ch !=6) {
					list.add(0+n,0);
					ch++;
				}
				n+=6;
			}
			//8자리씩 끊어서 아스키 코드표로 변환
			for(int j=0;j<list.size()/8;j++) {
				int num = 0;
				int ch =0;
				while(ch != 8) {
					num += (int)(list.get((j*8)+ch)*Math.pow(2, 7-ch));
					ch++;
				}
				sb.append((char)num);
			}sb.append("\n");
		}//하나의 테스트 케이스 끝 
		System.out.println(sb);
	}
}

 

 

728x90