[SWEA] 1928 Base64 Decoder

[SWEA] 1928 Base64 Decoder

문제 링크

이 문제는 Base64로 Encoding된 문자열을 Decoding하는 문제다.

Base64를 제대로 이해하고 풀이한게 아니라서 좀 애매하다. 아래 링크에서 base64 encoding decoding 개념을 살폈다. 참고 링크

우선 Base64 디코딩 원리를 코드로 구현한 수준에 그쳤다.

  1. 인코딩된 문자열을 Base64색인표에서 찾아 해당 값의 2진법으로 표시합니다.
  2. 24비트 버퍼에 가장 위쪽 비트부터 6비트씩 4개의 값를 넣습니다.
  3. 24비트 버퍼를 8비트로 잘라 그 값을 ASCII로 읽습니다. 만약 값이 =으로 패딩되었다면 제외합니다.
  4. ASCII를 다시 문자열로 읽어 출력합니다.

table 객체를 만들어서 입력되는 문자(key)에 맞는 value를 반환하도록 작성했는데, 불필요한 하드코딩이었다. 개선한 코드는 맨 하단에 첨부했다. 친구의 코드를 보고 알아차린 것인데, 어차피 0~63까지의 인덱스를 갖게 되기에 table을 문자열 형식으로 나열해서 반복문으로 접근하는 방법을 택할 수 있었다.

또는 table을 타자를 쳐서 입력하는 것이 아니라 아스키 코드를 활용해서 작성해볼 수도 있겠다.

물론 하드 코딩한 것이 동작은 빠를 것으로 예상.

나의 풀이

t= int(input())

def char2bin(char):
  table = {
    "A" : 0, "B" : 1, "C" : 2, "D" : 3, "E" : 4, "F" : 5, "G" : 6, "H" : 7, "I" : 8, "J":9, "K" : 10,
    "L" : 11, "M":12, "N":13, "O":14, "P":15, "Q":16, "R":17, "S":18, "T":19, "U":20, "V":21, "W":22, "X":23, "Y":24, "Z":25,
    "a":26, "b":27, "c":28, "d":29, "e":30, "f":31, "g":32, "h":33, "i":34, "j":35, "k":36, "l":37, "m":38, "n":39, "o":40, "p":41, "q":42, "r":43, "s":44, "t":45, "u":46, "v":47, "w":48, "x":49, "y":50, "z":51,
    "0":52, "1":53, "2":54, "3":55, "4":56, "5":57, "6":58, "7":59, "8":60, "9":61, "+":62, "/":63
  }
  return bin(table.get(char))[2:].zfill(6)

def bin2oct(str):
  array = []
  for k in range(len(str)//8):
    # print('0b'+str[k*8:8*(k+1)])
    array.append(int('0b'+str[k*8:8*(k+1)], 2))
  if len(str) % 8:
    array.append(" ")
  return array

for i in range(t):
  base64_str  = input()
  base64_str = list(base64_str)

  for j in range(len(base64_str)):
    base64_str[j] = char2bin(base64_str[j])

  octs = bin2oct("".join(base64_str))

  print(f"#{i+1}", end=" ")
  for char in octs:
    if char == " ":
      print(" ", end="")
    else:
      print(chr(char), end="")
  print("")

table 수정 버전

t= int(input())

def char2bin(char):
  table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  for i in range(len(table)):
        if char == table[i]:
            return bin(i)[2:].zfill(6)

def bin2oct(str):
  array = []
  for k in range(len(str)//8):
    # print('0b'+str[k*8:8*(k+1)])
    array.append(int('0b'+str[k*8:8*(k+1)], 2))
  if len(str) % 8:
    array.append(" ")
  return array

# 테스트 케이스별 실행
for i in range(t):
  base64_str  = input() # base64로 인코딩 된 문자열 입력
  base64_str = list(base64_str) # list로 변환하여 문자열의 각 글자에 접근/수정이 가능하도록 함

  for j in range(len(base64_str)):
    base64_str[j] = char2bin(base64_str[j]) #char -> bin 함수를 통해서 base64 색인표에 따라 2진법으로 변환

  octs = bin2oct("".join(base64_str)) #8비트 단위로 구분해야하기에 문자열로 변환하여 bin->oct 함수로 전달
	# bin->oct 함수에서 8비트로 분리하여 10진수로 전환하여 반환, 8비트가 채워지지 않는 경우 공백(" ")으로 반환

  print(f"#{i+1}", end=" ")
  for char in octs:
    if char == " ": # 공백은 따로 처리
      print(" ", end="")
    else:
      print(chr(char), end="") #10진수 -> ASCII 코드에 따라 문자열로 변환
  print("")

© 2021. All rights reserved.