diff --git a/2021/06/06.csproj b/2021/06/06.csproj index 043826d..8af3444 100644 --- a/2021/06/06.csproj +++ b/2021/06/06.csproj @@ -8,4 +8,12 @@ enable + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/2021/06/Migrations/20211206123902_InitialCreate.Designer.cs b/2021/06/Migrations/20211206123902_InitialCreate.Designer.cs new file mode 100644 index 0000000..51400dc --- /dev/null +++ b/2021/06/Migrations/20211206123902_InitialCreate.Designer.cs @@ -0,0 +1,37 @@ +// +using Day06; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace _06.Migrations +{ + [DbContext(typeof(FishContext))] + [Migration("20211206123902_InitialCreate")] + partial class InitialCreate + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Day06.Fish", b => + { + b.Property("FishId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("InternalTimer") + .HasColumnType("INTEGER"); + + b.HasKey("FishId"); + + b.ToTable("Fishes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/2021/06/Migrations/20211206123902_InitialCreate.cs b/2021/06/Migrations/20211206123902_InitialCreate.cs new file mode 100644 index 0000000..b7c0eba --- /dev/null +++ b/2021/06/Migrations/20211206123902_InitialCreate.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace _06.Migrations +{ + public partial class InitialCreate : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Fishes", + columns: table => new + { + FishId = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + InternalTimer = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Fishes", x => x.FishId); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Fishes"); + } + } +} diff --git a/2021/06/Migrations/FishContextModelSnapshot.cs b/2021/06/Migrations/FishContextModelSnapshot.cs new file mode 100644 index 0000000..015225e --- /dev/null +++ b/2021/06/Migrations/FishContextModelSnapshot.cs @@ -0,0 +1,35 @@ +// +using Day06; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace _06.Migrations +{ + [DbContext(typeof(FishContext))] + partial class FishContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("Day06.Fish", b => + { + b.Property("FishId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("InternalTimer") + .HasColumnType("INTEGER"); + + b.HasKey("FishId"); + + b.ToTable("Fishes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/2021/06/Model.cs b/2021/06/Model.cs new file mode 100644 index 0000000..d68cff8 --- /dev/null +++ b/2021/06/Model.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; + +namespace Day06 +{ + public class FishContext : DbContext + { + public DbSet Fishes { get; set; } + + public string DbPath { get; } + + public FishContext() + { + var folder = Environment.SpecialFolder.LocalApplicationData; + var path = Environment.GetFolderPath(folder); + DbPath = System.IO.Path.Join(path, "fishes.db"); + } + + // The following configures EF to create a Sqlite database file in the + // special "local" folder for your platform. + protected override void OnConfiguring(DbContextOptionsBuilder options) + => options.UseSqlite($"Data Source={DbPath}"); + } + + public class Fish + { + public int FishId { get; set; } + public int InternalTimer { get; set; } + } +} \ No newline at end of file diff --git a/2021/06/Program.cs b/2021/06/Program.cs index ebc65b5..65fd54e 100644 --- a/2021/06/Program.cs +++ b/2021/06/Program.cs @@ -23,18 +23,18 @@ Console.WriteLine($"Day: {currentDay} - there are {lanternFishPopulation.Count()} lantern fish"); for (int i = 0; i < lanternFishPopulation.Count; i++) { - switch(lanternFishPopulation[i]) + switch (lanternFishPopulation[i]) { - case 0: - // its internal timer would reset to 6, and it would create a new lanternfish with an internal timer of 8. - lanternFishPopulation[i] = 6; - // Adding a new one with 9 though it should be 8 as this loop will catch new fish and decrement them. It's dirty, but fast way to solve the issue - lanternFishPopulation.Add(9); - break; - default: - // remove one day from the fish's countdown - lanternFishPopulation[i] -= 1; - break; + case 0: + // its internal timer would reset to 6, and it would create a new lanternfish with an internal timer of 8. + lanternFishPopulation[i] = 6; + // Adding a new one with 9 though it should be 8 as this loop will catch new fish and decrement them. It's dirty, but fast way to solve the issue + lanternFishPopulation.Add(9); + break; + default: + // remove one day from the fish's countdown + lanternFishPopulation[i] -= 1; + break; } } @@ -42,6 +42,58 @@ } } + static void SimulateLanternFishBigDatasets(ref List lanternFishPopulation, int daysToSimulate) + { + // A lanternfish that creates a new fish resets its timer to 6, not 7 (because 0 is included as a valid timer value). The new lanternfish starts with an internal timer of 8 and does not start counting down until the next day. + + // Store dataset into db + using (var db = new FishContext()) + { + foreach (var fish in lanternFishPopulation) + { + db.Add(new Fish { InternalTimer = fish }); + db.SaveChanges(); + } + } + + int currentDay = 1; + + while (currentDay <= daysToSimulate) + { + using (var db = new FishContext()) + { + int fishCount = db.Fishes.Count(); + Console.WriteLine($"Day: {currentDay} - there are {fishCount} lantern fish"); + + List fishIds = db.Fishes.Select(x => x.FishId).ToList(); + + foreach (int fishId in fishIds) + { + Fish fish = db.Fishes.First(x => x.FishId == fishId); + + switch (fish.InternalTimer) + { + case 0: + // its internal timer would reset to 6, and it would create a new lanternfish with an internal timer of 8. + fish.InternalTimer = 6; + // Adding a new one with 9 though it should be 8 as this loop will catch new fish and decrement them. It's dirty, but fast way to solve the issue + db.Add(new Fish { InternalTimer = 9 }); + break; + default: + // remove one day from the fish's countdown + fish.InternalTimer -= 1; + break; + } + } + + db.SaveChanges(); + } + + currentDay += 1; + } + } + + static void Part1(List lanternFish) { SimulateLanternFish(ref lanternFish, 80); @@ -51,11 +103,16 @@ static void Part2(List lanternFish) { - SimulateLanternFish(ref lanternFish, 256); + SimulateLanternFishBigDatasets(ref lanternFish, 256); // TODO - redo this using a database for large datasets, and entity framework, so as to avoid the HUGE memory usage - - Console.WriteLine($"After 256 days there are {lanternFish.Count()} lantern fish."); + using (var db = new FishContext()) + { + int fishCount = db.Fishes.Count(); + Console.WriteLine($"After 256 days there are {fishCount} lantern fish."); + } + + } } } \ No newline at end of file diff --git a/2021/06/readme.md b/2021/06/readme.md new file mode 100644 index 0000000..cf5d3eb --- /dev/null +++ b/2021/06/readme.md @@ -0,0 +1,3 @@ +Run dotnet ef database update to initialise the database +Delete the database if you want to run the code again +It's at C:\Users\Josh\AppData\Local as fishes.db and other associated files \ No newline at end of file