mirror of
https://github.com/jcreek/advent-of-code.git
synced 2026-07-13 03:03:46 +00:00
Add various uncommitted 2021 files for posterity
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Day15
|
||||
{
|
||||
public class Dijkstra
|
||||
{
|
||||
public object PartOne(string input) => Solve(GetRiskLevelMap(input));
|
||||
public object PartTwo(string input) => Solve(ScaleUp(GetRiskLevelMap(input)));
|
||||
|
||||
int Solve(Dictionary<Point, int> riskMap)
|
||||
{
|
||||
// Disjktra algorithm
|
||||
|
||||
var topLeft = new Point(0, 0);
|
||||
var bottomRight = new Point(riskMap.Keys.MaxBy(p => p.x).x, riskMap.Keys.MaxBy(p => p.y).y);
|
||||
|
||||
// Visit points in order of cumulted risk
|
||||
// ⭐ .Net 6 finally has a PriorityQueue collection :)
|
||||
var q = new PriorityQueue<Point, int>();
|
||||
var totalRiskMap = new Dictionary<Point, int>();
|
||||
|
||||
totalRiskMap[topLeft] = 0;
|
||||
q.Enqueue(topLeft, 0);
|
||||
|
||||
// It would be enough to go until we find the bottom right corner, but computing all
|
||||
// risk levels is not much more work
|
||||
while (q.Count > 0)
|
||||
{
|
||||
var p = q.Dequeue();
|
||||
|
||||
foreach (var n in Neighbours(p))
|
||||
{
|
||||
if (riskMap.ContainsKey(n) && !totalRiskMap.ContainsKey(n))
|
||||
{
|
||||
var totalRisk = totalRiskMap[p] + riskMap[n];
|
||||
totalRiskMap[n] = totalRisk;
|
||||
if (n == bottomRight)
|
||||
{
|
||||
break;
|
||||
}
|
||||
var h = 0; //bottomRight.y - n.y + bottomRight.x - n.x;
|
||||
q.Enqueue(n, totalRisk + h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return bottom right corner's total risk:
|
||||
return totalRiskMap[bottomRight];
|
||||
}
|
||||
|
||||
// Create an 5x scaled up map, as described in part 2
|
||||
Dictionary<Point, int> ScaleUp(Dictionary<Point, int> map)
|
||||
{
|
||||
var (ccol, crow) = (map.Keys.MaxBy(p => p.x).x + 1, map.Keys.MaxBy(p => p.y).y + 1);
|
||||
|
||||
var res = new Dictionary<Point, int>(
|
||||
from y in Enumerable.Range(0, crow * 5)
|
||||
from x in Enumerable.Range(0, ccol * 5)
|
||||
|
||||
// x, y and risk level in the original map:
|
||||
let tileY = y % crow
|
||||
let tileX = x % ccol
|
||||
let tileRiskLevel = map[new Point(tileX, tileY)]
|
||||
|
||||
// risk level is increased by tile distance from origin:
|
||||
let tileDistance = (y / crow) + (x / ccol)
|
||||
|
||||
// risk level wraps around from 9 to 1:
|
||||
let riskLevel = (tileRiskLevel + tileDistance - 1) % 9 + 1
|
||||
select new KeyValuePair<Point, int>(new Point(x, y), riskLevel)
|
||||
);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// store the points in a dictionary so that we can iterate over them and
|
||||
// to easily deal with points outside the area
|
||||
Dictionary<Point, int> GetRiskLevelMap(string input)
|
||||
{
|
||||
var map = input.Split("\n");
|
||||
return new Dictionary<Point, int>(
|
||||
from y in Enumerable.Range(0, map[0].Length)
|
||||
from x in Enumerable.Range(0, map.Length)
|
||||
select new KeyValuePair<Point, int>(new Point(x, y), map[y][x] - '0')
|
||||
);
|
||||
}
|
||||
|
||||
IEnumerable<Point> Neighbours(Point point) =>
|
||||
new[] {
|
||||
point with {y = point.y + 1},
|
||||
point with {y = point.y - 1},
|
||||
point with {x = point.x + 1},
|
||||
point with {x = point.x - 1},
|
||||
};
|
||||
}
|
||||
}
|
||||
record Point(int x, int y);
|
||||
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// A C# program for Dijkstra1's single
|
||||
// source shortest path algorithm.
|
||||
// The program is for adjacency matrix
|
||||
// representation of the graph
|
||||
|
||||
namespace Day15
|
||||
{
|
||||
class Dijkstra1
|
||||
{
|
||||
// A utility function to find the
|
||||
// vertex with minimum distance
|
||||
// value, from the set of vertices
|
||||
// not yet included in shortest
|
||||
// path tree
|
||||
static int V = 9;
|
||||
int minDistance(int[] dist,
|
||||
bool[] sptSet)
|
||||
{
|
||||
// Initialize min value
|
||||
int min = int.MaxValue, min_index = -1;
|
||||
|
||||
for (int v = 0; v < V; v++)
|
||||
if (sptSet[v] == false && dist[v] <= min)
|
||||
{
|
||||
min = dist[v];
|
||||
min_index = v;
|
||||
}
|
||||
|
||||
return min_index;
|
||||
}
|
||||
|
||||
// A utility function to print
|
||||
// the constructed distance array
|
||||
void printSolution(int[] dist, int n)
|
||||
{
|
||||
Console.Write("Vertex Distance "
|
||||
+ "from Source\n");
|
||||
for (int i = 0; i < V; i++)
|
||||
Console.Write(i + " \t\t " + dist[i] + "\n");
|
||||
}
|
||||
|
||||
// Function that implements Dijkstra1's
|
||||
// single source shortest path algorithm
|
||||
// for a graph represented using adjacency
|
||||
// matrix representation
|
||||
public void dijkstra(int[,] graph, int src)
|
||||
{
|
||||
int[] dist = new int[V]; // The output array. dist[i]
|
||||
// will hold the shortest
|
||||
// distance from src to i
|
||||
|
||||
// sptSet[i] will true if vertex
|
||||
// i is included in shortest path
|
||||
// tree or shortest distance from
|
||||
// src to i is finalized
|
||||
bool[] sptSet = new bool[V];
|
||||
|
||||
// Initialize all distances as
|
||||
// INFINITE and stpSet[] as false
|
||||
for (int i = 0; i < V; i++)
|
||||
{
|
||||
dist[i] = int.MaxValue;
|
||||
sptSet[i] = false;
|
||||
}
|
||||
|
||||
// Distance of source vertex
|
||||
// from itself is always 0
|
||||
dist[src] = 0;
|
||||
|
||||
// Find shortest path for all vertices
|
||||
for (int count = 0; count < V - 1; count++)
|
||||
{
|
||||
// Pick the minimum distance vertex
|
||||
// from the set of vertices not yet
|
||||
// processed. u is always equal to
|
||||
// src in first iteration.
|
||||
int u = minDistance(dist, sptSet);
|
||||
|
||||
// Mark the picked vertex as processed
|
||||
sptSet[u] = true;
|
||||
|
||||
// Update dist value of the adjacent
|
||||
// vertices of the picked vertex.
|
||||
for (int v = 0; v < V; v++)
|
||||
|
||||
// Update dist[v] only if is not in
|
||||
// sptSet, there is an edge from u
|
||||
// to v, and total weight of path
|
||||
// from src to v through u is smaller
|
||||
// than current value of dist[v]
|
||||
if (!sptSet[v] && graph[u, v] != 0 &&
|
||||
dist[u] != int.MaxValue && dist[u] + graph[u, v] < dist[v])
|
||||
dist[v] = dist[u] + graph[u, v];
|
||||
}
|
||||
|
||||
// print the constructed distance array
|
||||
printSolution(dist, V);
|
||||
}
|
||||
|
||||
// Driver Code
|
||||
// public static void Main()
|
||||
// {
|
||||
// /* Let us create the example
|
||||
//graph discussed above */
|
||||
// int[,] graph = new int[,] { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },
|
||||
// { 4, 0, 8, 0, 0, 0, 0, 11, 0 },
|
||||
// { 0, 8, 0, 7, 0, 4, 0, 0, 2 },
|
||||
// { 0, 0, 7, 0, 9, 14, 0, 0, 0 },
|
||||
// { 0, 0, 0, 9, 0, 10, 0, 0, 0 },
|
||||
// { 0, 0, 4, 14, 10, 0, 2, 0, 0 },
|
||||
// { 0, 0, 0, 0, 0, 2, 0, 1, 6 },
|
||||
// { 8, 11, 0, 0, 0, 0, 1, 0, 7 },
|
||||
// { 0, 0, 2, 0, 0, 0, 6, 7, 0 } };
|
||||
// Dijkstra1 t = new Dijkstra1();
|
||||
// t.dijkstra(graph, 0);
|
||||
// }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user