A GitHub blog, usefull to me, hope the same for you.
I love the minimalist design of this event. I know about this annual event for coders through my nephew Cyrille. Not very confident at first, I had finished last year’s puzzles a few months late. Let try to do it using C# and Python.
Here we have a groups of number separated with newlines and an empty line as a separator. We need to find the sum of these groups of number and find the bigger.
void Day1()
{
string[] lines = File.ReadAllLines("day1.txt");
var l = new List<int>() { 0 };
foreach (string line in lines)
if (line == "")
l.Add(0);
else
l[l.Count - 1] += int.Parse(line);
Console.WriteLine(l.Max());
}
After the remark of my mentor Johann that this algorithm is “not terrible”
static void Day1()
{
var c = 0;
var m = 0;
foreach (string line in System.IO.File.ReadLines(@"day1.txt"))
if (line == "")
{
if (c > m) m = c;
c = 0;
}
else
c += int.Parse(line);
// last group of values
if (c > m) m = c;
Console.WriteLine(m);
}
To avoid redondant condition
static void Day1()
{
var c = 0;
var m = 0;
foreach (string line in System.IO.File.ReadLines(@"day1.txt"))
{
if (line == "") c = 0;
else c += int.Parse(line);
if (c > m) m = c;
}
Console.WriteLine(m);
}
Using enumerator
static void Day1()
{
var e = File.ReadLines(@"day1.txt").GetEnumerator();
var last = !e.MoveNext();
string line;
var c = 0;
var m = 0;
while (!last)
{
line = e.Current;
if (line == "") c = 0;
else c += int.Parse(line);
last = !e.MoveNext();
if (c > m && (line == "" || last)) m = c;
}
Console.WriteLine(m);
}
After just thinking twice
protected override string Part1(string inp)
{
var elfCalories = 0;
var maxCalories = 0;
foreach (var line in ToLines(inp))
{
elfCalories = line == string.Empty ? 0 : elfCalories + int.Parse(line);
maxCalories = Math.Max(maxCalories, elfCalories);
}
return maxCalories.ToString();
}
Part 2 need to have top 3
static void Day1p2()
{
var c = 0;
var l = new List<int>();
foreach (string line in System.IO.File.ReadLines(@"day1.txt"))
if (line == "")
{
l.Add(c);
c = 0;
}
else
c += int.Parse(line);
l.Add(c);
Console.WriteLine(l.OrderByDescending(x=>x).Take(3).Sum());
}
I realized that in C#, String.Empty and “” produces exactly the same code
“String.Empty” is more self explanatory and makes the code easier to read.
here I must code the rules of the game and decode the inputs First version not terrible, second version better
static void Day2()
{
var input = System.IO.File.ReadLines(@"day2.txt");
var codes = new Dictionary<string, string>
{
{"A","Rock" },
{"B" ,"Paper"},
{"C" , "Scissors"},
{"X","Rock" },
{"Y" ,"Paper"},
{"Z" , "Scissors"}
};
var values = new List<string> { "Rock", "Paper", "Scissors"};
var defeats = new List<string> { "RockScissors", "ScissorsPaper", "PaperRock" };
var score = 0;
foreach (var (opponent, you) in input.Select(x => x.Split(" ")).Select(x => (codes[x[0]], codes[x[1]])))
{
score += 1 + values.IndexOf(you);
if (!defeats.Contains(opponent + you))
{
score += you == opponent ? 3 : 6;
}
}
Console.WriteLine(score);
}
static void Day2()
{
var input = System.IO.File.ReadLines(@"day2.txt");
// var action = new List<string> { "Rock", "Paper", "Scissors" };
var defeats = new List<(int,int)> { (1,3), (3,2), (2,1) };
var score = 0;
foreach (var (opponent, you) in input.Select(x => x.Split(" ")).Select(x => ("ABC".IndexOf(x[0][0])+1,"XYZ".IndexOf(x[1][0])+1)))
{
score += you;
if (!defeats.Contains((opponent,you)))
{
score += you == opponent ? 3 : 6;
}
}
Console.WriteLine(score);
}
static void Day2p2()
{
var input = System.IO.File.ReadLines(@"day2.txt");
// var action = new List<string> { "Rock", "Paper", "Scissors" };
var score = 0;
var defeats = new List<(int, int)> { (1, 3), (3, 2), (2, 1) };
foreach (var (opponent, ending) in input.Select(x => x.Split(" ")).Select(x => ("ABC".IndexOf(x[0][0]) + 1, "XYZ".IndexOf(x[1][0]) + 1)))
{
var you = opponent;
if (ending == 1)
you = defeats.Find(x => x.Item1 == opponent).Item2;
else if (ending == 3)
you = defeats.Find(x => x.Item2 == opponent).Item1;
score += you;
score += (ending-1) * 3;
}
Console.WriteLine(score);
}
static void Day3()
{
var input = System.IO.File.ReadLines(@"day3.txt");
var score = 0;
foreach (var line in input)
{
var l = line.Length;
var (a, b) = (line.Substring(0, l / 2), line.Substring(l / 2, l / 2));
var r = (int)a.First(x => b.Contains(x));
var p = r >= (int)'a' ? r - (int)'a' + 1 : r - (int)'A' + 27;
score += p;
}
Console.WriteLine(score);
}
static void Day3p2()
{
var input = System.IO.File.ReadAllLines(@"day3.txt");
var score = 0;
for (var i = 0; i < input.Length / 3; i++)
{
var (a, b, c) = (input[i * 3], input[i * 3 + 1], input[i * 3 + 2]);
var r = (int)a.First(x => b.Contains(x) && c.Contains(x));
var p = r >= (int)'a' ? r - (int)'a' + 1 : r - (int)'A' + 27;
score += p;
}
Console.WriteLine(score);
}
# Day 4 Coding some intervals
static void Day4()
{
var input = System.IO.File.ReadAllLines(@"day4.txt");
var r = (string x) => { var r = x.Split("-"); return (start: int.Parse(r[0]), end: int.Parse(r[1])); };
var score = 0;
foreach ( var (a,b) in input.Select(x => x.Split(",")).Select(x => (r(x[0]), r(x[1]))) )
{
if ((b.start >= a.start && b.end <= a.end) || (a.start >= b.start && a.end <= b.end))
score++;
}
Console.WriteLine(score);
}
static void Day4p2()
{
var input = System.IO.File.ReadAllLines(@"day4.txt");
var r = (string x) => { var r = x.Split("-"); return (start: int.Parse(r[0]), end: int.Parse(r[1])); };
var score = 0;
foreach (var (a, b) in input.Select(x => x.Split(",")).Select(x => (r(x[0]), r(x[1]))))
{
if ( ( a.start <= b.start && b.start <= a.end) || (b.start <= a.start && a.start <= b.end))
score++;
}
Console.WriteLine(score);
}
Stacks But better if I just used lists instead ?
static void Day5()
{
var input = System.IO.File.ReadLines(@"day5.txt").GetEnumerator();
input.MoveNext();
var w = 1 + (System.IO.File.ReadLines(@"day5.txt").First().Length) / 4;
var stacks = new Stack<char>[w];
foreach (var i in Enumerable.Range(0, w))
stacks[i] = new Stack<char>();
while (input.Current[1] != '1' )
{
foreach (var i in Enumerable.Range(0, w))
if (input.Current[i*4+1] != ' ')
stacks[i].Push(input.Current[i * 4 + 1]);
input.MoveNext();
}
input.MoveNext();
// reversing the stacks because of read order of the input :-(
foreach (var i in Enumerable.Range(0, w))
{
var l = new Stack<char>();
foreach (var c in stacks[i])
l.Push(c);
stacks[i] = l;
}
while (input.MoveNext())
{
Console.WriteLine(input.Current);
var i = input.Current.Replace("move ", "").Replace(" from ", ",").Replace(" to ", ",").Split(',').Select(x => int.Parse(x)).ToList();
var (amount, origin, destination) = (i[0], i[1], i[2]);
foreach (var c in Enumerable.Range(1,amount))
{
stacks[destination-1].Push(stacks[origin-1].Pop());
Console.WriteLine(string.Join("", stacks.Select(x => x.FirstOrDefault(' '))));
}
}
}
static void Day5p2()
{
var input = System.IO.File.ReadLines(@"day5.txt").GetEnumerator();
input.MoveNext();
var w = 1 + (System.IO.File.ReadLines(@"day5.txt").First().Length) / 4;
var stacks = new Stack<char>[w];
foreach (var i in Enumerable.Range(0, w))
stacks[i] = new Stack<char>();
while (input.Current[1] != '1')
{
foreach (var i in Enumerable.Range(0, w))
if (input.Current[i * 4 + 1] != ' ')
stacks[i].Push(input.Current[i * 4 + 1]);
input.MoveNext();
}
input.MoveNext();
// reversing the stacks because of read order of the input :-(
foreach (var i in Enumerable.Range(0, w))
{
var l = new Stack<char>();
foreach (var c in stacks[i])
l.Push(c);
stacks[i] = l;
}
while (input.MoveNext())
{
Console.WriteLine(input.Current);
var i = input.Current.Replace("move ", "").Replace(" from ", ",").Replace(" to ", ",").Split(',').Select(x => int.Parse(x)).ToList();
var (amount, origin, destination) = (i[0], i[1], i[2]);
var mover = new Stack<char>();
foreach (var c in Enumerable.Range(1, amount))
mover.Push(stacks[origin - 1].Pop());
foreach (var c in mover)
stacks[destination - 1].Push(c);
Console.WriteLine(string.Join("", stacks.Select(x => x.FirstOrDefault(' '))));
}
Console.WriteLine("END "+string.Join("", stacks.Select(x => x.FirstOrDefault(' '))));
}
Spend less time on this one to process the input, so less pain !
static void Day6()
{
var input = System.IO.File.ReadLines(@"day6.txt").First();
var marker = new Queue<char>();
var pos = 1;
foreach (var c in input)
{
if (marker.Count == 4) marker.Dequeue();
marker.Enqueue(c);
if (marker.Count == 4 && marker.GroupBy(x => x).Select(y => y.Count()).Max() == 1) break;
pos++;
}
Console.WriteLine("Restult = " + pos);
}
static void Day6p2()
{
var input = System.IO.File.ReadLines(@"day6.txt").First();
var marker = new Queue<char>();
var pos = 1;
foreach (var c in input)
{
if (marker.Count == 14) marker.Dequeue();
marker.Enqueue(c);
if (marker.Count == 14 && marker.GroupBy(x => x).Select(y => y.Count()).Max() == 1) break;
pos++;
}
Console.WriteLine("Restult = " + pos);
}
I used a string to uniquely identify the directories, and string.Contains() to identify the parents of a given directory.
static void Day7()
{
var input = System.IO.File.ReadLines(@"day7.txt");
var contents = new Dictionary<string, int>
{
{ "#/", 0 }
};
var curdir = new Stack<string>();
foreach (var line in input)
{
if (line[0] == '$')
{
if (line[2..4] == "cd")
{
var dir = line[5..];
if (dir == "..")
{
curdir.Pop();
}
else curdir.Push(dir);
Console.WriteLine("#" + string.Join("-", curdir.Reverse()));
}
}
else
{
if (line[0..4] != "dir ")
{
var dir = "#" + string.Join("-", curdir.Reverse());
var size = int.Parse(line.Split(" ")[0]);
// tricky here we add also to parents
foreach (var d in contents.Keys.Where(x => dir.Contains(x)))
contents[d] += size;
} else
{
var dir = "#" + string.Join("-", curdir.Reverse()) + "-" + line[4..];
contents.Add(dir, 0);
}
}
}
var atMost = 100000;
var res = contents.Values.Where(x => x <=atMost).Sum();
Console.WriteLine("Result :" + res);
}
static void Day7p2()
{
var input = System.IO.File.ReadLines(@"day7.txt");
var contents = new Dictionary<string, int>
{
{ "#/", 0 }
};
var curdir = new Stack<string>();
foreach (var line in input)
{
if (line[0] == '$')
{
if (line[2..4] == "cd")
{
var dir = line[5..];
if (dir == "..")
{
curdir.Pop();
}
else curdir.Push(dir);
Console.WriteLine("#" + string.Join("-", curdir.Reverse()));
}
}
else
{
if (line[0..4] != "dir ")
{
var dir = "#" + string.Join("-", curdir.Reverse());
var size = int.Parse(line.Split(" ")[0]);
// tricky here we add also to parents
foreach (var d in contents.Keys.Where(x => dir.Contains(x)))
contents[d] += size;
}
else
{
var dir = "#" + string.Join("-", curdir.Reverse()) + "-" + line[4..];
contents.Add(dir, 0);
}
}
}
var total = 70000000;
var freeRequired = 30000000;
var used = contents["#/"];
var toBeFreed = freeRequired - (total - used);
var res = contents.Values.Where(x => x >= toBeFreed).Min();
Console.WriteLine("Result :" + res);
}