I am tring to solve the directions reduction problem from CodeWar. The problem can be found in the following link https://www.codewars.com/kata/550f22f4d758534c1100025a/train/csharp. In this problem you get an array with strings and every string is a direction and you need to remove needless effort directions for example
a = {"NORTH", "SOUTH", "EAST", "WEST", "NORTH"}
the answer to this example will be
answer = {"NORTH"}
since north and south can be reduced and east and west too.
The solution I tried was by adding all the array elements to a list and remove items with condition. The code is working with some arrays but not all of them. In addition when I try to test the code in the VS(Visual Studio) I get a System.String[] as an output. Here is my code and thank you in advance for your help.
using System;
using System.Text;
using System.Linq;
using System.Collections.Generic;
namespace MyApplication
{
public class Kata
{
public static void Main()
{
string[] arr = { "NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST" };
List<string> arr1 = new List<string>();
List<string> arr2 = new List<string>();
for (int i = 0; i < arr.Length; i )
{ arr1.Add(arr[i]); }
for (int c = 0; c < arr1.Count -1; c )
{
if (arr1[c] == "NORTH" && arr1[c 1] == "SOUTH")
{
arr1.Remove(arr1[c]);
arr1.Remove(arr1[c]);
}
else if (arr1[c] == "SOUTH" && arr1[c 1] == "NORTH")
{
arr1.Remove(arr1[c]);
arr1.Remove(arr1[c]);
}
else if (arr1[c] == "WEST" && arr1[c 1] == "EAST")
{
arr1.Remove(arr1[c]);
arr1.Remove(arr1[c]);
}
else if (arr1[c] == "EAST" && arr1[c 1] == "WEST")
{
arr1.Remove(arr1[c]);
arr1.Remove(arr1[c]);
}
}
string[] a = arr1.ToArray();
for (int j = 0; j < a.Length; j )
{ arr2.Add(a[j]); }
for (int i = 0; i < arr2.Count - 1; i )
{
if (arr2[i] == "NORTH" && arr2[i 1] == "SOUTH")
{
arr2.Remove(arr2[i]);
arr2.Remove(arr2[i]);
}
else if (arr2[i] == "SOUTH" && arr2[i 1] == "NORTH")
{
arr2.Remove(arr2[i]);
arr2.Remove(arr2[i]);
}
else if (arr2[i] == "WEST" && arr2[i 1] == "EAST")
{
arr2.Remove(arr2[i]);
arr2.Remove(arr2[i]);
}
else if (arr2[i] == "EAST" && arr2[i 1] == "WEST")
{
arr2.Remove(arr2[i]);
arr2.Remove(arr2[i]);
}
}
string[] b = arr2.ToArray();
Console.WriteLine(b);
}
}
}
CodePudding user response:
I suggest using a linked list. We take direction
after direction
and either add it ti the result
if its not oppostite to the last direction of the result
or drop the last result direction.
For instance:
given : {"NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST"}
result : empty
step : direction : result before : action : result after
---------------------------------------------------------
1 : NORTH : empty : add : NORTH
2 : SOUTH : NORTH : drop : empty
3 : SOUTH : empty : add : SOUTH
4 : EAST : SOUTH : add : SOUTH -> EAST
5 : WEST : SOUTH -> EAST : drop : SOUTH
6 : NORTH : NORTH : drop : empty
7 : WEST : WEST : add : WEST
Finally we have result with one item "WEST"
Code:
using System.Linq;
...
// The "dirReduc" name is taken from the problem template
private static string[] dirReduc(string[] path) {
if (path == null)
return path;
var opposites = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) {
{ "North", "South" },
{ "South", "North" },
{ "East", "West" },
{ "West", "East" },
};
var result = new LinkedList<string>();
foreach (string direction in path)
if (!string.Equals(result.Last?.Value,
opposites[direction],
StringComparison.OrdinalIgnoreCase))
result.AddLast(direction);
else
result.RemoveLast();
return result.ToArray();
}
I hope that the code is quite clear; the only trick is in result.Last?.Value
fragment: if result
is empty, result.Last
will be null
and that's why I used null propagation - result.Last?.Value
to have null
and not exception.
Demo:
string[] test = new string[] {
"NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST" };
var result = dirReduc(test);
Console.Write(string.Join(" ", result));
Output:
WEST