Skip to content

Instantly share code, notes, and snippets.

@Stevie-O
Created December 14, 2023 21:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Stevie-O/6585c7139963244916afbbb5c87e47c4 to your computer and use it in GitHub Desktop.
Save Stevie-O/6585c7139963244916afbbb5c87e47c4 to your computer and use it in GitHub Desktop.
aoc-2023-day14-state-compressor
enum RockType { None, Round, Cube }
interface IPlatformState
{
int Width { get; }
int Height { get; }
RockType GetRockAt(int row, int col);
}
interface IBitstreamWriter
{
void Write(uint value, int bitLength);
}
/// <summary>Compress a platform state after an eastward tilt.</summary>
void CompressPlatformState(IPlatformState state, IBitstreamWriter writer)
{
var h = state.Height;
var w = state.Width;
for (int r = 0; r < h; r++)
{
uint count = 0;
uint size = 0;
uint size_limit = 0;
int size_bits = 0;
bool empty = false;
for (int c = w - 1; c >= 0; --c)
{
var rock = state.GetRockAt(r, c);
switch (rock)
{
case RockType.Cube:
if (size_bits > 0)
{
// two horizontally adjacent cubes: ##
writer.Write(count, size_bits);
size = size_limit = count = 0; size_bits = 0;
empty = false; // empty can't be true if size==0
}
break;
case RockType.Round:
// this cannot happen after a tilt
if (empty) throw new Exception("invalid platform state");
++count;
goto round_or_dot;
case RockType.None:
empty = true;
round_or_dot:
++size;
if (size > size_limit)
{
if (size == 1) { size_limit = 1; size_bits = 1; }
else { size_limit <<= 1; size_bits++; }
}
break;
}
}
if (size_bits > 0) { writer.Write(count, size_bits); }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment