C#:Day03 코드 2021의 출현 - 바이너리 진단 사용
19195 단어 csharpadventofcode
코드가 좀 지루하고 복잡해졌지만, 그다지 나쁘거나 복잡하지는 않았다.
제1부
이 퍼즐은 우리에게 비트 시퀀스 목록을 제공했다.이 데이터 집합에 근거하여 우리는 두 개의 값
delta
과 epsilon
을 계산하여 잠수함의 소모에 대응해야 한다.만약 우리가 데이터 집합을 2차원 비트 그룹으로 간주한다면, 더욱 쉽게 계산할 수 있을 것이다.delta
값은 2차원 그룹의 열마다 가장 흔히 볼 수 있는 값을 지정함으로써 생성된 서열이다.epsilon
값은 열마다 가장 흔치 않은 값의 서열이다.delta
와 epsilon
의 값을 확정한 후에 우리는 반드시 이진수를 소수로 전환해야 한다.마지막으로 우리는 이 두 숫자의 곱셈이 필요하다.이 해결 방안을 위해 알고리즘을 설계합시다.
POWER_CONSUMPTION(Values)
Input: A list of binary numbers
Output: The product of delta times epsilon values
FOR i=0 TO Length(Values[0])
common += GetMostCommon(Values, i)
uncommon += GetLeastCommon(Values, i)
ENDFOR
common = ConvertToDecimal(common)
uncommon = ConvertToDecimal(uncommon)
return common * uncommon
알고리즘이 완성되면 C# 구현을 시작하겠습니다.시퀀스에서 특정 위치 가져오기
각 시퀀스의 위치를 열별로 검색하기 위해
GetBitsAt
방법을 만들었습니다.private static string[] GetBitsAt(string[] sequence, int index)
{
if (index > sequence[0].Length)
throw new ArgumentOutOfRangeException(nameof(index));
string[] bits = new string[sequence.Length];
for (int i = 0; i < sequence.Length; i++)
{
bits[i] = sequence[i][index].ToString();
}
return bits;
}
이 방법은 문자열 그룹과 인덱스를 매개 변수로 받아들인다.C#의 문자열은 Chars[] 속성을 제공합니다.이 속성은 문자열의 색인 위치에서 단일 Char 대상을 통해 접근할 수 있습니다.따라서, 우리는 서열 그룹의 모든 문자열에서 특정 문자에 접근할 수 있다.본질적으로, 우리는 서열 그룹을 2차원 문자 행렬로 볼 수 있다.
따라서 이 방법은 열 방식에 따라 서열을 교체할 수 있다.교체할 열은 제공된
index
매개 변수에 달려 있습니다.계산 시퀀스에서 가장 흔히 볼 수 있는 원소
시퀀스 열에서 가장 일반적인 위치를 찾기 위해
MostCommon
방법을 만들었습니다.public static string MostCommon(string[] sequence)
=> sequence.GroupBy(v => v)
.OrderByDescending(g => g.Count())
.First()
.Key;
이 방법은 문자열 배열을 받아들이고 LINQ 조회 추출 시퀀스에서 가장 흔히 볼 수 있는 요소를 사용합니다.우리들은 이 문제를 몇 부분으로 나누자.
GroupBy(v => v)
: 서열 요소는 0
와 1
로 나뉜다.OrderByDescending(g => g.Count())
: 두 그룹은 각자의 원소 계수에 따라 내림차순으로 배열된다.First()
: 첫 번째 그룹의 첫 번째 요소를 반환합니다.Key
: 원소의 값을 추출한다.이 두 가지 방법이 있으면 남은 해결 방안은 보잘것없게 변한다.
var gammaRate = "";
var epsilonRate = "";
for (int i = 0; i < data[0].Length; i++)
{
string mostCommon = MostCommon(GetBitsAt(data, i));
gammaRate += mostCommon;
if (mostCommon.Equals("1"))
epsilonRate += "0";
else
epsilonRate += "1";
}
var result = Convert.ToInt32(gammaRate, 2) * Convert.ToInt32(epsilonRate, 2);
제2부분
두 번째 부분에서 우리는 가장 흔하고 가장 흔하지 않은 위치를 다시 한 번 추적해야 한다.그러나 이번에 우리는 우리의 가치관을 창조하는 것이 아니라 일련의 기준을 바탕으로 그것들을 없애는 것이다.
우리는 다시 열 방식으로 서열을 두루 훑어보았다.산소발생기의 정해진 값을 찾는 과정은 이전 수수께끼에서
delta
값을 생성하는 과정과 거의 같다.각 위치에서 가장 자주 사용하는 비트의 서열만 보존합니다.유일한 차이점은 0
비트와 1
비트의 수량이 같으면 1
비트의 서열을 이 위치에 유지한다는 것이다.이산화탄소 세척기의 정액치도 마찬가지다.각 위치에서 공통 비트가 가장 적은 시퀀스만 유지됩니다.이번에는 같은 상황에서 서열
0
을 이 위치에 유지한다.나는 이전 수수께끼 중의
MostCommon
와 GetBitAt
방법을 다시 사용했다.나는 이 해결 방안이 자랑스럽지 않다. 왜냐하면 일부 코드 복제가 있고, 일부 재구성은 틀림없이 질서정연하기 때문이다. 그러나 이것은 내가 처음 그것을 해결할 때 제기한 해결 방안이다.나는 이것이 경쟁적인 프로그래밍의 결점이라고 생각한다.여기에는 세 가지 새로운 방법이 있다.
HasMostCommon
방법은 주어진 서열이 이 위치에서 가장 흔히 볼 수 있는 위치가 있는지 검사한다.private static bool HasMostCommon(string sequence, string bit, int position)
=> sequence[position].ToString().Equals(bit);
GetOxygenRating
와 GetCO2Rating
는 각각 산소와 이산화탄소의 정해진 값을 귀속 방식으로 계산한다.private static string GetOxygenRating(string[] sequences, int index)
{
if (sequences.Length == 1)
return sequences[0];
string mostCommon = Utils.MostCommon(GetBitsAt(sequences, index));
List<string> common = new();
List<string> uncommon = new();
foreach (var sequence in sequences)
{
if (HasMostCommon(sequence, mostCommon, index))
common.Add(sequence);
else
uncommon.Add(sequence);
}
if (common.Count == uncommon.Count)
if (uncommon[0][index].ToString().Equals("1"))
return GetOxygenRating(uncommon.ToArray(), index + 1);
return GetOxygenRating(common.ToArray(), index + 1);
}
private static string GetCO2Rating(string[] sequences, int index)
{
if (sequences.Length == 1)
return sequences[0];
string mostCommon = Utils.MostCommon(GetBitsAt(sequences, index));
List<string> common = new List<string>();
List<string> uncommon = new List<string>();
foreach (var sequence in sequences)
{
if (HasMostCommon(sequence, mostCommon, index))
common.Add(sequence);
else
uncommon.Add(sequence);
}
if (common.Count == uncommon.Count)
if (common[0][index].ToString().Equals("0"))
return GetCO2Rating(common.ToArray(), index + 1);
return GetCO2Rating(uncommon.ToArray(), index + 1);
}
HasMostCommon
방법은 주어진 서열이 이 위치에서 가장 흔히 볼 수 있는 위치가 있는지 검사한다.해결 방안의 나머지 부분은 다시 보잘것없게 변했다.
string oxygen = GetOxygenRating(data, 0);
string co2 = GetCO2Rating(data, 0);
var result = (Convert.ToInt32(oxygen, 2) * Convert.ToInt32(co2, 2))
이 사람들만!
셋째 날은 여기까지야.나는 이 코드에 대해 그다지 만족하지 않는다.그것은 틀림없이 약간의 재구성과 정리가 필요하지만, 경쟁적인 프로그래밍에서는 때때로 실현 속도를 위해 형식을 희생해야 한다.
나는 내가 당신들에게 나의 해결 방안이 어떻게 작동하는지 더욱 깊이 있는 설명을 제공할 수 있기를 바랍니다.
myGithub Repo에서 이 해결 방안과 다른 해결 방안을 찾을 수 있습니다.
재미있게 놀았으면 좋겠습니다. 다음 회'코드 2021'에서 만나요!
Reference
이 문제에 관하여(C#:Day03 코드 2021의 출현 - 바이너리 진단 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/kalkwst/advent-of-code-2021-using-c-day03-binary-diagnostic-4665텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)