mirror of
https://github.com/farcasclaudiu/MartianRobots.git
synced 2026-06-28 21:01:08 +03:00
Add project files.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class CommandProcessor
|
||||
{
|
||||
private Dictionary<string, IRobotCommand> processors = new Dictionary<string, IRobotCommand>();
|
||||
|
||||
public CommandProcessor()
|
||||
{
|
||||
Assembly.GetExecutingAssembly()
|
||||
.GetTypes()
|
||||
.Where(t => !t.IsAbstract && t.IsAssignableTo(typeof(IRobotCommand)))
|
||||
.Select(t =>
|
||||
{
|
||||
IRobotCommand? command = Activator.CreateInstance(t) as IRobotCommand;
|
||||
if(command != null)
|
||||
processors.Add(command.Command, command);
|
||||
return command;
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public void Process(RobotInfo robotInfo, string cmd)
|
||||
{
|
||||
|
||||
if (processors.ContainsKey(cmd))
|
||||
{
|
||||
processors[cmd].Process(robotInfo);
|
||||
} else {
|
||||
throw new NotSupportedException($"cmd {cmd} is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public interface IRobotCommand
|
||||
{
|
||||
public string Command { get; }
|
||||
|
||||
public void Process(RobotInfo robotInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Ardalis.GuardClauses;
|
||||
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class MarsNavigator
|
||||
{
|
||||
private WorldInfo worldInfo;
|
||||
|
||||
private CommandProcessor commandProcessor = new CommandProcessor();
|
||||
public MarsNavigator(WorldInfo worldInfo)
|
||||
{
|
||||
this.worldInfo=worldInfo;
|
||||
}
|
||||
|
||||
public string Navigate(RobotInfo robotInfo)
|
||||
{
|
||||
//validate robot coordintates in world
|
||||
Guard.Against.InvalidInput(robotInfo, nameof(robotInfo), ri => {
|
||||
return ri.PosX<= worldInfo.SizeX || ri.PosY <= worldInfo.SizeY;
|
||||
});
|
||||
|
||||
foreach (var cmd in robotInfo.Commands)
|
||||
{
|
||||
//save old coords
|
||||
var oldPosX = robotInfo.PosX;
|
||||
var oldPosY = robotInfo.PosY;
|
||||
|
||||
//process command
|
||||
commandProcessor.Process(robotInfo, cmd.ToString());
|
||||
|
||||
//check new robot coordintates in world
|
||||
if (robotInfo.PosX> worldInfo.SizeX || robotInfo.PosY > worldInfo.SizeY ||
|
||||
robotInfo.PosX<0 || robotInfo.PosY<0)
|
||||
{
|
||||
//revert to previous values
|
||||
robotInfo.PosX = oldPosX;
|
||||
robotInfo.PosY = oldPosY;
|
||||
|
||||
if (!worldInfo.HasScent(oldPosX, oldPosY))
|
||||
{
|
||||
robotInfo.IsLost = true;
|
||||
//add scent
|
||||
worldInfo.AddScent(robotInfo.PosX, robotInfo.PosY);
|
||||
//exit loop
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return robotInfo.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using Ardalis.GuardClauses;
|
||||
using System.Text;
|
||||
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class MarsSolver
|
||||
{
|
||||
public RobotSolution Process(string input)
|
||||
{
|
||||
var lines = input.Split(new string[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
|
||||
//extract world info
|
||||
var wInfo = lines[0].Split(" ");
|
||||
var sizeX = Convert.ToInt32(wInfo[0]);
|
||||
var sizeY = Convert.ToInt32(wInfo[1]);
|
||||
var worldInfo = new WorldInfo(sizeX, sizeY);
|
||||
var robotSolution = new RobotSolution()
|
||||
{
|
||||
Input = input,
|
||||
WorldInfo = worldInfo
|
||||
};
|
||||
|
||||
//map robots info and commands
|
||||
for (int i = 0; i < (lines.Count - 1)/2; i++)
|
||||
{
|
||||
var rInfo = lines[1 + i*2].Split(" ");
|
||||
var rPosX = Convert.ToInt32(rInfo[0]);
|
||||
var rPosY = Convert.ToInt32(rInfo[1]);
|
||||
var rHead = rInfo[2];
|
||||
|
||||
var robotCommands = lines[2 + i*2];
|
||||
Guard.Against.InvalidInput(robotCommands, nameof(robotCommands), rc => rc.Length<100);
|
||||
var robotInfo = new RobotInfo(rPosX, rPosY, rHead, robotCommands);
|
||||
robotSolution.Robots.Add(robotInfo);
|
||||
}
|
||||
|
||||
//process commands
|
||||
var navigator = new MarsNavigator(worldInfo);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var robotInfo in robotSolution.Robots)
|
||||
{
|
||||
if (sb.Length>0)
|
||||
sb.Append(Environment.NewLine);
|
||||
sb.Append(navigator.Navigate(robotInfo));
|
||||
}
|
||||
|
||||
//store output
|
||||
robotSolution.Output = sb.ToString();
|
||||
|
||||
return robotSolution;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Ardalis.GuardClauses" Version="4.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MartianRobots.Web\Shared\MartianRobots.Web.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class RobotCommandConstants
|
||||
{
|
||||
public const string HEADING = "NESW";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class RobotCommandForward: IRobotCommand
|
||||
{
|
||||
public string Command => "F";
|
||||
|
||||
public void Process(RobotInfo robotInfo)
|
||||
{
|
||||
int deltaX = 0;
|
||||
int deltaY = 0;
|
||||
switch (robotInfo.Head)
|
||||
{
|
||||
case "N":
|
||||
deltaY = 1;
|
||||
break;
|
||||
case "S":
|
||||
deltaY = -1;
|
||||
break;
|
||||
case "E":
|
||||
deltaX = 1;
|
||||
break;
|
||||
case "W":
|
||||
deltaX = -1;
|
||||
break;
|
||||
}
|
||||
robotInfo.PosX += deltaX;
|
||||
robotInfo.PosY += deltaY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class RobotCommandLeft : IRobotCommand
|
||||
{
|
||||
public string Command => "L";
|
||||
|
||||
public void Process(RobotInfo robotInfo)
|
||||
{
|
||||
var hIndex = RobotCommandConstants.HEADING.IndexOf(robotInfo.Head)-1;
|
||||
if(hIndex<0)
|
||||
hIndex = RobotCommandConstants.HEADING.Length-1;
|
||||
robotInfo.Head = RobotCommandConstants.HEADING[hIndex].ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class RobotCommandRight : IRobotCommand
|
||||
{
|
||||
public string Command => "R";
|
||||
|
||||
public void Process(RobotInfo robotInfo)
|
||||
{
|
||||
var hIndex = RobotCommandConstants.HEADING.IndexOf(robotInfo.Head)+1;
|
||||
if(hIndex>RobotCommandConstants.HEADING.Length-1)
|
||||
hIndex = 0;
|
||||
robotInfo.Head = RobotCommandConstants.HEADING[hIndex].ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Ardalis.GuardClauses;
|
||||
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class RobotInfo
|
||||
{
|
||||
public int PosX { get; set; }
|
||||
public int PosY { get; set; }
|
||||
public string Head { get; set; }
|
||||
public string Commands { get; }
|
||||
public bool IsLost { get; set; } = false;
|
||||
|
||||
public RobotInfo(int posX, int posY, string head, string commands)
|
||||
{
|
||||
Guard.Against.Negative(posX, nameof(posX));
|
||||
Guard.Against.Negative(posY, nameof(posX));
|
||||
this.PosX = posX;
|
||||
this.PosY = posY;
|
||||
this.Head = head;
|
||||
this.Commands = commands;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{PosX} {PosY} {Head}{ (IsLost ? " LOST" : string.Empty) }";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class RobotSolution
|
||||
{
|
||||
public WorldInfo WorldInfo { get; internal set; }
|
||||
public string Input { get; set; }
|
||||
public List<RobotInfo> Robots { get; internal set; } = new List<RobotInfo>();
|
||||
public string Output { get; internal set; }
|
||||
|
||||
public DateTime DateTimeStamp { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Ardalis.GuardClauses;
|
||||
|
||||
namespace MartianRobotsSolver
|
||||
{
|
||||
public class WorldInfo
|
||||
{
|
||||
private List<(int X,int Y)> scents = new List<(int X, int Y)>();
|
||||
public WorldInfo(int sizeX, int sizeY)
|
||||
{
|
||||
Guard.Against.OutOfRange(sizeX, nameof(sizeX), 0, 50);
|
||||
Guard.Against.OutOfRange(sizeY, nameof(sizeY), 0, 50);
|
||||
this.SizeX=sizeX;
|
||||
this.SizeY=sizeY;
|
||||
}
|
||||
|
||||
public int SizeX { get; internal set; }
|
||||
public int SizeY { get; internal set; }
|
||||
|
||||
internal void AddScent(int posX, int posY)
|
||||
{
|
||||
if(!HasScent(posX, posY))
|
||||
scents.Add((posX, posY));
|
||||
}
|
||||
|
||||
internal bool HasScent(int posX, int posY)
|
||||
{
|
||||
return scents.Contains((posX, posY));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user