From aa905069434e6b2e0d94becca70e02574a2ceee0 Mon Sep 17 00:00:00 2001 From: Alexander Sigler Date: Thu, 8 Dec 2022 15:39:18 -0800 Subject: [PATCH] Initial Commit --- .gitignore | 263 ++++++++++++++++++ AdventOfCode.sln | 25 ++ AdventOfCode/AdventOfCode.csproj | 19 ++ AdventOfCode/Common/AOCAttribute.cs | 15 + AdventOfCode/Common/AOCExtensions.cs | 12 + .../Common/TextPlainInputFormatter.cs | 35 +++ .../Controllers/AdventOfCodeController.cs | 51 ++++ AdventOfCode/Models/AOCDay.cs | 79 ++++++ AdventOfCode/Models/AOCRequest.cs | 17 ++ AdventOfCode/Models/AOCResponse.cs | 35 +++ AdventOfCode/Models/AOCVersion.cs | 15 + AdventOfCode/Models/IAOCService.cs | 12 + AdventOfCode/Program.cs | 26 ++ AdventOfCode/Properties/launchSettings.json | 31 +++ AdventOfCode/Startup.cs | 70 +++++ AdventOfCode/_2022/Day1.cs | 65 +++++ AdventOfCode/_2022/Day2.cs | 114 ++++++++ AdventOfCode/_2022/Day3.cs | 66 +++++ AdventOfCode/appsettings.Development.json | 9 + AdventOfCode/appsettings.json | 10 + 20 files changed, 969 insertions(+) create mode 100644 .gitignore create mode 100644 AdventOfCode.sln create mode 100644 AdventOfCode/AdventOfCode.csproj create mode 100644 AdventOfCode/Common/AOCAttribute.cs create mode 100644 AdventOfCode/Common/AOCExtensions.cs create mode 100644 AdventOfCode/Common/TextPlainInputFormatter.cs create mode 100644 AdventOfCode/Controllers/AdventOfCodeController.cs create mode 100644 AdventOfCode/Models/AOCDay.cs create mode 100644 AdventOfCode/Models/AOCRequest.cs create mode 100644 AdventOfCode/Models/AOCResponse.cs create mode 100644 AdventOfCode/Models/AOCVersion.cs create mode 100644 AdventOfCode/Models/IAOCService.cs create mode 100644 AdventOfCode/Program.cs create mode 100644 AdventOfCode/Properties/launchSettings.json create mode 100644 AdventOfCode/Startup.cs create mode 100644 AdventOfCode/_2022/Day1.cs create mode 100644 AdventOfCode/_2022/Day2.cs create mode 100644 AdventOfCode/_2022/Day3.cs create mode 100644 AdventOfCode/appsettings.Development.json create mode 100644 AdventOfCode/appsettings.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..06482ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,263 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +################### +# compiled source # +################### +*.com +*.class +*.dll +*.exe +*.pdb +*.dll.config +*.cache +*.suo +# Include dlls if they’re in the NuGet packages directory +!/packages/*/lib/*.dll +# Include dlls if they're in the CommonReferences directory +!*CommonReferences/*.dll +#################### +# VS Upgrade stuff # +#################### +_UpgradeReport_Files/ +############### +# Directories # +############### +bin/ +obj/ +TestResults/ +################### +# Web publish log # +################### +*.Publish.xml +############# +# Resharper # +############# +/_ReSharper.* +*.ReSharper.* +############ +# Packages # +############ +# it’s better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip +###################### +# Logs and databases # +###################### +*.log +*.sqlite +# OS generated files # +###################### +.DS_Store? +ehthumbs.db +Icon? +Thumbs.db + + +# User-specific files +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studo 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +bower_components/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt \ No newline at end of file diff --git a/AdventOfCode.sln b/AdventOfCode.sln new file mode 100644 index 0000000..77eae18 --- /dev/null +++ b/AdventOfCode.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32929.386 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdventOfCode", "AdventOfCode\AdventOfCode.csproj", "{30F2887D-526F-4068-A581-E20BAF52F900}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {30F2887D-526F-4068-A581-E20BAF52F900}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30F2887D-526F-4068-A581-E20BAF52F900}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30F2887D-526F-4068-A581-E20BAF52F900}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30F2887D-526F-4068-A581-E20BAF52F900}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9B8E4DE0-580A-4E29-91F9-90720A6A5230} + EndGlobalSection +EndGlobal diff --git a/AdventOfCode/AdventOfCode.csproj b/AdventOfCode/AdventOfCode.csproj new file mode 100644 index 0000000..72b5faa --- /dev/null +++ b/AdventOfCode/AdventOfCode.csproj @@ -0,0 +1,19 @@ + + + + net5.0 + + + + + + + + + + + + + + + diff --git a/AdventOfCode/Common/AOCAttribute.cs b/AdventOfCode/Common/AOCAttribute.cs new file mode 100644 index 0000000..779f0cf --- /dev/null +++ b/AdventOfCode/Common/AOCAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace AdventOfCode.Common +{ + public class AOCAttribute : Attribute + { + public int Year { get; set; } + public int Day { get; set; } + public AOCAttribute(int year, int day) + { + this.Year = year; + this.Day = day; + } + } +} diff --git a/AdventOfCode/Common/AOCExtensions.cs b/AdventOfCode/Common/AOCExtensions.cs new file mode 100644 index 0000000..489d462 --- /dev/null +++ b/AdventOfCode/Common/AOCExtensions.cs @@ -0,0 +1,12 @@ +using System; + +namespace AOC2021.Helper +{ + public static class AOCExtensions + { + public static int ToInt(this string str) + { + return Convert.ToInt32(str); + } + } +} diff --git a/AdventOfCode/Common/TextPlainInputFormatter.cs b/AdventOfCode/Common/TextPlainInputFormatter.cs new file mode 100644 index 0000000..4250c20 --- /dev/null +++ b/AdventOfCode/Common/TextPlainInputFormatter.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Mvc.Formatters; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace AOC2021.Helper +{ + public class TextPlainInputFormatter : InputFormatter + { + private const string ContentType = "text/plain"; + + public TextPlainInputFormatter() + { + SupportedMediaTypes.Add(ContentType); + } + + public override async Task ReadRequestBodyAsync(InputFormatterContext context) + { + var request = context.HttpContext.Request; + using (var reader = new StreamReader(request.Body)) + { + var content = await reader.ReadToEndAsync(); + return await InputFormatterResult.SuccessAsync(content); + } + } + + public override bool CanRead(InputFormatterContext context) + { + var contentType = context.HttpContext.Request.ContentType; + return contentType.StartsWith(ContentType); + } + } +} diff --git a/AdventOfCode/Controllers/AdventOfCodeController.cs b/AdventOfCode/Controllers/AdventOfCodeController.cs new file mode 100644 index 0000000..4743ff4 --- /dev/null +++ b/AdventOfCode/Controllers/AdventOfCodeController.cs @@ -0,0 +1,51 @@ +using AdventOfCode.Common; +using AdventOfCode.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using System; +using System.Linq; + +namespace AdventOfCode.Controllers +{ + [ApiController] + [Route("[controller]")] + public class AdventOfCodeController : ControllerBase + { + private readonly ILogger _logger; + + public AdventOfCodeController(ILogger logger) + { + _logger = logger; + } + + [HttpPost] + [Consumes("text/plain")] + public AOCResponse Day(int year, int day, AOCVersion version, [FromBody] string input, bool IgnoreLogMessages = false) + { + AOCRequest request = new AOCRequest() { Input = input, Version = version, IgnoreLogMessages = IgnoreLogMessages }; + return GetAOCDay(year, day).ExecuteDay(request); + } + + private AOCDay GetAOCDay(int year, int day) + { + AOCDay aocDay = null; + var type = typeof(AOCDay); + var types = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(s => s.GetTypes()) + .Where(p => type.IsAssignableFrom(p) && !p.IsInterface && !p.IsAbstract); + foreach (var x in types) + { + var aocAttribute = (AOCAttribute) Attribute.GetCustomAttribute(x, typeof(AOCAttribute)); + if (aocAttribute != null) + { + if (aocAttribute.Year == year && aocAttribute.Day == day) + { + aocDay = (AOCDay)(IAOCService)Activator.CreateInstance(x); + aocDay.SetLogger(this._logger); + } + } + } + return aocDay; + } + } +} diff --git a/AdventOfCode/Models/AOCDay.cs b/AdventOfCode/Models/AOCDay.cs new file mode 100644 index 0000000..1a4a096 --- /dev/null +++ b/AdventOfCode/Models/AOCDay.cs @@ -0,0 +1,79 @@ + +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace AdventOfCode.Models +{ + public abstract class AOCDay : IAOCService + { + protected AOCRequest _request; + protected AOCResponse _response; + protected ILogger _logger; + private List _debugMessages; + protected object Answer { set { this._response.Answer = value; } } + public AOCDay() + { + this._response = new AOCResponse() + { + Status = false + }; + this._debugMessages = new List(); + } + public AOCResponse ExecuteDay(AOCRequest request) + { + _request = request; + var timer = new Stopwatch(); + try + { + timer.Start(); + switch (request.Version) + { + case AOCVersion.A: + this._response = ExecutePartA(); + break; + case AOCVersion.B: + this._response = ExecutePartB(); + break; + } + timer.Stop(); + this._response.RunTime = timer.ElapsedTicks.ToString(); + this._response.Status = true; + } + catch (Exception e) + { + this._response.Answer = e.Message; + this._response.Status = false; + this._response.StackTrace = e.StackTrace; + } + if (!request.IgnoreLogMessages) + this._response.Debug = this._debugMessages; + return this._response; + } + + protected abstract AOCResponse ExecutePartA(); + protected abstract AOCResponse ExecutePartB(); + + protected string[] GetSplitInput() + { + return this._request.Input.Trim().Replace("\r", "").Split("\n"); + } + + protected string[] GetSplitRowInput() + { + return this._request.Input.Trim().Replace("\r", "").Split("\n"); + } + public void SetLogger(ILogger logger) + { + this._logger = logger; + } + + protected void Log(object message, params object[] args) + { + if (_logger != null && !this._request.IgnoreLogMessages) + _logger.LogInformation(message.ToString(), args); + _debugMessages.Add(string.Format(message.ToString(), args)); + } + } +} diff --git a/AdventOfCode/Models/AOCRequest.cs b/AdventOfCode/Models/AOCRequest.cs new file mode 100644 index 0000000..9317b47 --- /dev/null +++ b/AdventOfCode/Models/AOCRequest.cs @@ -0,0 +1,17 @@ +using System; +using System.Runtime.Serialization; + +namespace AdventOfCode.Models +{ + [DataContract] + [Serializable] + public class AOCRequest + { + [DataMember] + public AOCVersion Version { get; set; } + [DataMember] + public string Input { get; set; } + [DataMember] + public bool IgnoreLogMessages { get; set; } + } +} diff --git a/AdventOfCode/Models/AOCResponse.cs b/AdventOfCode/Models/AOCResponse.cs new file mode 100644 index 0000000..bcdf6f8 --- /dev/null +++ b/AdventOfCode/Models/AOCResponse.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + + +namespace AdventOfCode.Models +{ + [DataContract] + [Serializable] + public class AOCResponse + { + [DataMember] + public DateTime Date { get { return DateTime.Now; } } + [DataMember] + public object Answer { get; set; } + [DataMember] + public bool Status { get; set; } + [DataMember] + public IEnumerable Debug { get; set; } + [DataMember] + public string StackTrace { get; set; } + private string timeInTicks; + [DataMember] + public string RunTime { get { return FormatRunTime(); } set { timeInTicks = value; } } + + public string FormatRunTime() + { + var ts = TimeSpan.FromTicks((long)Convert.ToDouble(timeInTicks)); + var microseconds = (ts.Ticks - (ts.Milliseconds * TimeSpan.TicksPerMillisecond)) / (TimeSpan.TicksPerMillisecond / 1000); + return $"Run time is {ts.Minutes}min {ts.Seconds}sec {ts.Milliseconds}ms {microseconds}µs"; + } + } + + +} diff --git a/AdventOfCode/Models/AOCVersion.cs b/AdventOfCode/Models/AOCVersion.cs new file mode 100644 index 0000000..4d9db0f --- /dev/null +++ b/AdventOfCode/Models/AOCVersion.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.Runtime.Serialization; + +namespace AdventOfCode.Models +{ + [JsonConverter(typeof(StringEnumConverter))] + public enum AOCVersion + { + [EnumMember(Value = "A")] + A, + [EnumMember(Value = "B")] + B + } +} diff --git a/AdventOfCode/Models/IAOCService.cs b/AdventOfCode/Models/IAOCService.cs new file mode 100644 index 0000000..0bcc73b --- /dev/null +++ b/AdventOfCode/Models/IAOCService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AdventOfCode.Models +{ + public interface IAOCService + { + public AOCResponse ExecuteDay(AOCRequest request); + } +} diff --git a/AdventOfCode/Program.cs b/AdventOfCode/Program.cs new file mode 100644 index 0000000..d0d4aa2 --- /dev/null +++ b/AdventOfCode/Program.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AdventOfCode +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/AdventOfCode/Properties/launchSettings.json b/AdventOfCode/Properties/launchSettings.json new file mode 100644 index 0000000..028a864 --- /dev/null +++ b/AdventOfCode/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:20379", + "sslPort": 44329 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "AdventOfCode": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/AdventOfCode/Startup.cs b/AdventOfCode/Startup.cs new file mode 100644 index 0000000..3e92133 --- /dev/null +++ b/AdventOfCode/Startup.cs @@ -0,0 +1,70 @@ +using AOC2021.Helper; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.HttpsPolicy; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.OpenApi.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AdventOfCode +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddCors(options => + { + options.AddPolicy("AnyOrigin", builder => + { + builder + .AllowAnyOrigin() + .AllowAnyMethod(); + }); + }); + services.AddControllers(); + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new OpenApiInfo { Title = "AdventofCode", Version = "v1" }); + }); + services.AddControllers(o => o.InputFormatters.Insert(o.InputFormatters.Count, new TextPlainInputFormatter())); + services.AddSwaggerGenNewtonsoftSupport(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseSwagger(); + app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "AdventOfCode v1")); + } + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} diff --git a/AdventOfCode/_2022/Day1.cs b/AdventOfCode/_2022/Day1.cs new file mode 100644 index 0000000..a43bfac --- /dev/null +++ b/AdventOfCode/_2022/Day1.cs @@ -0,0 +1,65 @@ +using AdventOfCode.Common; +using AdventOfCode.Models; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AdventOfCode._2022 +{ + [AOC(year: 2022, day: 1)] + public class Day1 : AOCDay + { + protected override AOCResponse ExecutePartA() + { + var rows = GetSplitInput(); + var elves = new List(); + int elfSet = 0; + for (int i = 0; i < rows.Length; i++) + { + if (string.IsNullOrWhiteSpace(rows[i])) + { + elves.Add(rows.Skip(elfSet).Take(i - elfSet).ToArray()); + elfSet = i+1; + } + if (i == rows.Length-1) + { + elves.Add(rows.Skip(elfSet).ToArray()); + } + } + var highestCalories = 0; + foreach (var elf in elves) + { + highestCalories = Math.Max(highestCalories, elf.Select(x => int.Parse(x)).Sum()); + } + + _response.Answer = highestCalories; + return _response; + } + + protected override AOCResponse ExecutePartB() + { + var rows = GetSplitInput(); + var elves = new List(); + int elfSet = 0; + for (int i = 0; i < rows.Length; i++) + { + if (string.IsNullOrWhiteSpace(rows[i])) + { + elves.Add(rows.Skip(elfSet).Take(i - elfSet).ToArray()); + elfSet = i + 1; + } + if (i == rows.Length - 1) + { + elves.Add(rows.Skip(elfSet).ToArray()); + } + } + var highestCalories = new List(); + foreach (var elf in elves) + { + highestCalories.Add(elf.Select(x => int.Parse(x)).Sum()); + } + _response.Answer = highestCalories.OrderByDescending(x => x).Take(3).Sum(); + return _response; + } + } +} diff --git a/AdventOfCode/_2022/Day2.cs b/AdventOfCode/_2022/Day2.cs new file mode 100644 index 0000000..9966375 --- /dev/null +++ b/AdventOfCode/_2022/Day2.cs @@ -0,0 +1,114 @@ +using AdventOfCode.Common; +using AdventOfCode.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace AdventOfCode._2022 +{ + [AOC(year: 2022, day: 2)] + public class Day2 : AOCDay + { + protected override AOCResponse ExecutePartA() + { + var rows = GetSplitInput(); + var totalScore = 0; + foreach (var row in rows) + { + var opponent = row.Split(" ")[0]; + var mine = row.Split(" ")[1]; + var score = ScoreRound(opponent, mine); + Log(score); + totalScore += score; + } + _response.Answer = totalScore; + return _response; + } + + protected override AOCResponse ExecutePartB() + { + var rows = GetSplitInput(); + var totalScore = 0; + foreach (var row in rows) + { + var opponent = row.Split(" ")[0]; + var mine = DeduceCorrectShape(opponent, row.Split(" ")[1]); + var score = ScoreRound(opponent, mine); + Log(score); + totalScore += score; + } + _response.Answer = totalScore; + return _response; + } + + private string DeduceCorrectShape(string opponent, string mine) + { + var oppScore = GetShapeScore(opponent); + if (mine == "X") //Lose + { + if (oppScore == 1) return "C"; + else if (oppScore == 2) return "A"; + else if (oppScore == 3) return "B"; + }else if (mine == "Y") //Draw + { + if (oppScore == 1) return "A"; + else if (oppScore == 2) return "B"; + else if (oppScore == 3) return "C"; + } + else //Win + { + if (oppScore == 1) return "B"; + else if (oppScore == 2) return "C"; + else if (oppScore == 3) return "A"; + } + return ""; + } + + private int ScoreRound(string o, string m) + { + //Its a draw + if (GetShapeScore(o) == GetShapeScore(m)) + { + return 3 + GetShapeScore(m); //Tied + }else if (DidYouWin(o, m)) + { + return 6 + GetShapeScore(m); //Won + } + return GetShapeScore(m); //Lost + } + + private bool DidYouWin(string o, string m) + { + var opp = GetShapeScore(o); + var mine = GetShapeScore(m); + if (opp == 1 && mine == 2) return true; + if (opp == 1 && mine == 3) return false; + if (opp == 2 && mine == 1) return false; + if (opp == 2 && mine == 3) return true; + if (opp == 3 && mine == 1) return true; + if (opp == 3 && mine == 2) return false; + return false; + } + + private int GetShapeScore(string s) + { + switch (s) + { + //Rock + case "A": + case "X": + return 1; + //Paper + case "B": + case "Y": + return 2; + //Scissors + case "C": + case "Z": + return 3; + } + return 0; + } + } +} diff --git a/AdventOfCode/_2022/Day3.cs b/AdventOfCode/_2022/Day3.cs new file mode 100644 index 0000000..555d1da --- /dev/null +++ b/AdventOfCode/_2022/Day3.cs @@ -0,0 +1,66 @@ +using AdventOfCode.Common; +using AdventOfCode.Models; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AdventOfCode._2022 +{ + [AOC(year: 2022, day: 3)] + public class Day3 : AOCDay + { + protected override AOCResponse ExecutePartA() + { + var rows = GetSplitInput(); + int total = 0; + foreach (var row in rows) + { + var first = row.Substring(0, row.Length / 2); + var second = row.Substring((row.Length / 2)); + var invalidItem = first.ToCharArray().Intersect(second.ToCharArray()).First(); + total += GetPriority(invalidItem); + } + _response.Answer = total; + return _response; + } + + protected override AOCResponse ExecutePartB() + { + var rows = GetSplitInput(); + var elves = new List(); + int elfSet = 0; + for (int i = 0; i < rows.Length; i++) + { + if (string.IsNullOrWhiteSpace(rows[i])) + { + elves.Add(rows.Skip(elfSet).Take(i - elfSet).ToArray()); + elfSet = i + 1; + } + if (i == rows.Length - 1) + { + elves.Add(rows.Skip(elfSet).ToArray()); + } + } + var highestCalories = new List(); + foreach (var elf in elves) + { + highestCalories.Add(elf.Select(x => int.Parse(x)).Sum()); + } + _response.Answer = highestCalories.OrderByDescending(x => x).Take(3).Sum(); + return _response; + } + + private int GetPriority(char c) + { + if (Char.IsUpper(c)) + { + return (c - 'A' + 27); + } + if (Char.IsLower(c)) + { + return (c - 'a' + 1); + } + return 0; + } + } +} diff --git a/AdventOfCode/appsettings.Development.json b/AdventOfCode/appsettings.Development.json new file mode 100644 index 0000000..8983e0f --- /dev/null +++ b/AdventOfCode/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/AdventOfCode/appsettings.json b/AdventOfCode/appsettings.json new file mode 100644 index 0000000..d9d9a9b --- /dev/null +++ b/AdventOfCode/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +}