Reputation: 1614
Lets Say I have 4 strings in a List<string>
. I have used x y and z as an example here but could be any character.
"xyyy",
"yyyz",
"yyxz",
"yyyy"
How would I go about calculating the position of the of the SURROUNDING Y in terms of x in this list of strings ? So target X and calculate all touching Y points , note that I Wish to ignore z and only target y in this case. In the case of x in the top left part it would be 3 touching y points
I started iterating through the string by using ToCharArray()
and keeping track of the lower and upper bounds of where I am in the list but it quickly becomes recursion hell. Im looking for better solution to iterating through every list and checking if it has a below and upward bound and then iterating through all chars.
For clarifications sake :
Lets zoom on the first two strings in the list
"xyyy",
"yyyz"
We can clearly see that x touches the y to the right,diagonally and one below it which means 3 touching ys in total.
I would then have to output to console the amount of times x touched y PER string in the list - in other words : per line
Upvotes: 2
Views: 440
Reputation: 125
Here's a rough implementation of what you've described you want.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Touching {
class CharFinder {
public static List<Tuple<int, int>> counted = new List<Tuple<int, int>>();
public static void Main(string[] args) {
getInputs(out char target, out char indexed, out List<string> lines);
List<Tuple<int, int>> indexes = new List<Tuple<int, int>>();
for (int i = 0; i != lines.Count; i++) {
for (int j = 0; j != lines[i].Length; j++) {
if (lines[i][j] == indexed) {
indexes.Add(new Tuple<int, int>(i, j));
}
}
} int tCount = countNeighbor(lines, indexes[0], target);
for (int i = 0; i != indexes.Count; i++) {
tCount += countNeighbor(lines, indexes[i], target);
} Console.WriteLine(tCount.ToString());
Console.ReadLine();
}
public static int countNeighbor(List<string> grid, Tuple<int, int> ind, char target) {
int count = 0;
for (int i = ind.Item1 - 1; i < ind.Item1 + 2; i++) {
if (i == -1 || i >= grid.Count) { continue; }
for (int j = ind.Item2 - 1; j < ind.Item2 + 2; j++) {
if (j == -1 || j >= grid[i].Length) { continue; }
if (grid[i][j] == target && !counted.Contains(new Tuple<int, int>(i, j))) {
counted.Add(new Tuple<int, int>(i, j));
count++;
}
}
} return count;
}
public static void getInputs(out char target, out char indexed, out List<string> strs) {
int lines = 0;
strs = new List<string>();
while (true) {
Console.Clear();
Console.Write("Number of lines?: ");
try { lines = Convert.ToInt32(Console.ReadLine()); if (lines < 1) { throw new Exception(); } break; }
catch { Console.WriteLine("ERROR: Must be a positive integer."); Console.ReadLine(); }
} Console.Clear();
Console.Write("Target?: ");
target = Console.ReadLine()[0];
Console.Clear();
Console.Write("Indexed?: ");
indexed = Console.ReadLine()[0];
for (int i = 0; i < lines; i++) {
strs.Add(Console.ReadLine());
}
}
}
}
Upvotes: 0
Reputation: 3836
If you know the row length, and you know the index of the target(found by scanning the whole array for x, then it is trivial to compute the index of the adjacent squares
int i= //some index;
int l= //row length;
int y = i/l;//the floored quotient is the y offset
int x = i % l;//the remainder is the x offset
//Note that a negative result or a number greater than the whole array length is illegal so you have to catch that in your logic
int n= i-w;// skip a row back
int s = i+w;// skip a row forward
//if we hit the end then illegal else adjacent
int e= x+1 ==l? -1 : i+1;
int w= x-1 <0? -1: i-1;
//If you don't want to convert the list of string into a 2D array, just go line by line as above but y now simply becomes the index into your Lst, while x is a scan of the string. When you find the target character its adjacent values will be:
char n = list[y-1][x];
char s = list[y+1][x];
char e = list[y][x+1];
char w = list[y][x-1];
char sw= list[y+1][x-1];
char se= list[y+1][x+1];
//etc.
Just remember to check the bounds, just catch IndexOutOfRange
, and continue the loop, to avoid lots of tedious specialized check logic.
Those are my back of the napkin calculations, you might want to check with a picture. Also if you want diagonals I leave that as an exercise. Hint: use the same logic with the newly produced indices.
If you have the character values there are plenty of examples of summing them, I assume the difficult part was finding adjacency.
Upvotes: 1