Home > other >  Directions Reduction problem from CodeWar
Directions Reduction problem from CodeWar

Time:06-23

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
  • Related