I am working on a project here where I need to have a rolling average of a 2D array of numbers. The rolling average should average across a rolling "window" size of 8. I have a simple example here to demonstrate, but the idea is that with each new 2D array (a new data scan), that array will be copied into the rolling buffer that I have set up as a 3D array where the 3rd dimension is of size of the rolling window. With the current code I have below, I'm not getting the output I expect. To check if its working, I am just printing out the same position in each 2D scan across all scans of the rolling buffer, but I am not getting what I expect and I'm struggling to find issue in the code. Am I even going about this correctly? Thanks for any help. output attached below.
I would expect an output that looks like:
0 (nextline)
1 | 0 (nextline)
2 | 1 | 0 (nextline)
3 | 2 | 1 | 0 (nextline)
and so on ...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BlockCopySample
{
class Program
{
static void Main(string[] args)
{
RollingAverager RA = new RollingAverager();
for (int i = 0; i < 25; i++)
{
RA.addValue(i);
RA.PrintBuffer();
System.Threading.Thread.Sleep(1000);
}
}
}
class RollingAverager
{
const int INT_SIZE = 4;
const int DOUBLE_SIZE = 8;
const int BUFFER_LENGTH = 8;
const int SCAN_ROW_SIZE = 3;
const int SCAN_COLUMN_SIZE = 4;
//int scan_value_block_size = SCAN_ROW_SIZE * SCAN_COLUMN_SIZE * DOUBLE_SIZE;
int scan_value_block_size=0;
double[,] array_CurrentScan = null;
double[,,] array_FullBuffer = null;
double total = 0;
int numLoaded = 0;
public double Average { get; set; }
public RollingAverager()
{
array_CurrentScan = new double[SCAN_ROW_SIZE, SCAN_COLUMN_SIZE];
array_FullBuffer = new double[SCAN_ROW_SIZE, SCAN_COLUMN_SIZE, BUFFER_LENGTH];
scan_value_block_size = Buffer.ByteLength(array_CurrentScan);
}
//public void addValue(int newVal)
public void addValue(int index)
{
//Console.Write("here" + index.ToString() + "\n");
for (int j = 0; j < SCAN_ROW_SIZE; j++)
{
for (int k = 0; k < SCAN_COLUMN_SIZE; k++)
{
array_CurrentScan[j, k] = (double) index + j + k;
}
}
//Console.Write("here 1\n");
if (numLoaded == 0)
{
numLoaded++;
Console.Write("here 2\n");
}
else if(numLoaded > 0 && numLoaded < BUFFER_LENGTH)
{
//shift all buffer scans by 1 index to allow for new data to be copied into 0 index
Buffer.BlockCopy(array_FullBuffer, 0 * scan_value_block_size, array_FullBuffer, 1 * scan_value_block_size, numLoaded * scan_value_block_size);
Console.Write("here 3\n");
numLoaded++;
}
else
{
//shift all buffer scans by 1 index to allow for new data to be copied into 0 index
Buffer.BlockCopy(array_FullBuffer, 0 * scan_value_block_size, array_FullBuffer, 1 * scan_value_block_size, (BUFFER_LENGTH - 1) * scan_value_block_size);
Console.Write("here 4\n");
}
//Copy new data into buffer at index 0
Buffer.BlockCopy(array_CurrentScan, 0 * scan_value_block_size, array_FullBuffer, 0 * scan_value_block_size, scan_value_block_size);
//Average = total / numLoaded;
}
public void PrintBuffer()
{
//Console.Write("|");
//Console.Write(total.ToString() + "\n");
for (int i = 0; i < numLoaded; i++)
{
//total += array_FullBuffer[0,3,i];
Console.Write(array_FullBuffer[0, 0, 0].ToString() + " | ");
}
Console.Write("\n");
//Console.WriteLine(" Average = " + Average.ToString());
}
}
}
Related
I have a 2d array that is moving the char 'd' around and everything that isn't a char has '*'. When the movement starts all locations are a zero. Every time a move takes place, that location is incremented by 1. How do I increment the values at each spot?
My code:
using System;
class MainClass {
public static void Main (string[] args) {
bool over = false;
Console.Write("Enter city size: ");
int size = Convert.ToInt32(Console.ReadLine());
char [,] city = new char [size,size];
int [,] counts = new int [size,size];
CreateCity(city);
Console.Clear();
while(!over){
ShowCity(city, counts);
Move(city, counts, ref over);
System.Threading.Thread.Sleep((int)System.TimeSpan.FromSeconds(1).TotalMilliseconds);
if(!over){
Console.Clear();
Console.WriteLine();}
}//end while
Console.WriteLine("done");
}//end main
public static void CreateCity(char [,] c){
int rowLength = c.GetLength(0);
int colLength = c.GetLength(1);
for(int i = 0; i < rowLength; i++){
for(int j = 0; j < colLength; j++){
c[i,j] = '*';}//end j
}//end i
c[rowLength/2,colLength/2] = 'D';
}//end CreateCity
public static void ShowCity (char [,] c, int [,] d){
for(int i = 0; i < c.GetLength(0); i++){
for(int j = 0; j < c.GetLength(1); j++){Console.Write("{0}\t",c[i,j]);}
Console.WriteLine();
}}//end ShowCity
public static int GetDirection(){
Random random = new Random();
int num = random.Next(-1,2);
return num;
}
public static void Move (char [,] c, int [,] d, ref bool done){
int alocation = 0;
int bloaction = 0;
int anewLocation = 0;
int bnewlocation = 0;
int asize = c.GetLength(0);
int bsize = c.GetLength(1);
for(int i = 0; i < asize; i++){
for(int j = 0; j < bsize; j++){
if (c[i,j] == 'D'){
alocation = i;
bloaction = j;
}}}
anewLocation = alocation+GetDirection();
bnewlocation = bloaction+GetDirection();
if (( anewLocation == -1 || anewLocation == asize ) || ( bnewlocation == -1 || bnewlocation == bsize )){
done = true;
}//bounds if
else{
c[alocation,bloaction] = '*';
c[anewLocation,bnewlocation] = 'D';
}
}
}//end class
produces
* * * * *
* * * * D
* * * * *
* * * * *
* * * * *
and the D started in the middle and moved so I want it to produce
* * * * *
* * * 1 D
* * 1 2 1
* * * 1 1
* * * * *
so it changed to 1 if it the D moved there once. I have the int [,] counts = new int [size,size]; to hold the values I will use for the numbers but I would appreciate help on how to proceed
The Move() method should change to something like this:
else
{
d[alocation, bloaction]++;
string countStr = d[alocation, bloaction].ToString();
c[alocation, bloaction] = countStr[countStr.Length - 1];
c[anewLocation, bnewlocation] = 'D';
}
}
}//end class
I used countStr[countStr.Length - 1] because the city cells are characters and cannot hold the whole string. I think you'd better use string[,] instead of char[,].
I have a matrix with two values (0,1), I have to count the number of "1" in this matrix, so I tried to check all elements but for [1000,1000] matrix, it takes too long, and another problem is, I should do this many times for different matrices, so I hope anyone could help me with a faster mode.
here is my code:
for (int i = 0; i < matrix.height; i++)
{
for (int j = 0; j < matrix.width; j++)
{
if (matrix[j, i] == 1)
{
count++;
}
}
}
You actually have multiple options if you implement matrix class yourself:
public class BoleanMatrix
{
public bool this[int i, int j] {get;set;}
}
Cache it. Its easy. Upon any modification just update cached value of high bits. Implementation is irrelevant.
public class BoleanMatrix
{
private int _highBitCount = 0;
public bool this[int i, int j]
{
get;
set
{
if(prev != value)
{
if(value)
_highBitCount++;
else
_highBitCount--;
}
//set here
}
}
}
Change implementation to any sparse variant, for example, you can store matrix values as bits in byte[] array. If it is still too much - compress it with Run Length Encoding. It comes with drawbacks such as update and distribution problems of those matrix and usually they much slower than memory wide matrix. Efficient algorithm highly depends on nature of your matrix (distribution of values) and how you use them (multiplication, division, substraction, etc).
Try a parallel for loop ? If it can't be cached.
object mylock = new object();
int count = 0;
Parallel.For(0, matrix.height, i =>
{
int forcount = 0;
for (int j = 0; j < matrix.width; j++)
{
if (matrix[j, i] == 1)
{
forcount++;
}
}
lock (mylock)
{
count += forcount;
}
}
);
Given that you are only storing bits, you can improve the storage usage by storing the bits packed into uint values, which will reduce the amount of space required by a factor of 32 compared to using int for each value.
If you do that, then you can also more efficiently count the number of set bits by using one of many different "Hamming Weight" algorithms.
The drawback of this approach is that it may be slower to access the individual bits using the array BitMatrix indexer, but the computation of the number of set bits is much faster (more than 90 times faster for RELEASE mode builds on my PC).
Here's the sample code; the important class is BitMatrix:
using System;
using System.Diagnostics;
namespace Demo
{
class Program
{
static void Main()
{
int[,] matrix = new int[1000, 1000];
BitMatrix bitMatrix = new BitMatrix(1000, 1000);
// Randomly populate matrices and calculate expected count.
var rng = new Random(985912);
int expected = 0;
for (int r = 0; r < 1000; ++r)
{
for (int c = 0; c < 1000; ++c)
{
if ((rng.Next() & 1) == 0)
continue;
++expected;
matrix[r, c] = 1;
bitMatrix[r, c] = true;
}
}
Console.WriteLine("Expected = " + expected);
// Time the explicit matrix loop.
var sw = Stopwatch.StartNew();
for (int i = 0; i < 1000; ++i)
if (count1(matrix) != expected)
Console.WriteLine("count1() failed");
var elapsed1 = sw.ElapsedTicks;
Console.WriteLine(sw.Elapsed);
// Time the hamming weight approach.
sw.Restart();
for (int i = 0; i < 1000; ++i)
if (bitMatrix.NumSetBits() != expected)
Console.WriteLine("NumSetBits() failed");
var elapsed2 = sw.ElapsedTicks;
Console.WriteLine(sw.Elapsed);
Console.WriteLine("BitMatrix matrix is " + elapsed1 / elapsed2 + " times faster");
}
static int count1(int[,] matrix)
{
int h = 1 + matrix.GetUpperBound(0);
int w = 1 + matrix.GetUpperBound(1);
int c = 0;
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
if (matrix[i, j] == 1)
++c;
return c;
}
}
public sealed class BitMatrix
{
public BitMatrix(int rows, int cols)
{
Rows = rows;
Cols = cols;
bits = new uint[(rows*cols+31)/32];
}
public int Rows { get; }
public int Cols { get; }
public int NumSetBits()
{
int count = 0;
foreach (uint i in bits)
count += hammingWeight(i);
return count;
}
public bool this[int row, int col]
{
get
{
int n = row * Cols + col;
int i = n / 32;
int j = n % 32;
uint m = 1u << j;
return (bits[i] & m) != 0;
}
set
{
int n = row * Cols + col;
int i = n / 32;
int j = n % 32;
uint m = 1u << j;
if (value)
bits[i] |= m;
else
bits[i] &= ~m;
}
}
static int hammingWeight(uint i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (int)((((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
}
readonly uint[] bits;
}
}
If you are running 64-bit code, then it's actually more efficient to use an array of ulong and calculate a 64-bit hamming weight.
When I tried that on my PC, it was more than 120 times faster.
Here's the 64-bit version of BitMatrix:
public sealed class BitMatrix
{
public BitMatrix(int rows, int cols)
{
Rows = rows;
Cols = cols;
bits = new ulong[(rows*cols+63)/64];
}
public int Rows { get; }
public int Cols { get; }
public int NumSetBits()
{
int count = 0;
foreach (ulong i in bits)
count += hammingWeight(i);
return count;
}
public bool this[int row, int col]
{
get
{
int n = row * Cols + col;
int i = n / 64;
int j = n % 64;
ulong m = 1ul << j;
return (bits[i] & m) != 0;
}
set
{
int n = row * Cols + col;
int i = n / 64;
int j = n % 64;
ulong m = 1ul << j;
if (value)
bits[i] |= m;
else
bits[i] &= ~m;
}
}
static int hammingWeight(ulong i)
{
i = i - ((i >> 1) & 0x5555555555555555UL);
i = (i & 0x3333333333333333UL) + ((i >> 2) & 0x3333333333333333UL);
return (int)(unchecked(((i + (i >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56);
}
readonly ulong[] bits;
}
Observation: It turns out to be marginally faster to use for() rather than foreach in the loop in NumSetBits(), for example:
public int NumSetBits()
{
int count = 0;
for (var index = 0; index < bits.Length; index++)
count += hammingWeight(bits[index]);
return count;
}
On my PC this changes the performance from 120 times faster to 130 times faster.
Finally: If you want to take advantage of multithreading, you can do so like so (note the use of a Partitioner - this is to increase the block size of data calculated by each thread to make it a lot more efficient):
public int NumSetBits()
{
int count = 0;
var partitioner = Partitioner.Create(0, bits.Length);
Parallel.ForEach(partitioner, (range, loopState) =>
{
int subtotal = 0;
for (int i = range.Item1; i < range.Item2; ++i)
{
subtotal += hammingWeight(bits[i]);
}
Interlocked.Add(ref count, subtotal);
});
return count;
}
With this change, the Hamming approach is almost 200 times faster (and almost 300 times faster for a 2000x2000 matrix), but note that the amount by which it is faster depends on the proportion of 1 bits set.
After running my program I noticed that all values of my array are equal to one and after running the debugger I noticed that my for loops that should have populated the array are simply skipped over but I have absolutly no idea as to why. Could someone please tell me what I've done wrong?
The program reaches this line:
for (a = a; a >= 1000; a++) // Adds all prime numbers 1 through 1000 to primeA[];
and then jumps to:
for (int k = 0; k < primeA.Length; k++)
Complete code:
class calcPrime
{
/* #Method: isPrimeSET
* #param: int a, int b
* #return: true / false
* # Builds a list of primes and sorts them into a multi dimensional array.
*/
public int[,] isPrimeSet(int a, int b)
{
int[,] primeNumArray = new int[999, 999]; // Prime Multi Array 1000 slots in each array
int[] primeA = new int[999]; // All prime numbers a 1 to 1000
int[] primeB = new int[999]; // All prime numbers b 1 to 1000
ArrayList dumpArrayA = new ArrayList(); // None prime numbers
ArrayList dumpArrayB = new ArrayList(); // None prime numbers
for (a = a; a >= 1000; a++) // Adds all prime numbers 1 through 1000 to primA[];
{
if (isPrime(a) == true)
{
int i = 0; // Index of primeA
primeA[i] = a; // Add primes to a
i++;
}
else // Stores none prime numbers
{
int m = 0;
dumpArrayA.Add(m);
m++;
}
for (b = b; b >= 1000; b++) // Adds all prime number 1 through 1000 to primeB[];
{
if (isPrime(b) == true)
{
int j = 0; // Index of primeB
primeB[j] = b; // Add primes to b
j++;
}
else
{
int n = 0;
dumpArrayB.Add(n);
n++;
}
}
}
// Merge primesA[] and primesB[];
for (int k = 0; k < primeA.Length; k++)
{
primeNumArray[k, 0] = primeA[k];
primeNumArray[k, 1] = primeB[k];
}
// Print Contents of PrimeNumArray
for (int l = 0; l >= primeNumArray.Length; l++) {
Console.WriteLine(primeNumArray[l, l]);
}
return primeNumArray;
}
Else statements and dump arrays added in vain attempt at making the program work. Also I know I assigned a variable to the same variable in the for loops, I wanted the value to be set wherever the user chooses when the method is called.
There are many mistake there !!
I managed to correct your code
here is your corrected code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Prime_number
{
class Program
{
static void Main(string[] args)
{
int[,] k = isPrimeSet(1, 1);
Console.Read();
}
public static int[,] isPrimeSet(int a, int b)
{
int[,] primeNumArray; // Prime Multi Array 1000 slots in each array
ArrayList primeA = new ArrayList(); // All prime numbers a 1 to 1000
ArrayList primeB = new ArrayList(); // All prime numbers b 1 to 1000
ArrayList dumpArrayA = new ArrayList(); // None prime numbers
ArrayList dumpArrayB = new ArrayList(); // None prime numbers
int i = 0;
int m = 0;
int j = 0; // Index of primeB
int n = 0;
for (a = 1; a <= 1000; a++) // Adds all prime numbers 1 through 1000 to primA[];
{
if (isPrime(a) == true)
{
// Index of primeA
primeA.Add( a); // Add primes to a
i++;
}
else // Stores none prime numbers
{
dumpArrayA.Add(m);
m++;
}
}
for (b = 1; b <= 1000; b++) // Adds all prime number 1 through 1000 to primeB[];
{
if (isPrime(b) == true)
{
primeB.Add(b); // Add primes to b
j++;
}
else
{
dumpArrayB.Add(n);
n++;
}
}
primeNumArray= new int[primeA.Count,2];
// Merge primesA[] and primesB[];
for (int k = 0; k < primeA.Count; k++)
{
primeNumArray[k, 0] = (int)primeA[k];
primeNumArray[k, 1] = (int)primeB[k];
}
// Print Contents of PrimeNumArray
for (int l = 0; l <= primeNumArray.GetLength(0)-1; l++)
{
Console.WriteLine(primeNumArray[l, 0] + " " + primeNumArray[l, 1]);
}
return primeNumArray;
}
static bool isPrime(int num)
{
bool bPrime = true;
int factor = num / 2;
int i = 0;
for (i = 2; i <= factor; i++)
{
if ((num % i) == 0)
bPrime = false;
}
return bPrime;
}
}
}
Give it a try :) ! Thanks
I think index of array seems incorrect,
if (isPrime(a) == true)
{
int i = 0; // Index of primeA
primeA[i] = a; // Add primes to a
i++;
}
Isn't that changing only primeA[0] value? And for primeB array
int j = 0; // Index of primeB
primeB[j] = b; // Add primes to b
j++;
Maybe you should define i and j out of loop.
Hi I have 2D array type of int where I have numbers, for example from 1 to 100.
It's a game - something like Tic-Tac-Toe - but I use bigger array. So I need to put a character 'X' or 'O' from user to this array. But problem is I can't (don't know) how to put these characters in that int array. I wan to use only the console.
I tried make the array type of char but then I can't fill the array with numbers.
I know how to do it if user would have want put some numbers but then It doesn't look good...
I would be happy for any advice how to do it.
public void Napln () { //filling the array
int poc = 1;
for (int i = 0; i < pole.GetLength(1); i++)
{
Console.Write(" ");
for (int j = 0; j < pole.GetLength(0); j++)
{
if (poc < 10)
Console.Write(" " + (pole[j, i] = poc++) + " | ");
else if ( poc < 100 )
Console.Write( (pole[j,i] = poc ++) + " | ");
else
Console.Write((pole[j, i] = poc++) + " | ");
}
Console.WriteLine();
for ( int v = 0; v < roz1; v ++ )
Console.Write("_____|");
Console.WriteLine();
}
Console.WriteLine();
public void Pozice (int vyber) //find the user choice
{
for ( int i = 0; i < pole.GetLength(1); i ++ )
{
for ( int j = 0; j < pole.GetLength(0); j ++ )
{
if (pole[i, j] == vyber)
{
pole[i, j] = 'X';
hraci.Vypis();
}
}
}
}
public void Vypis() //print the same with change of user choice
{
for ( int i = 0; i < pole.GetLength(1); i ++ )
{
Console.Write(" ");
for ( int j = 0; j < pole.GetLength(0); j ++ )
{
if (pole[j,i] < 10)
Console.Write(" " + pole[j, i] + " | ");
else if (pole[j,i] < 100)
Console.Write(pole[j, i] + " | ");
else
Console.Write(pole[j, i] + " | ");
}
Console.WriteLine();
for (int v = 0; v < roz1; v++)
Console.Write("_____|");
Console.WriteLine();
}
}
I am the new one in C# especially the OOP. So if you have any more advice I would be happy.
Just taking your question as it is, I can imagine two ways I'd do it without getting too fancy.
The first one would be to use two arrays. One for holding the numbers (and int array), one for holding the player input (a char array holding "x" and "o"). This could look like this:
public class Program
{
public static void Main()
{
int width = 10;
int height = 10;
char[,] playerBoard = new char[width, height];
int[,] numberedBoard = new int[width, height];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// Fill the numbered board with 1 to 100
numberedBoard[x, y] = x * width + y + 1;
// And the player board with emptyness
playerBoard[x, y] = ' ';
}
}
System.Console.WriteLine("Number at x = 3 / y = 5: " + numberedBoard[3, 5]);
System.Console.WriteLine("Current owner of x = 3 / y = 5: \"" + playerBoard[3, 5] + "\"");
// Let's change the owner of x = 3 and y = 5
playerBoard[3, 5] = 'X';
System.Console.WriteLine("New owner of x = 3 / y = 5: \"" + playerBoard[3, 5] + "\"");
}
}
A second solution could be to create an object to fit your needs, and have an array of this one. The benefit is that you only have one array, and each cell holds all the information relevant to this cell. Consider the following:
using System;
public class Program
{
struct BoardEntry {
public int number;
public char owner;
}
public static void Main()
{
int width = 10;
int height = 10;
BoardEntry[,] board = new BoardEntry[width, height];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// For each "cell" of the board, we create a new instance of
// BoardEntry, holding the number for this cell and a possible ownage.
board[x, y] = new BoardEntry() {
number = x * width + y + 1,
owner = ' '
};
}
}
// You can access each of those instances with `board[x,y].number` and `board[x,y].owner`
System.Console.WriteLine("Number at x = 3 / y = 5: " + board[3, 5].number);
System.Console.WriteLine("Current owner of x = 3 / y = 5: \"" + board[3, 5].owner + "\"");
// Let's change the owner of x = 3 and y = 5
board[3, 5].owner = 'X';
System.Console.WriteLine("New owner at x = 3 / y = 5: \"" + board[3, 5].owner + "\"");
}
}
It seems like you are new to programming, so the first solution might be easier to understand and use right now, but I suggest you read at some point a little bit into what structs and classes are, because they let you do some really powerful things, like in this case bundle the relevant information that belongs together.
My routine is as follows (the SpeedyBitmap class just locks each bitmap for faster pixel data access):
private static bool TestRange(int number, int lower, int upper) {
return number >= lower && number <= upper;
}
public static List<Point> Search(Bitmap toSearch, Bitmap toFind, double percentMatch = 0.85, byte rTol = 2, byte gTol = 2, byte bTol = 2) {
List<Point> points = new List<Point>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int findArea = toFind.Width * toFind.Height;
int allowedMismatches = findArea - (int)(findArea * percentMatch);
int mismatches = 0;
using (SpeedyBitmap speedySearch = new SpeedyBitmap(toSearch)) {
using (SpeedyBitmap speedyFind = new SpeedyBitmap(toFind)) {
for (int i = 0; i < speedySearch.Height - speedyFind.Height + 1; i++) {
for (int j = 0; j < speedySearch.Width - speedyFind.Width + 1; j++) {
for (int k = 0; k < speedyFind.Height; k++) {
for (int l = 0; l < speedyFind.Width; l++) {
Color searchColor = speedySearch[j + l, i + k];
Color findColor = speedyFind[l, k];
if (!TestRange(searchColor.R, findColor.R - rTol, findColor.R + rTol) ||
!TestRange(searchColor.G, findColor.G - gTol, findColor.G + gTol) ||
!TestRange(searchColor.B, findColor.B - bTol, findColor.B + bTol)) {
mismatches++;
if (mismatches > allowedMismatches) {
mismatches = 0;
goto notFound;
}
}
}
}
points.Add(new Point(j, i));
continue;
notFound:
;
}
}
}
}
Console.WriteLine(stopwatch.ElapsedMilliseconds);
return points;
}
Searching a moderately sized image (1000x1000) takes over 20 seconds. Removing the percent match takes it down to a few hundred milliseconds, so I think I've established where the major bottleneck is.
How can I make this run faster? Perhaps I could flatten the two-dimensional arrays down to one-dimensional arrays and then apply some sort of sequence check on the two to possibly match up the longest sequence of where the toFind bitmap data appears with the respective tolerances and match percent. If this would be a good solution, how would I begin to implement it?