Skip to content

Instantly share code, notes, and snippets.

@kthompson
Last active December 8, 2022 15:55
Show Gist options
  • Save kthompson/e7aa9038900072baa23e66a71df89aa2 to your computer and use it in GitHub Desktop.
Save kthompson/e7aa9038900072baa23e66a71df89aa2 to your computer and use it in GitHub Desktop.
var lines = File.ReadAllLines("day1.txt");
var state = lines.Aggregate(new State(new ElfCalories(0, 0), new ElfCalories(0, 0)), (state, line) =>
{
if (line == string.Empty)
{
return NextState(state);
}
var calories = int.Parse(line);
var current = state.Current with { Calories = state.Current.Calories + calories };
state = new State(current, GetMaxElf(current, state.Max));
return state;
});
Console.WriteLine($"Elf: {state.Max.Elf + 1} with {state.Max.Calories} calories");
State NextState(State state) =>
new State(
new ElfCalories(state.Current.Elf + 1, 0),
GetMaxElf(state.Current, state.Max)
);
ElfCalories GetMaxElf(ElfCalories elf1, ElfCalories elf2) => elf1.Calories > elf2.Calories ? elf1 : elf2;
record ElfCalories(int Elf, int Calories);
record State(ElfCalories Current, ElfCalories Max);
using System.Collections.Immutable;
var lines = File.ReadAllLines("day1.txt");
var state = lines.Aggregate(new State(new ElfCalories(0, 0), ImmutableArray<ElfCalories>.Empty), (state, line) =>
{
if (line == string.Empty)
{
return NextState(state);
}
var calories = int.Parse(line);
state.Current.Calories += calories;
return state with { Max = GetMaxElves(state.Max.Add(state.Current)) };
});
foreach (var elfCalories in state.Max)
{
Console.WriteLine($"Elf {elfCalories.Elf + 1} with {elfCalories.Calories} calories");
}
Console.WriteLine($"{state.Max.Sum(elf => elf.Calories)} total calories");
State NextState(State state)
{
return new State(
new ElfCalories(state.Current.Elf + 1, 0),
GetMaxElves(state.Max.Add(state.Current))
);
}
ImmutableArray<ElfCalories> GetMaxElves(ImmutableArray<ElfCalories> elves)
{
return elves.DistinctBy(elf => elf.Elf).OrderByDescending(elf => elf.Calories).Take(3).ToImmutableArray();
};
class ElfCalories
{
public ElfCalories(int Elf, int Calories)
{
this.Elf = Elf;
this.Calories = Calories;
}
public int Elf { get; }
public int Calories { get; set; }
}
record State(ElfCalories Current, ImmutableArray<ElfCalories> Max);
var lines = File.ReadAllLines("day1.txt");
var total = 0;
foreach (var line in lines)
{
var parts = line.Split(' ');
var opp = GetHand(parts[0][0]);
var player = GetHand(parts[1][0]);
var score = GetScore(opp, player);
total += score;
}
Console.WriteLine(total);
Hand GetHand(char c) => (Hand)(c is >= 'A' and <= 'C' ? c - 'A' : c - 'X');
State GetOutcome(Hand opponent, Hand player)
{
if (opponent == player) return State.Draw;
return opponent switch
{
Hand.Rock => player == Hand.Paper ? State.Win : State.Loss,
Hand.Paper => player == Hand.Scissors ? State.Win : State.Loss,
Hand.Scissors => player == Hand.Rock ? State.Win : State.Loss,
_ => throw new ArgumentOutOfRangeException(nameof(opponent), opponent, null)
};
}
int GetScore(Hand opp, Hand player)
{
var shapeSelection = (int)player + 1;
var outcome = GetOutcome(opp, player);
return shapeSelection + (int)outcome;
}
enum State
{
Loss = 0,
Draw = 3,
Win = 6,
}
enum Hand
{
Rock = 0, Paper = 1, Scissors = 2,
}
var lines = File.ReadAllLines("day1.txt");
var total = 0;
foreach (var line in lines)
{
var parts = line.Split(' ');
var opp = GetHand(parts[0][0]);
var outcome = GetOutcomeFromString(parts[1][0]);
var player = GetPlayerHand(opp, outcome);
var score = GetScore(opp, player);
total += score;
}
Console.WriteLine(total);
Hand GetHand(char c) => (Hand)(c is >= 'A' and <= 'C' ? c - 'A' : c - 'X');
Hand GetPlayerHand(Hand opponent, Outcome outcome)
{
if (outcome == Outcome.Draw) return opponent;
return opponent switch
{
Hand.Rock => outcome == Outcome.Win ? Hand.Paper : Hand.Scissors,
Hand.Paper => outcome == Outcome.Win ? Hand.Scissors : Hand.Rock,
Hand.Scissors => outcome == Outcome.Win ? Hand.Rock : Hand.Paper,
_ => throw new ArgumentOutOfRangeException(nameof(opponent), opponent, null)
};
}
Outcome GetOutcomeFromString(char c) => (Outcome )(c - 'X');
Outcome GetOutcome(Hand opponent, Hand player)
{
if (opponent == player) return Outcome.Draw;
return opponent switch
{
Hand.Rock => player == Hand.Paper ? Outcome.Win : Outcome.Loss,
Hand.Paper => player == Hand.Scissors ? Outcome.Win : Outcome.Loss,
Hand.Scissors => player == Hand.Rock ? Outcome.Win : Outcome.Loss,
_ => throw new ArgumentOutOfRangeException(nameof(opponent), opponent, null)
};
}
int GetScore(Hand opp, Hand player)
{
var shapeSelection = (int)player + 1;
var outcome = GetOutcome(opp, player);
return shapeSelection + GetOutcomeScore(outcome);
}
int GetOutcomeScore(Outcome outcome) =>
outcome switch
{
Outcome.Loss => 0,
Outcome.Draw => 3,
Outcome.Win => 6,
_ => throw new ArgumentOutOfRangeException(nameof(outcome), outcome, null)
};
enum Outcome
{
Loss = 0,
Draw = 1,
Win = 2,
}
enum Hand
{
Rock = 0, Paper = 1, Scissors = 2,
}
// See https://aka.ms/new-console-template for more information
var lines = File.ReadAllLines("day3.txt");
var total = 0;
for (int i = 0; i < lines.Length; i+=3)
{
total += GetPriority(GetBadge(lines, i));
}
Console.WriteLine(total);
char GetBadge(string[] strings, int index)
{
var set1 = new HashSet<char>();
foreach (var c in strings[index])
{
set1.Add(c);
}
var set2 = new HashSet<char>();
foreach (var c in strings[index + 1])
{
if (set1.Contains(c))
set2.Add(c);
}
foreach (var c in strings[index + 2])
{
if (set2.Contains(c))
{
Console.WriteLine(c);
return c;
}
}
throw new InvalidOperationException();
}
int GetPriority(char c) =>
c switch
{
>= 'a' and <= 'z' => c - 'a' + 1,
>= 'A' and <= 'Z' => c - 'A' + 27,
_ => throw new InvalidOperationException()
};
var lines = File.ReadAllLines("day1.txt");
var total = 0;
foreach (var line in lines)
{
var elves = line.Split(',');
var elf1 = Span.Parse(elves[0]);
var elf2 = Span.Parse(elves[1]);
if (elf1.Overlaps(elf2))
total++;
}
Console.WriteLine(total);
record Span(int Start, int End)
{
public bool Overlaps(Span span) =>
Contains(span.Start) || Contains(span.End) ||
span.Contains(Start) || span.Contains(End);
public bool Contains(int position) => position >= Start && position <= End;
public bool Contains(Span span) => Contains(span.Start) && Contains(span.End);
public static Span Parse(string value)
{
var parts = value.Split('-');
return new Span(int.Parse(parts[0]), int.Parse(parts[1]));
}
}
using System.Collections.Immutable;
var lines = File.ReadAllLines("day1.txt");
var total = 0;
var puzzle = Puzzle.Parse(lines.TakeWhile(line => line.Trim() != "").ToArray());
var moveLines = lines.SkipWhile(line => line.Trim() != "").Skip(1).ToArray();
foreach (var line in moveLines)
{
// move 1 from 2 to 1
var command = line.Split(' ');
var quantity = int.Parse(command[1]);
var from = int.Parse(command[3]);
var to = int.Parse(command[5]);
puzzle.Move(from, to, quantity);
}
Console.WriteLine(puzzle.Tops);
record Puzzle(Dictionary<int, Stack<char>> Stacks)
{
public string Tops => string.Join("", Stacks.OrderBy(kv => kv.Key).Select(kv => kv.Value.Peek()));
public void Move(int from, int to, int quantity)
{
while (quantity-- > 0)
{
Move(from, to);
}
}
public void Move(int from, int to) => Stacks[to].Push(Stacks[from].Pop());
public static Puzzle Parse(string[] lines)
{
var ids = lines[^1]
.Split(' ', StringSplitOptions.RemoveEmptyEntries)
.Select(id => int.Parse(id.Trim()))
.ToArray();
var stacks = ids.ToDictionary(id => id, _ => new Stack<char>());
for (var i = lines.Length - 2; i >= 0; i--)
{
// first char index is 1
// next is 5
var line = lines[i];
foreach (var id in ids)
{
var index = 1 + 4 * (id - 1);
if (index < line.Length && line[index] != ' ')
stacks[id].Push(line[index]);
}
}
return new Puzzle(stacks);
}
}
using System.Collections.Immutable;
var lines = File.ReadAllLines("day1.txt");
var total = 0;
var puzzle = Puzzle.Parse(lines.TakeWhile(line => line.Trim() != "").ToArray());
var moveLines = lines.SkipWhile(line => line.Trim() != "").Skip(1).ToArray();
foreach (var line in moveLines)
{
// move 1 from 2 to 1
var command = line.Split(' ');
var quantity = int.Parse(command[1]);
var from = int.Parse(command[3]);
var to = int.Parse(command[5]);
puzzle.Move(from, to, quantity);
}
Console.WriteLine(puzzle.Tops);
record Puzzle(Dictionary<int, Stack<char>> Stacks)
{
public string Tops => string.Join("", Stacks.OrderBy(kv => kv.Key).Select(kv => kv.Value.Peek()));
public void Move(int from, int to, int quantity)
{
var stack = new Stack<char>();
var a = quantity;
while (a-- > 0)
{
stack.Push(Stacks[from].Pop());
}
a = quantity;
while (a-- > 0)
{
Stacks[to].Push(stack.Pop());
}
}
public static Puzzle Parse(string[] lines)
{
var ids = lines[^1]
.Split(' ', StringSplitOptions.RemoveEmptyEntries)
.Select(id => int.Parse(id.Trim()))
.ToArray();
var stacks = ids.ToDictionary(id => id, _ => new Stack<char>());
for (var i = lines.Length - 2; i >= 0; i--)
{
// first char index is 1
// next is 5
var line = lines[i];
foreach (var id in ids)
{
var index = 1 + 4 * (id - 1);
if (index < line.Length && line[index] != ' ')
stacks[id].Push(line[index]);
}
}
return new Puzzle(stacks);
}
}
var input = "hlfhfzffqnnrlnnvnmmgbgwgttbppcrcnnmdmfdmmgwwrrqnrrscrctcbttvcvtvvhchjhccjgjttmddplplqplqlbqlblrrbrvvprpffpmmzpmpcczjzzbwwfssvrrvggncgncgcwczzswwqqjjflffpwfpwpbwpwpdpbpvvqffcfcjffjllncczfzzmhzzmddgdrgrwwjzzdjjsnjsjfsjsjhhcchlccchqchhzzpnngdgndnpnppsdsggbvgvgpprqrqmmlzmzllvrrcvclcwczcqqcdcfcqqmmzbzdzdjzdjdmjdjzdjjcvjvcjvcvssltstttfbtftrfrlrdllrqqfssslccjdcjdjfdjfjqjnqjnjnrnddtnndtnnztzqztqztqzzpmzmggzrgrwwdqwdwcdwdnnmlmgmtmtstwssbffcnclclnclcjjcjpcpqcpqcpqpmqqfccpcjppnspsnnzggnpntndtdqtthwhnhwnwllzhlzhlzzghzghhlhvhwhjhfjjcnjnvjnjvvqccdmmgddllnmnrrdtdnncggfhgfglfgfmfnnpvvggznnwvnwwfgghrrfwrwzwszzzldzdldhlhblhblhbbbgjgsjggmqqmrrzggrhhwpwdpwdpwplpgpbggtssqffbqfbqbnnsqnqfnngcnnmwnmnbmmmslsjllbtbbpllltzzhgzztllsdllrvvhvjvbbhcbhchmchcctbcttvccgwcwpcchrcrdrdggcrrntrrfllcffbdfflrrrgbgrbbbdqbqjbbgbgrrqwqtwqwhwghwhzwwcswsnwnqqjhjhwhfwhffdfgddgjgsjgjhgglhlwhlhssfqfhhdmdnmnppdcddfzzhmhqqntqnnjvnjvjddcvcgcbgbbpjbjtbjjfgftgffplljfjrrhqqpddlssrvsrvrpppsllsdsqqqzzfttqsqzssjbbrnbnnrbbsrshsrrshrhwhbwbrrsrfrttfqtfqqfddvrvjrjvjsjhjsjdjqdjjlqjjjgcjcmcncfcrcwrwsrsslffzszmsszrsssrnrjjvbvpvcppptbbhhrddbcbggbqbmmsqqwggfpfbblmldmmpmwpwfwjfjsjnjmmpllccjzcjcwwpswshhpthhzchctcbcrrrrmvrvrdvvjmmvgmgwglghllvmllzlzzsvzzrmmhnnsjnnpvpwvpwwmvwwdqqdffhhhmccfgfvggchcctrrmdrrhrhnhnzzgpzzgttnhthvhzzqvvvwpwqpqdppsnnrgnnhphphmhcmcrmrvvqlvqqsccqhchzhwwmvmzmczzgsgdsggthgglrlnrlllbdllhwlwltwwcswsgssbhbsbvsbsbwbhbnncrcllttbrbppjccfpfhhgshschsccmrcmmcrrrzvvrcrggmwgwjwnwjjbffjddjnjgngqgdgnndznndvvfqfgfvvrvqrvvpllnsszbsbdbbdzbdbzbqbzznrznzjzpptcptccvwccfscffrftrrsnsvvswvvhbhzzfbzffncchhcnngzzcpcmmfttsntnjjsccqbcqqmzzgppdhppdtppmffgtgvvlzlpptdtttdppqjqtqctcrrzsswwtnwtnwnqqvbbdgjhvmmzpnhfvsbddzhgdwcnfdstvhhbzlzcfjwhlptbhmbmblprtsdmrdhbbbwpplnzgdnrzjmgzgpqbggnqvwwtntzgfwqrztqtdrsnhpfzswptggnvbszdcrmrhhtlrrfnpqrnpwrbmhlfwmdqqdbqrwbzqjbzwrgmbgrtzrhdclqfgsrtsgfwqrnnqgwsncmpgffggssrqvwjlhpsghbqdtzwmvzzvcmzsjqvprvcqwqjbcqcqrhpwwcsrscgmfdppbgvmnrdfrppblznbstnjzwwgstjvtprjbhtpdfgrhdjnjmnlbfwggzhcngvcwvcfpcwdtdppwjrdzsnjlnrzbfqqshlnzvwsmscgpfwjzhtwgfwgzdhbdwwzbsmfwwbmvrlrpswnjlmfbfzhwvcmgwfzssmmtjlwtrpwpwgnspbgchdncbfcpjsvtzjqtwqwjwgbhrbwvhqbcstsgsnwsjmhrlrvzgqhqfrmnrjdrhdjwcwctpdrzctlvnfzmzwhsnfprlzgzjpqvzchlmvbhffhpfjtvsdbvbdmwgvmqpflhwwndbqthmmwshdtspsrvqdflmmzwbqbqmpfdwjmvpbzdnqzfmhzdgldqjjvgpfcqftvjzwnzmfqdggrwlfzdhjnhmtrjbnllgqpntwmhnwtglnqdwbqdblpwnnrdwzpsqzfwqcmhqhnpsdcwvdldphgnrtqzdbnnzdzfttldrqcztlvlrgpdqzrcthslmtqhfvbzrfgnlrprcpbsctqhspbhnjtzrzhqjzszbzdthttqmbznzssftztwlggmdqqdtfllqjzjtvpgjfhtbwtbmtjplqnbdmsvlnqcwtdbdvfjnzgsmpnhbvvwwfbrgffjqfsccdjdwvbsdhqwfzvcpjzjbdjgrdctjplhwbdhhnbnwstvndnnwtsgbhzbvwdshvmnbwsthlrggtmddvjbfzfrnrdrqfjpslrccctzpjbwpdbhlbzfmwbltcqfngdprvfhgcszdtpnrcpdmllfnlspgrdrpwqmqbmrglvlrsmrfqrtzzgjcvqtqzpmghjrvmdmvvqztrjzbzjwdqsmrwpqnswbzhjbzzhdvmnfdsztzdzrjssgnnfqvbtsqrrmcppjgrmnstrnrlwjvvcczqlcbmwqzdfpssfwdfrvwtstwchdgwtrhhcmppcqlmrqlnwqccfphsdhbsbmtjvpcwwjrmrllbpnrmpbvwgwbftpdpphccwqcblcnvvbbppscmnjqgddllbnbvmmqzdffrrjtqwllzgpqrmnlfqrptzqmdmnrfnjpvqvjbsqrhljslgqqcqqtmtbwjrpphtjgjbqpzmzrzjrfjwcdcnbsjfljclffjplnrrcfbmhphtcjrzlrvvjcznpgpnrdwwqvgnbnzqnlcghhgwvhqbvjzfbdvhrzlqfbtlqhpltfjlfpbnjbphmmpntzqgjmwjtchwmlwvfjmfflqzpqnvvrgnbddzlfpdpdjghfgbsfddjspnfdwvqppncmdgfrnvrpcrflhgjgbwdsbwblfcwbtlrrnjjdhbvmrzgsvjwgfnnhqfbvhprlmwwqgclzlbqbrdspcbhftmdscsmpwrggrmnsvjphjmzmmrlrhnmdhwjlbmjchtvsrcplfspsssjznmzcrqnsjjtwjzvlhshbptqwwvjhjvzrhphphsbphpnzpfbwcdnqrhrrvlrwrztlpqnrcfzrncsvpzqzgslrlrwhvtgjmfncldqmvshlmnlpqbgvnwqfcthgrgllmqrjqmfgznspgltpptglpdcvhtzsprprbldbzhbmjsqzwvjggwhsczltcvgwqhspzpzvljwqjgrgtwswjdswlzjzslrsslvqzncjwhbbjpbdthqpgmhfglggmlrgwdsplgscrwstntvrhjzjjlshtgmnnhvsjwfmcjbpzjcstmnpvtbgrfcfdwjljsrfhdphrdcslwhgvlnwltwchplvfzntfgcnlsvzrvnnczhhqdlwjvqprhmtjdtwmppffmszzzqtfrgnhnzqgqzhrjzgntcszstrfhhtptgvswvzvjcgcntmhzzmdgsmtgzhpfvqfnwmsjdhtfgmmbrrfsdlptchqqzqdqjncmtpznfssrcnmcdnthglmfzsfgltrndqsfmdftmfgchbwmzgrtjvgqtshlltthnnpqnzfrchzhdzrrnpzvfzblrmhwdwjnqdptlbvndmmlhzhvsfdlmlhqrgqqzsdqtpczwcrwcbsftvvphfbwjrvrnrcqbbcsqgnhltwzvllljcvpwjgslbmngcdmpdvjlgcnrzwqjdgrblncpqmrgjmpqjzvdmcmwfnwqlszdgwqdfznhsnpsjrfwrqpqmpvhstmzgqblfmcfvwljbhdfhdmqcvrwnqcstwtzgmng";
Console.WriteLine(DetectMarker(input, 14));
int DetectMarker(string signal, int size)
{
var marker = signal.Take(size).ToArray();
var index = size - 1;
while (marker.Distinct().Count() < size)
{
index++;
marker[index % size] = signal[index];
}
return index + 1;
}
// build map
var input = File.ReadAllLines("day1.txt");
var width = input[0].Length;
var height = input.Length;
var map = new int[width, height];
var visible = new int[width, height];
for (var y = 0; y < height; y++)
for (var x = 0; x < width; x++)
{
map[x, y] = input[x][y] - '0';
}
var count = 0;
for (var y = 0; y < height; y++)
for (var x = 0; x < width; x++)
{
if (IsVisible(x, y))
{
visible[x, y] = 1;
count++;
}
}
Console.WriteLine(count);
bool IsVisible(int x, int y)
{
if (x == 0 || y == 0) return true;
if (x == width - 1 || y == height - 1) return true;
var currHeight = map[x, y];
// from left
if (IsVisibleFrom(x, y, -1, 0, currHeight)) return true;
// from right
if (IsVisibleFrom(x, y, 1, 0, currHeight)) return true;
// from top
if (IsVisibleFrom(x, y, 0, -1, currHeight)) return true;
// from bottom
if (IsVisibleFrom(x, y, 0, 1, currHeight)) return true;
return false;
}
bool IsVisibleFrom(int x, int y, int dx, int dy, int maxHeight)
{
// out of bounds
if (x + dx < 0 || x + dx >= width) return true;
if (y + dy < 0 || y + dy >= height) return true;
var currHeight = map[x + dx, y + dy];
if (currHeight >= maxHeight) return false;
return IsVisibleFrom(x + dx, y + dy, dx, dy, maxHeight);
}
// build map
var input = File.ReadAllLines("day1.txt");
var width = input[0].Length;
var height = input.Length;
var map = new int[width, height];
for (var y = 0; y < height; y++)
for (var x = 0; x < width; x++)
{
map[x, y] = input[x][y] - '0';
}
var maxScore = -1;
for (var y = 0; y < height; y++)
for (var x = 0; x < width; x++)
{
maxScore = Math.Max(maxScore, GetScenicScore(x, y));
}
Console.WriteLine(maxScore);
int GetScenicScore(int x, int y)
{
var h = map[x, y];
var left = GetViewingDistance(x, y, -1, 0, h);
var right = GetViewingDistance(x, y, 1, 0, h);
var up = GetViewingDistance(x, y, 0, -1, h);
var down = GetViewingDistance(x, y, 0, 1, h);
return left * right * up * down;
}
int GetViewingDistance(int x, int y, int dx, int dy, int maxHeight, int trees = 0)
{
// out of bounds
if (x + dx < 0 || x + dx >= width) return trees;
if (y + dy < 0 || y + dy >= height) return trees;
var currHeight = map[x + dx, y + dy];
// tree blocks
if (currHeight >= maxHeight) return trees + 1;
return GetViewingDistance(x + dx, y + dy, dx, dy, maxHeight, trees + 1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment