[Rules_규칙]
문자를 임의의 코드로 변환하는 것을 인코딩이라고 합니다.
이 게임의 인코딩 규칙은 다음과 같습니다.
- 입력 문자열은 7비트 아스키코드로 구성되어 있습니다.
- 출력할 메시지는 0의 블록으로 구성됩니다.
- 각 블록은 "공백"으로 구분합니다.
- 출력할 메시지는 연속한 동일 비트를 묶어 2개의 블록을 한 쌍으로 표현합니다.
- 첫 번째 블록은 항상 0 또는 00입니다. 비트가 1일 경우 0으로, 0일 경우 00으로 표현합니다.
- 두 번째 블록은 연속한 동일 비트(1 또는 0)의 개수만큼 0을 출력합니다.
[문제]
https://www.codingame.com/training/easy/unary/discuss
Developer discussion about "Unary"
Exchange with other coders about "Unary". Discuss about algorithm, optimization, language syntax tips...
www.codingame.com
[난이도]
[학습 개념]
[풀이]
입력된 문자열을 7비트 아스키 코드로 변환한 후, 이진수로 변환하여 하나의 문자열로 만들고 있습니다.
이진수 문자열에서는 이전 비트와 동일한 비트가 나타날 때마다 count 변수를 1 증가시키고, 이전 비트와 다른 비트가 나타날 때마다 현재까지의 count 값을 이용하여 정답 문자열(answer)을 생성합니다.
이전 비트가 '1'인 경우에는 정답 문자열에 '0 '을 추가하고, '0'인 경우에는 '00 '을 추가합니다. 이후에는 count 값만큼 '0'을 더해주고, 뒤에 공백을 추가합니다.
마지막으로, 마지막 연속 비트들을 처리하여 압축 문자열을 생성하고, 이를 출력합니다.
[소스 코드]
class Solution
{
static void Main(string[] args)
{
string MESSAGE = Console.ReadLine();
#region 입력 받은 메시지를 2진수로 변환하는 부분
string binary_string = "";
foreach (var c in MESSAGE)
{
var asciiValue = (int)c;
Console.Error.WriteLine(asciiValue);
var binary = Convert.ToString(asciiValue, 2);
binary_string += binary;
}
//6비트 문자열을 앞에 0을 추가해 7비트 문자열로 바꾸는 부분
if (binary_string.Length == 6)
{
binary_string = "0" + binary_string;
}
#endregion
#region 2진수 문자열을 단항 방식으로 인코딩하는 부분
char previous_bit = binary_string[0]; //이전 문자열 저장
int count = 0; //이전 문자가 연속해서 나타나는 횟수
string answer = ""; //정답을 저장할 변수
for (int i = 0; i < binary_string.Length; i++)
{
if (binary_string[i] != previous_bit)
{
if (previous_bit == '1')
{
answer += "0 ";
}
else
{
answer += "00 ";
}
answer += String.Concat(Enumerable.Repeat("0", count)) + " "; // 반복 횟수만큼 0을 더하고 뒤에 공백 추가
count = 0;
}
count++;
previous_bit = binary_string[i];
}
if (previous_bit == '1')
{
answer += "0 ";
}
else
{
answer += "00 ";
}
answer += String.Concat(Enumerable.Repeat("0", count));
Console.Error.WriteLine(binary_string);
#endregion
Console.WriteLine(answer);
}
}
위의 코드는 제가 고민하여 만든 코드입니다.
[새롭게 알게된 점]
위의 코드로도 작동은 됩니다.
하지만 C#의 기능을 제대로 못쓴 기분이고 코드 중복에 예외 처리에 주석도 깔끔하지 못합니다.
그래서 더 코드를 깔끔하게 할 수 있지 않을까 하고 노력한 결과 새롭게 알게 된 지식들이 있고, 이것들을 소개한 후 새로운 코드를 보여드리겠습니다.
- string 클래스를 사용하면 문자열이 변경되면 새로운 문자열 객체를 만들어서 메모리에 할당하게 됩니다. 이러한 동작은 메모리를 많이 사용하여 성능 저하를 가져올 수 있습니다. StringBuilder 클래스는 이러한 성능 문제를 해결하기 위해 문자열 객체를 만들지 않고 문자열을 수정할 수 있습니다.
- StringBuilder 클래스에는 문자열을 추가하는 Append 메서드가 있습니다. 이 메서드는 문자열이 아닌 여러 가지 데이터 형식을 추가할 수 있습니다. 또한, Insert 메서드를 사용하여 문자열의 특정 위치에 문자열을 삽입할 수 있습니다. Remove 메서드를 사용하여 문자열의 특정 위치에서부터 지정된 길이만큼 문자열을 제거할 수 있습니다.
- PadLeft 메소드는 문자열을 지정된 길이로 맞추기 위해 왼쪽에 지정된 문자를 추가하는 메소드입니다. 즉, 문자열이 지정된 길이보다 짧을 경우 왼쪽에 지정된 문자를 추가하여 문자열의 길이를 맞출 수 있습니다.
[개선한 소스 코드]
using System;
using System.Linq;
using System.Text;
class Solution
{
static void Main(string[] args)
{
string MESSAGE = Console.ReadLine();
#region 입력 받은 메시지를 2진수로 변환하는 부분
// 입력 문자열이 null이거나 빈 문자열인 경우 "No input"을 출력하고 프로그램 종료
if (string.IsNullOrEmpty(MESSAGE))
{
Console.WriteLine("No input");
return;
}
// 입력 문자열을 7비트 이진수로 변환하여 StringBuilder에 저장
var binaryStringBuilder = new StringBuilder();
foreach (var c in MESSAGE)
{
var asciiValue = (int)c; // 문자 c의 ASCII 코드 값을 구함
var binary = Convert.ToString(asciiValue, 2).PadLeft(7, '0'); // ASCII 코드 값을 2진수로 변환하고, 7자리 비트로 맞춤
binaryStringBuilder.Append(binary); // StringBuilder에 이진수 문자열 추가
}
var binaryString = binaryStringBuilder.ToString(); // StringBuilder의 내용을 문자열로 변환
#endregion
#region 2진수 문자열을 단항 방식으로 인코딩하는 부분
// 연속으로 나타나는 비트들을 압축하여 StringBuilder에 저장
var previousBit = binaryString[0]; // 이전 비트 초기화
var count = 1; // 비트 연속 개수 초기화
var compressedBuilder = new StringBuilder(); // 압축된 문자열을 저장할 StringBuilder 초기화
for (int i = 1; i < binaryString.Length; i++)
{
if (previousBit == binaryString[i])
{
// 이전 비트와 같으면 카운트 증가
count++;
}
else
{
// 이전 비트와 다르면 압축 문자열을 생성하여 StringBuilder에 추가
compressedBuilder.Append(previousBit == '0' ? "00 " : "0 "); // 이전 비트가 0이면 "00", 1이면 "0"을 추가
compressedBuilder.Append(new string('0', count) + " "); // 연속 비트의 개수를 추가
count = 1; // 비트 연속 개수를 1로 초기화
previousBit = binaryString[i]; // 이전 비트를 현재 비트로 갱신
}
}
// 마지막 연속 비트들을 처리하여 압축 문자열 생성 후 StringBuilder에 추가
compressedBuilder.Append(previousBit == '0' ? "00 " : "0 "); // 마지막 비트가 0이면 "00", 1이면 "0"을 추가
compressedBuilder.Append(new string('0', count)); // 마지막 연속 비트들의 개수를 추가
#endregion
// 압축된 문자열을 출력
Console.WriteLine(compressedBuilder.ToString());
}
}
'알고리즘 공부 > codingame 사이트 문제' 카테고리의 다른 글
[CodinGame] SHADOWS OF THE KNIGHT(이진 탐색으로 폭탄 찾기) (0) | 2023.05.08 |
---|---|
[CodinGame] SCRABBLE(해시맵으로 단어 만들기) (0) | 2023.05.04 |
[CodinGame] WAR(카드 게임 알고리즘-Queue) (0) | 2023.05.03 |
[CodinGame] THERE IS NO SPOON - EPISODE 1(2차원 노드 찾기) (0) | 2023.04.19 |
[CodinGame] Stock Exchange Losses(중간 증권 거래소 손실) (0) | 2023.04.18 |