adventofcode/2020/Program.cs
2020-12-02 11:18:16 -05:00

121 lines
3.7 KiB
C#

using System;
using static System.Console;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Xunit;
namespace AdventOfCode {
public class Program {
static string RootDir =
Environment.GetEnvironmentVariable("HOME") + "/src/adventofcode/2020/";
static List<int> ReadInts(string filename) {
string[] lines = File.ReadAllLines(filename);
return lines.Select(int.Parse).ToList();
}
static int Day1Part1(List<int> numbers) {
for (var i = 0; i < numbers.Count; i++) {
for (var j = i + 1; j < numbers.Count; j++) {
if (numbers[i] + numbers[j] == 2020) {
return numbers[i] * numbers[j];
}
}
}
throw new ArgumentException("no pair of numbers summed to 2020");
}
static int Day1Part2(List<int> numbers) {
for (var i = 0; i < numbers.Count; i++) {
for (var j = i + 1; j < numbers.Count; j++) {
for (var k = j + 1; k < numbers.Count; k++) {
if (numbers[i] + numbers[j] + numbers[k] == 2020) {
return numbers[i] * numbers[j] * numbers[k];
}
}
}
}
throw new ArgumentException("no triple of numbers summed to 2020");
}
[Fact]
static void Day1Test() {
var emptyInput = new List<int>();
var bogusInput = new List<int>() {
111, 222, 333, 444, 555, 666, 777, 888, 999
};
var exampleInput = new List<int>() {
1721, 979, 366, 299, 675, 1456
};
var testInput = ReadInts(RootDir + "day1.txt");
Assert.Throws<ArgumentException>(() => Day1Part1(emptyInput));
Assert.Throws<ArgumentException>(() => Day1Part1(bogusInput));
Assert.Equal(514579, Day1Part1(exampleInput));
Assert.Equal(355875, Day1Part1(testInput));
Assert.Throws<ArgumentException>(() => Day1Part2(emptyInput));
Assert.Throws<ArgumentException>(() => Day1Part2(bogusInput));
Assert.Equal(241861950, Day1Part2(exampleInput));
Assert.Equal(140379120, Day1Part2(testInput));
}
static bool IsPasswordValid1(string spec) {
string[] tokens = spec.Split(' ');
string[] numbers = tokens[0].Split('-');
int min = int.Parse(numbers[0]);
int max = int.Parse(numbers[1]);
char required = tokens[1][0];
string password = tokens[2];
int count = 0;
for (int i = 0; i < password.Length; i++) {
if (password[i] == required) {
count++;
}
}
return min <= count && count <= max;
}
static bool IsPasswordValid2(string spec) {
string[] tokens = spec.Split(' ');
string[] numbers = tokens[0].Split('-');
int lowIndex = int.Parse(numbers[0]) - 1;
int highIndex = int.Parse(numbers[1]) - 1;
char required = tokens[1][0];
string password = tokens[2];
return
(password[lowIndex] == required && password[highIndex] != required) ||
(password[lowIndex] != required && password[highIndex] == required);
}
static int Day2Part1() {
return File.ReadAllLines(RootDir + "day02.txt").Count(IsPasswordValid1);
}
static int Day2Part2() {
return File.ReadAllLines(RootDir + "day02.txt").Count(IsPasswordValid2);
}
[Fact]
static void Day2Test() {
Assert.True(IsPasswordValid1("1-3 a: abcde"));
Assert.False(IsPasswordValid1("1-3 b: cdefg"));
Assert.True(IsPasswordValid1("2-9 c: ccccccccc"));
Assert.Equal(603, Day2Part1());
Assert.True(IsPasswordValid2("1-3 a: abcde"));
Assert.False(IsPasswordValid2("1-3 b: cdefg"));
Assert.False(IsPasswordValid2("2-9 c: ccccccccc"));
Assert.Equal(404, Day2Part2());
}
static void Main(string[] args) {
Day2Test();
}
}
}