Added Day 11 and Day 12 for AdventOfCode
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		
							parent
							
								
									436cad8605
								
							
						
					
					
						commit
						f655768af4
					
				| @ -13,7 +13,6 @@ | |||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Folder Include="Models\" /> |     <Folder Include="Models\" /> | ||||||
|     <Folder Include="_2021\" /> |     <Folder Include="_2021\" /> | ||||||
|     <Folder Include="_2022\Day11\" /> |  | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| 
 | 
 | ||||||
| </Project> | </Project> | ||||||
|  | |||||||
| @ -39,5 +39,17 @@ namespace AdventOfCode.Common | |||||||
|                 Console.WriteLine(); |                 Console.WriteLine(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         public static void PrintSquareArray(this char[,] arr) | ||||||
|  |         { | ||||||
|  |             for (int x = 0; x < arr.GetLength(0); x++) | ||||||
|  |             { | ||||||
|  |                 for (int y = 0; y < arr.GetLength(1); y++) | ||||||
|  |                 { | ||||||
|  |                     Console.Write(arr[x, y] + " "); | ||||||
|  |                 } | ||||||
|  |                 Console.WriteLine(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; | |||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Diagnostics; | using System.Diagnostics; | ||||||
|  | using System.Linq; | ||||||
| 
 | 
 | ||||||
| namespace AdventOfCode.Models | namespace AdventOfCode.Models | ||||||
| { | { | ||||||
| @ -47,8 +48,8 @@ namespace AdventOfCode.Models | |||||||
|                 this._response.Status = false; |                 this._response.Status = false; | ||||||
|                 this._response.StackTrace = e.StackTrace; |                 this._response.StackTrace = e.StackTrace; | ||||||
|             } |             } | ||||||
|             if (!request.IgnoreLogMessages) | 
 | ||||||
|                 this._response.Debug = this._debugMessages; |             this._response.Debug = this._debugMessages; | ||||||
|             return this._response; |             return this._response; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -66,6 +67,26 @@ namespace AdventOfCode.Models | |||||||
|         { |         { | ||||||
|             return this._request.Input.Trim().Replace("\r", "").Split("\n"); |             return this._request.Input.Trim().Replace("\r", "").Split("\n"); | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         protected List<string[]> SplitInputOnEmptyLine() | ||||||
|  |         { | ||||||
|  |             var rows = GetSplitInput(); | ||||||
|  |             var input = new List<string[]>(); | ||||||
|  |             int set = 0; | ||||||
|  |             for (int i = 0; i < rows.Length; i++) | ||||||
|  |             { | ||||||
|  |                 if (string.IsNullOrWhiteSpace(rows[i])) | ||||||
|  |                 { | ||||||
|  |                     input.Add(rows.Skip(set).Take(i - set).ToArray()); | ||||||
|  |                     set = i + 1; | ||||||
|  |                 } | ||||||
|  |                 if (i == rows.Length - 1) | ||||||
|  |                 { | ||||||
|  |                     input.Add(rows.Skip(set).ToArray()); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return input; | ||||||
|  |         } | ||||||
|         public void SetLogger(ILogger logger) |         public void SetLogger(ILogger logger) | ||||||
|         { |         { | ||||||
|             this._logger = logger; |             this._logger = logger; | ||||||
| @ -73,8 +94,16 @@ namespace AdventOfCode.Models | |||||||
| 
 | 
 | ||||||
|         protected void Log(object message, params object[] args) |         protected void Log(object message, params object[] args) | ||||||
|         { |         { | ||||||
|             if (_logger != null && !this._request.IgnoreLogMessages) |             if (!this._request.IgnoreLogMessages) | ||||||
|                 _logger.LogInformation(message.ToString(), args); |             { | ||||||
|  |                 if (_logger != null) | ||||||
|  |                     _logger.LogInformation(message.ToString(), args); | ||||||
|  |                 _debugMessages.Add(string.Format(message.ToString(), args)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected void Info(object message, params object[] args) | ||||||
|  |         { | ||||||
|             _debugMessages.Add(string.Format(message.ToString(), args)); |             _debugMessages.Add(string.Format(message.ToString(), args)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
							
								
								
									
										68
									
								
								AdventOfCode/_2022/Day11/Day11.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								AdventOfCode/_2022/Day11/Day11.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | using AdventOfCode._2022.Models; | ||||||
|  | using AdventOfCode.Common; | ||||||
|  | using AdventOfCode.Models; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | 
 | ||||||
|  | namespace AdventOfCode._2022.Day11 | ||||||
|  | { | ||||||
|  |     [AOC(year: 2022, day: 11)] | ||||||
|  |     public class Day11 : AOCDay | ||||||
|  |     { | ||||||
|  |         protected override AOCResponse ExecutePartA() | ||||||
|  |         { | ||||||
|  |             ExecuteMonkeyBusiness(20); | ||||||
|  |             return _response; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected override AOCResponse ExecutePartB() | ||||||
|  |         { | ||||||
|  |             ExecuteMonkeyBusiness(10000); | ||||||
|  |             return _response; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void ExecuteMonkeyBusiness(int rounds) | ||||||
|  |         { | ||||||
|  |             var input = SplitInputOnEmptyLine(); | ||||||
|  |             var monkeys = new List<Monkey>(); | ||||||
|  |             foreach (var monkey in input) | ||||||
|  |             { | ||||||
|  |                 monkeys.Add(new Monkey(_request.Version, monkey.ToArray())); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             long lcm = 1; //Only needed for part b | ||||||
|  |             //Target Monkey Mapping | ||||||
|  |             foreach (var monkey in monkeys) | ||||||
|  |             { | ||||||
|  |                 lcm *= monkey.DivisibleNumber; | ||||||
|  |                 monkey.MapTargetMonkeys(monkeys.First(x => x.MonkeyId == monkey.TargetMonkeyIds.Item1), monkeys.First(x => x.MonkeyId == monkey.TargetMonkeyIds.Item2)); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //Start round | ||||||
|  |             for (int i = 0; i < rounds; i++) | ||||||
|  |             { | ||||||
|  |                 foreach (var monkey in monkeys) | ||||||
|  |                 { | ||||||
|  |                     monkey.Business(lcm); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if (_request.Version == AOCVersion.A) | ||||||
|  |                     monkeys.ForEach(x => Log("Round" + (i + 1) + "_M" + x.MonkeyId + ": " + string.Join(", ", x.Items))); | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     if ((i + 1) == 1 || (i + 1) == 20 || (i + 1) == 1000 || (i + 1) % 1000 == 0) | ||||||
|  |                     { | ||||||
|  |                         monkeys.ForEach(x => Log($"R{i + 1}Monkey{x.MonkeyId} inspected {x.ItemsInspected} items")); | ||||||
|  |                         monkeys.ForEach(x => Log("Round" + (i + 1) + "_M" + x.MonkeyId + ": " + string.Join(", ", x.Items))); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |             } | ||||||
|  |             monkeys.ForEach(x => Info($"Monkey{x.MonkeyId} inspected {x.ItemsInspected} items")); | ||||||
|  | 
 | ||||||
|  |             var crazyMonkeys = monkeys.OrderByDescending(x => x.ItemsInspected).ToArray(); | ||||||
|  |             _response.Answer = crazyMonkeys[0].ItemsInspected * crazyMonkeys[1].ItemsInspected; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										105
									
								
								AdventOfCode/_2022/Day11/Monkey.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								AdventOfCode/_2022/Day11/Monkey.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | |||||||
|  | using AdventOfCode.Models; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text.RegularExpressions; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | 
 | ||||||
|  | namespace AdventOfCode._2022.Day11 | ||||||
|  | { | ||||||
|  |     public class Monkey | ||||||
|  |     { | ||||||
|  |         private AOCVersion _version; | ||||||
|  |         public int MonkeyId { get; set; } | ||||||
|  |         public Queue<long> Items { get; set; } | ||||||
|  |         public Tuple<string, string> Operation { get; set; } | ||||||
|  |         public long DivisibleNumber { get; set; } | ||||||
|  |         public Tuple<int, int> TargetMonkeyIds { get; set; } | ||||||
|  |         public Tuple<Monkey, Monkey> TargetMonkeys { get; set; } | ||||||
|  |         public long ItemsInspected { get; set; } | ||||||
|  |         public Monkey(AOCVersion version, string[] monkey) | ||||||
|  |         { | ||||||
|  |             _version = version; | ||||||
|  |             //Pull monkey id | ||||||
|  |             MonkeyId = Convert.ToInt32(Regex.Replace(monkey.First(), "[^0-9.]", "")); | ||||||
|  |              | ||||||
|  |             //Item creation | ||||||
|  |             Items = new Queue<long>(); | ||||||
|  |             Regex.Replace(monkey[1], "[^0-9. ]", "").Trim().Split(' ').ToList().ForEach(x => Items.Enqueue(Convert.ToInt32(x))); | ||||||
|  | 
 | ||||||
|  |             //Generate operation | ||||||
|  |             var splitOperation = monkey[2].Split(' '); | ||||||
|  |             Operation = Tuple.Create(splitOperation[splitOperation.Length - 2], splitOperation[splitOperation.Length - 1]); | ||||||
|  | 
 | ||||||
|  |             //Divisible number | ||||||
|  |             DivisibleNumber = Convert.ToInt32(Regex.Replace(monkey[3], "[^0-9.]", "")); | ||||||
|  | 
 | ||||||
|  |             //TargetMonkey | ||||||
|  |             TargetMonkeyIds = Tuple.Create(Convert.ToInt32(Regex.Replace(monkey[4], "[^0-9.]", "")), Convert.ToInt32(Regex.Replace(monkey[5], "[^0-9.]", ""))); | ||||||
|  | 
 | ||||||
|  |             //Set items insepcts to 0 | ||||||
|  |             ItemsInspected = 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void MapTargetMonkeys(Monkey trueMonkey, Monkey falseMonkey) | ||||||
|  |         { | ||||||
|  |             TargetMonkeys = Tuple.Create(trueMonkey, falseMonkey); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void Business(long lcm = 0) | ||||||
|  |         { | ||||||
|  |             while (Items.Any()) | ||||||
|  |             { | ||||||
|  |                 var item = Items.Dequeue(); | ||||||
|  |                 ItemsInspected++; | ||||||
|  |                 if (_version == AOCVersion.A) | ||||||
|  |                 { | ||||||
|  |                     item = ExecuteOperation(item); //Worry level | ||||||
|  |                     item = item / 3; //Monkey boredom | ||||||
|  | 
 | ||||||
|  |                     //Throw item to next monkey | ||||||
|  |                     if (item % DivisibleNumber == 0) | ||||||
|  |                     { | ||||||
|  |                         TargetMonkeys.Item1.Items.Enqueue(item); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         TargetMonkeys.Item2.Items.Enqueue(item); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     long number; | ||||||
|  |                     if (!long.TryParse(Operation.Item2, out number)) | ||||||
|  |                         number = item; | ||||||
|  |                     item %= lcm; | ||||||
|  |                     number %= lcm; | ||||||
|  |                     var result = Operation.Item1 == "+" ? item + number : item * number; | ||||||
|  |                     if (result% DivisibleNumber == 0) | ||||||
|  |                     { | ||||||
|  |                         TargetMonkeys.Item1.Items.Enqueue(result); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         TargetMonkeys.Item2.Items.Enqueue(result); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                   | ||||||
|  | 
 | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private long ExecuteOperation(long item) | ||||||
|  |         { | ||||||
|  |             long number; | ||||||
|  |             if (!long.TryParse(Operation.Item2, out number)) | ||||||
|  |                 number = item; | ||||||
|  |             if (Operation.Item1 == "+") | ||||||
|  |                 return number + item; | ||||||
|  |             else if (Operation.Item1 == "*") | ||||||
|  |                 return number * item; | ||||||
|  |             throw new ArgumentException("Unknown operation " + Operation.Item1); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								AdventOfCode/_2022/Day12/Day12.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								AdventOfCode/_2022/Day12/Day12.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | using AdventOfCode.Common; | ||||||
|  | using AdventOfCode.Models; | ||||||
|  | using System.Linq; | ||||||
|  | 
 | ||||||
|  | namespace AdventOfCode._2022.Day12 | ||||||
|  | { | ||||||
|  |     [AOC(year: 2022, day: 12)] | ||||||
|  |     [IgnoreTestAnswer(AOCVersion.B)] //Run time is 1min 38sec 648ms for PartB | ||||||
|  |     public class Day12 : AOCDay | ||||||
|  |     { | ||||||
|  |         protected override AOCResponse ExecutePartA() | ||||||
|  |         { | ||||||
|  |             var map = new Heightmap(GetSplitInput()); | ||||||
|  |             map.Traverse(_request.Version); | ||||||
|  |             map.Steps.ToList().ForEach(x => Info(x)); | ||||||
|  |             _response.Answer = map.TotalSteps; | ||||||
|  | 
 | ||||||
|  |             return _response; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected override AOCResponse ExecutePartB() | ||||||
|  |         { | ||||||
|  |             //Only difference is done VIA AOCVersion variable | ||||||
|  |             //Run time is 1min 38sec 648ms for PartB, might want to optimize | ||||||
|  |             return ExecutePartA(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										249
									
								
								AdventOfCode/_2022/Day12/Heightmap.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								AdventOfCode/_2022/Day12/Heightmap.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,249 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using AdventOfCode.Common; | ||||||
|  | using AdventOfCode.Models; | ||||||
|  | 
 | ||||||
|  | namespace AdventOfCode._2022.Day12 | ||||||
|  | { | ||||||
|  |     public class Heightmap | ||||||
|  |     { | ||||||
|  |         public int TotalSteps { get; set; } | ||||||
|  |         public string[] Steps { get; set; } | ||||||
|  |         private Coord _start, _end; | ||||||
|  |         private char[,] _map; | ||||||
|  |         private readonly int MaxX, MaxY; | ||||||
|  |         public Heightmap(string[] input) | ||||||
|  |         { | ||||||
|  |             //Create our 2d board | ||||||
|  |             _map = new char[input.Count(), input.First().Length]; | ||||||
|  |             for (int i = 0; i < input.Count(); i++) | ||||||
|  |             { | ||||||
|  |                 var line = input[i]; | ||||||
|  |                 for (int j = 0; j < line.Length; j++) | ||||||
|  |                 { | ||||||
|  |                     _map[i, j] = line[j]; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //Find the start and end | ||||||
|  |             MaxX = _map.GetLength(0); | ||||||
|  |             MaxY = _map.GetLength(1); | ||||||
|  |             for (int x = 0; x < _map.GetLength(0); x++) | ||||||
|  |             { | ||||||
|  |                 for (int y = 0; y < _map.GetLength(1); y++) | ||||||
|  |                 { | ||||||
|  |                     if (_map[x, y] == 'S') _start = new Coord(x, y); | ||||||
|  |                     if (_map[x, y] == 'E') _end = new Coord(x, y); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //Ensure a start and end was found | ||||||
|  |             if (_start == null) throw new ArgumentException("No start coord found!"); | ||||||
|  |             if (_end == null) throw new ArgumentException("No end coord found!"); | ||||||
|  |             _start.SetDistance(_end);//Set the distance between start and end | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void Traverse(AOCVersion version) | ||||||
|  |         { | ||||||
|  |             if (version == AOCVersion.A) | ||||||
|  |             { | ||||||
|  |                 //Traverse our 2d matrix | ||||||
|  |                 AStarTraversal(); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 _map[_start.X, _start.Y] = 'a'; //Change our S to an 'a' elevation | ||||||
|  |                 var possibleStarts = new List<Coord>(); | ||||||
|  |                 for (int x = 0; x < _map.GetLength(0); x++) | ||||||
|  |                 { | ||||||
|  |                     for (int y = 0; y < _map.GetLength(1); y++) | ||||||
|  |                     { | ||||||
|  |                         if (_map[x, y] == 'a') possibleStarts.Add(new Coord(x, y)); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 var routes = new List<string[]>(); | ||||||
|  |                 foreach (var possibleStart in possibleStarts) | ||||||
|  |                 { | ||||||
|  |                     _start = possibleStart; | ||||||
|  |                     AStarTraversal(); | ||||||
|  |                     routes.Add(Steps.ToArray()); | ||||||
|  |                 } | ||||||
|  |                 Steps = routes.OrderByDescending(x => x.Length).Last(); | ||||||
|  |                 TotalSteps = Steps.Length - 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private List<Coord> GetAdjacentCoords(Coord currentCoord) | ||||||
|  |         { | ||||||
|  |             var adjCoords = new List<Coord>() | ||||||
|  |             { | ||||||
|  |                 new Coord { X = currentCoord.X, Y = currentCoord.Y - 1, Parent = currentCoord, Cost = currentCoord.Cost + 1 }, //Left | ||||||
|  |                 new Coord { X = currentCoord.X, Y = currentCoord.Y + 1, Parent = currentCoord, Cost = currentCoord.Cost + 1},// Right | ||||||
|  |                 new Coord { X = currentCoord.X - 1, Y = currentCoord.Y, Parent = currentCoord, Cost = currentCoord.Cost + 1 }, //Up | ||||||
|  |                 new Coord { X = currentCoord.X + 1, Y = currentCoord.Y, Parent = currentCoord, Cost = currentCoord.Cost + 1 }, //Down | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             adjCoords.ForEach(coord => coord.SetDistance(_end)); | ||||||
|  |             var currentChar = _map[currentCoord.X, currentCoord.Y]; | ||||||
|  |             if (currentChar == 'S') currentChar = 'a'; //Set the starting char to 'a' so it can do the diff in char instead of from 'S' | ||||||
|  | 
 | ||||||
|  |             return adjCoords | ||||||
|  |                 .Where(coord => coord.X >= 0 && coord.X < MaxX) | ||||||
|  |                 .Where(coord => coord.Y >= 0 && coord.Y < MaxY) | ||||||
|  |                 .Where(coord => (_map[coord.X, coord.Y] != 'E' && (_map[coord.X, coord.Y] - currentChar) <= 1) //At most upper height is 1, can drop any amount | ||||||
|  |                     || (_map[coord.X, coord.Y] == 'E' && (currentChar == 'z' || currentChar == 'y'))) //E's height IS 'z', so it can go z->z or y->z for the final move. | ||||||
|  |                 .ToList(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void AStarTraversal() | ||||||
|  |         { | ||||||
|  |             var activeCoords = new List<Coord>(); | ||||||
|  |             activeCoords.Add(_start); | ||||||
|  |             var visitedCoords = new List<Coord>(); | ||||||
|  | 
 | ||||||
|  |             while (activeCoords.Any()) | ||||||
|  |             { | ||||||
|  |                 var checkCoord = activeCoords.OrderByDescending(x => x.CostDistance).Last(); | ||||||
|  | 
 | ||||||
|  |                 if (checkCoord.X == _end.X && checkCoord.Y == _end.Y) | ||||||
|  |                 { | ||||||
|  |                     //We found the destination and we can be sure (Because the the OrderBy above) | ||||||
|  |                     //That it's the most low cost option.  | ||||||
|  |                     var coord = checkCoord; | ||||||
|  |                     var steps = new List<string>(); | ||||||
|  |                     while (true) | ||||||
|  |                     { | ||||||
|  |                         steps.Add($"({coord.X},{coord.Y}) -> {_map[coord.X, coord.Y]}"); | ||||||
|  |                         coord = coord.Parent; | ||||||
|  |                         if (coord == null) | ||||||
|  |                         { | ||||||
|  |                             Steps = steps.Reverse<string>().ToArray(); | ||||||
|  |                             TotalSteps = steps.Count-1; //N coords touched, so N-1 steps. | ||||||
|  |                             return; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 visitedCoords.Add(checkCoord); | ||||||
|  |                 activeCoords.Remove(checkCoord); | ||||||
|  | 
 | ||||||
|  |                 var adjacentCoords = GetAdjacentCoords(checkCoord); | ||||||
|  | 
 | ||||||
|  |                 foreach (var adjCoor in adjacentCoords) | ||||||
|  |                 { | ||||||
|  |                     //Skip to next coord if we've already visited | ||||||
|  |                     if (visitedCoords.Any(x => x.X == adjCoor.X && x.Y == adjCoor.Y)) | ||||||
|  |                         continue; | ||||||
|  | 
 | ||||||
|  |                     //Its already pending as an active coord, but we need to re-check and update it if the cost is smaller | ||||||
|  |                     if (activeCoords.Any(x => x.X == adjCoor.X && x.Y == adjCoor.Y)) | ||||||
|  |                     { | ||||||
|  |                         var existingCoord = activeCoords.First(x => x.X == adjCoor.X && x.Y == adjCoor.Y); | ||||||
|  |                         if (existingCoord.CostDistance > checkCoord.CostDistance) | ||||||
|  |                         { | ||||||
|  |                             activeCoords.Remove(existingCoord); | ||||||
|  |                             activeCoords.Add(adjCoor); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         //New coord so we are adding it to the list | ||||||
|  |                         activeCoords.Add(adjCoor); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// This is a brute force method, it works for the sample but not my input, it takes way to long as it tries to explore every single path and square. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="visited"></param> | ||||||
|  |         /// <param name="pos"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         [Obsolete] | ||||||
|  |         public List<Coord> Traverse(List<Coord> visited, Coord pos) | ||||||
|  |         { | ||||||
|  |             visited.Add(pos); //Signify that we visited this coord in our search | ||||||
|  |             char val = _map[pos.X, pos.Y]; | ||||||
|  |             if (val == 'E') | ||||||
|  |             { | ||||||
|  |                 //We only want to return if the last visited char is 'z' since it needs to complete alphabet before continuing | ||||||
|  |                 var lastVisitedLocation = visited[visited.Count - 2]; | ||||||
|  |                 return _map[lastVisitedLocation.X, lastVisitedLocation.Y] == 'z' ? visited : null; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (val == 'S') val = 'a'; //So its on an even playing field. | ||||||
|  | 
 | ||||||
|  |             List<Coord> shortestPath = null; | ||||||
|  |             //left | ||||||
|  |             var newCoord = new Coord(pos.X, pos.Y - 1); | ||||||
|  |             if ((pos.Y - 1) >= 0 | ||||||
|  |                 && !visited.Any(c => c.X == newCoord.X && c.Y == newCoord.Y) | ||||||
|  |                 && _map[newCoord.X, newCoord.Y] - val <= 1) | ||||||
|  |             { | ||||||
|  |                 var newVisited = visited.Select(x => x).ToList(); | ||||||
|  |                 var path = Traverse(newVisited, newCoord); | ||||||
|  |                 if (path != null && (shortestPath == null || path.Count() < shortestPath.Count())) | ||||||
|  |                     shortestPath = path; | ||||||
|  |             } | ||||||
|  |             //right | ||||||
|  |             newCoord = new Coord(pos.X, pos.Y + 1); | ||||||
|  |             if ((pos.Y + 1) < MaxY | ||||||
|  |                 && !visited.Any(c => c.X == newCoord.X && c.Y == newCoord.Y) | ||||||
|  |                 && _map[newCoord.X, newCoord.Y] - val <= 1) | ||||||
|  |             { | ||||||
|  |                 var newVisited = visited.Select(x => x).ToList(); | ||||||
|  |                 var path = Traverse(newVisited, newCoord); | ||||||
|  |                 if (path != null && (shortestPath == null || path.Count() < shortestPath.Count())) | ||||||
|  |                     shortestPath = path; | ||||||
|  |             } | ||||||
|  |             //up | ||||||
|  |             newCoord = new Coord(pos.X - 1, pos.Y); | ||||||
|  |             if ((pos.X - 1) >= 0 | ||||||
|  |                 && !visited.Any(c => c.X == newCoord.X && c.Y == newCoord.Y) | ||||||
|  |                 && _map[newCoord.X, newCoord.Y] - val <= 1) | ||||||
|  |             { | ||||||
|  |                 var newVisited = visited.Select(x => x).ToList(); | ||||||
|  |                 var path = Traverse(newVisited, newCoord); | ||||||
|  |                 if (path != null && (shortestPath == null || path.Count() < shortestPath.Count())) | ||||||
|  |                     shortestPath = path; | ||||||
|  |             } | ||||||
|  |             //down | ||||||
|  |             newCoord = new Coord(pos.X + 1, pos.Y); | ||||||
|  |             if ((pos.X + 1) < MaxX | ||||||
|  |                 && !visited.Any(c => c.X == newCoord.X && c.Y == newCoord.Y) | ||||||
|  |                 && _map[newCoord.X, newCoord.Y] - val <= 1) | ||||||
|  |             { | ||||||
|  |                 var newVisited = visited.Select(x => x).ToList(); | ||||||
|  |                 var path = Traverse(newVisited, newCoord); | ||||||
|  |                 if (path != null && (shortestPath == null || path.Count() < shortestPath.Count())) | ||||||
|  |                     shortestPath = path; | ||||||
|  |             } | ||||||
|  |             return shortestPath; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class Coord | ||||||
|  |     { | ||||||
|  |         public Coord() { } | ||||||
|  |         public Coord(int x, int y) | ||||||
|  |         { | ||||||
|  |             this.X = x; | ||||||
|  |             this.Y = y; | ||||||
|  |         } | ||||||
|  |         public int X { get; set; } | ||||||
|  |         public int Y { get; set; } | ||||||
|  |         public int Cost { get; set; } | ||||||
|  |         public int Distance { get; set; } | ||||||
|  |         public int CostDistance { get { return Cost + Distance; } }  | ||||||
|  |         public Coord Parent { get; set; } | ||||||
|  | 
 | ||||||
|  |         //An estimated distance to a specific target | ||||||
|  |         public void SetDistance(Coord target) | ||||||
|  |         { | ||||||
|  |             this.Distance = Math.Abs(target.X - X) + Math.Abs(target.Y - Y); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user