Pattern matching in byte arrays [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Let's say I have two byte array which each contain a series of values like:
byte[] b = {50,60,70,80,90,10,20,1,2,3,4,5,50,2,3,1,2,3,4,5};
byte[] b2 = {1,2,3,4,5}
I can compare these two arrays and look for the equal values using LinQ methods. In this way, if I make a comparison between these two arrays, the result would be an index of b array where a value in an index of b2 array is a match.
I've been trying to exactly find the range where b2 array is recurring in b array. I mean
if (TheLenghtOfSearch==5) {Now the indexes of two regions must be return }
Result ->(7, 11), (15, 19)
if (TheLenghtOfSearch==2) {Now the indexes of around 9 regions where the two consecutive values in b2 recurred in b must be returned}
Result ->(7, 8), (15, 16), (8, 9), (13, 14), (16, 17), (9, 10), (17, 18), (10, 11), (18, 19)
I guess the solution is more mathematical.

I decided to use List, not array, because it have more helpers for this kind of operations.
As I understand depth = the amount of items that have to be equals in each array. This one works, check this out:
class Program
{
static void Main(string[] args)
{
List<byte> b = new List<byte>() { 50, 60, 70, 80, 90, 10, 20, 1, 2, 3, 4, 5, 50, 2, 3, 1, 2, 3, 4, 5 };
List<byte> b2 = new List<byte>() { 1, 2, 3, 4, 5 };
SmartComparer comparer = new SmartComparer();
//Setting the depth here, now the depth is = 5
var result = comparer.CompareArraysWithDepth(b, b2, 5);
foreach (var keyValuePair in result)
{
Console.WriteLine(String.Format("b[{0}]->b[{1}] are equal to b2[{2}]->b2[{3}]", keyValuePair.Key.Key,
keyValuePair.Key.Value, keyValuePair.Value.Key, keyValuePair.Value.Value));
}
}
}
public class SmartComparer
{
public Boolean CompareRange(List<byte> a, List<byte> b)
{
for (int i = 0; i < a.Count; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
/// <summary>
/// |
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="depth"></param>
/// <returns>Key->range in 'a', Value->range in 'b'</returns>
public List<KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>>> CompareArraysWithDepth(
List<byte> a, List<byte> b, int depth)
{
var result = new List<KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>>>();
if (depth > b.Count)
throw new ArgumentException("Array 'b' item count should be more then depth");
if(a.Count<b.Count)
throw new ArgumentException("Array 'a' item count should be more then Array 'b' item count");
for (int i = 0; i <= a.Count - depth; i++)
{
for (int j = 0; j <= b.Count - depth; j++)
{
if (CompareRange(a.GetRange(i, depth), b.GetRange(j, depth)))
{
result.Add(new KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>>(new KeyValuePair<int, int>(i, i + depth-1), new KeyValuePair<int, int>(j, j + depth-1)));
}
}
}
return result;
}
}
ADDED
The result of this operation for depth = 3:
b[7]->b[9] are equal to b2[0]->b2[2]
b[8]->b[10] are equal to b2[1]->b2[3]
b[9]->b[11] are equal to b2[2]->b2[4]
b[15]->b[17] are equal to b2[0]->b2[2]
b[16]->b[18] are equal to b2[1]->b2[3]
b[17]->b[19] are equal to b2[2]->b2[4]
The result of this operation for depth = 2:
b[7]->b[8] are equal to b2[0]->b2[1]
b[8]->b[9] are equal to b2[1]->b2[2]
b[9]->b[10] are equal to b2[2]->b2[3]
b[10]->b[11] are equal to b2[3]->b2[4]
b[13]->b[14] are equal to b2[1]->b2[2]
b[15]->b[16] are equal to b2[0]->b2[1]
b[16]->b[17] are equal to b2[1]->b2[2]
b[17]->b[18] are equal to b2[2]->b2[3]
b[18]->b[19] are equal to b2[3]->b2[4]
The result of this operation for depth = 5:
b[7]->b[11] are equal to b2[0]->b2[4]
b[15]->b[19] are equal to b2[0]->b2[4]

If Linq is not a absolutly required option for you, you can obtain the result by for loop:
public static IList<Tuple<int, int>> RecurringIndexes(Byte[] master, Byte[] toFind, int length) {
List<Tuple<int, int>> result = new List<Tuple<int, int>>();
// Let's return empty list ... Or throw appropriate exception
if (Object.ReferenceEquals(null, master))
return result;
else if (Object.ReferenceEquals(null, toFind))
return result;
else if (length < 0)
return result;
else if (length > toFind.Length)
return result;
Byte[] subRegion = new Byte[length];
for (int i = 0; i <= toFind.Length - length; ++i) {
for (int j = 0; j < length; ++j)
subRegion[j] = toFind[j + i];
for (int j = 0; j < master.Length - length + 1; ++j) {
Boolean counterExample = false;
for (int k = 0; k < length; ++k)
if (master[j + k] != subRegion[k]) {
counterExample = true;
break;
}
if (counterExample)
continue;
result.Add(new Tuple<int, int>(j, j + length - 1));
}
}
return result;
}
....
byte[] b = {50,60,70,80,90,10,20,1,2,3,4,5,50,2,3,1,2,3,4,5};
byte[] b2 = { 1, 2, 3, 4, 5 };
// Returns 2 patterns: {(7, 11), (15, 19)}
IList<Tuple<int, int>> indice5 = RecurringIndexes(b, b2, 5);
// Return 9 patterns: {(7, 8), (15, 16), (8, 9), (13, 14), (16, 17), (9, 10), (17, 18), (10, 11), (18, 19)}
IList<Tuple<int, int>> indice2 = RecurringIndexes(b, b2, 2);

Related

Pair Sum problem - c# code doesn't produce expected output-- please assist

public static int FindMaxNumForMaxSum(int[] nums, int k)
{
int retVal = 0;
int N = nums.Length;
var counter = 1;
var map = new Dictionary<int, int>();
for (var i = 0; i < N; i++)
{
if (nums[i] == retVal)
{
counter++;
continue;
}
var complement = k - nums[i];
retVal = complement;
if (nums[i] == complement)
{
if (!map.ContainsKey(complement))
{
map.Add(complement, counter);
}
else
{
map[complement] = counter++;
}
}
else
{
map.Add(complement, counter);
}
}
return counter;
}
Above is my code.
Problem description below:
Given a list of n integers arr[0..(n-1)], determine the number of different pairs of elements within it which sum to k.
If an integer appears in the list multiple times, each copy is considered to be different; that is, two pairs are considered different if one pair includes at least one array index which the other doesn't, even if they include the same values.
The above solution doesn't see to produce expected output and also there is a problem of adding duplicate keys in a dictionary.
Example 1
n = 5
k = 6
arr = [1, 2, 3, 4, 3]
output = 2
The valid pairs are 2+4 and 3+3.
Example 2
n = 5
k = 6
arr = [1, 5, 3, 3, 3]
output = 4
Example 3
arr = [2, 3, 6, 7, 4, 5, 1]
output = 3

Performant Concatenating 2D Arrays stored as sub-arrays [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Imagine we got a couple of 3x3 2D arrays that are identified by a X Y coordinate.
Pseudo code:
Array 0-0 Array 1-0
[[1,2,1] [[1,2,1]
[2,3,2] [2,3,2]
[3,1,2]] [3,1,2]]
Array 0-1 Array 1-1
[[1,2,1] [[1,2,1]
[2,3,2] [2,3,2]
[3,1,2]] [3,1,2]]
And we also have an index array, to index all this sub-arrays.
chunk_array = [
[Array 0-0, Array 0-1],
[Array 1-0, Array 1,1]
]
The problem is how to quickly create a final array, 6x6 containing all sub-arrays without having to iterate all elements of the array as this is a very critical place that has to operate in the minimal time possible.
So question: What would be the quickest way to perform this operation ? I've looked at Buffer copy, but not sure still what would be the best approach here.
Here's a solution based on the suggestion of Alexei Levenkov in the comments. From his comment: Fastest way to do something is not to do it at all... Does that work in your case (i.e. by wrapping all 4 into a class that exposes indexing the way you like)?
You create your four individual arrays and then add them to a wrapper capable of holding those arrays in a rectangular array. I use a function to access the individual elements, but you could use an indexer instead (if you are inclined that way - I'm not, that accessor seems a bit too complex for a simple indexer).
Here's the main class:
public class CompositeArray<T> where T:new()
{
private readonly T[,][,] _componentArray = null;
public int IndividualArrayWidth { get; }
public int IndividualArrayHeight { get; }
public int ComponentArrayWidth { get; }
public int ComponentArrayHeight { get; }
public int OverallArrayWidth => IndividualArrayWidth * ComponentArrayWidth;
public int OverallArrayHeight => IndividualArrayHeight * ComponentArrayHeight;
public CompositeArray(int individualArrayWidth, int individualArrayHeight, int componentArrayWidth,
int componentArrayHeight)
{
IndividualArrayWidth = individualArrayWidth;
IndividualArrayHeight = individualArrayHeight;
ComponentArrayWidth = componentArrayWidth;
ComponentArrayHeight = componentArrayHeight;
_componentArray = new T[ComponentArrayWidth, ComponentArrayHeight][,];
}
public void SetIndividualArray(int x, int y, T[,] array)
{
if (x < 0 || x >= IndividualArrayWidth)
{
throw new ArgumentOutOfRangeException(nameof(x), x, $#"Must be between 0 and {IndividualArrayWidth - 1}");
}
if (y < 0 || y >= IndividualArrayHeight)
{
throw new ArgumentOutOfRangeException(nameof(y), y, $#"Must be between 0 and {IndividualArrayHeight - 1}");
}
if (array.GetLength(0) != IndividualArrayWidth || array.GetLength(1) != IndividualArrayHeight)
{
throw new ArgumentOutOfRangeException(nameof(array), $#"Must be between an array that is {IndividualArrayWidth} by {IndividualArrayHeight}");
}
_componentArray[x, y] = array;
}
public T GetOverallElement(int x, int y)
{
if (x < 0 || x >= OverallArrayWidth)
{
throw new ArgumentOutOfRangeException(nameof(x), x, $#"Must be between 0 and {OverallArrayWidth - 1}");
}
if (y < 0 || y >= OverallArrayHeight)
{
throw new ArgumentOutOfRangeException(nameof(y), y, $#"Must be between 0 and {OverallArrayHeight - 1}");
}
int whichArrayX = x / IndividualArrayWidth;
int innerX = x % IndividualArrayWidth;
int whichArrayY = y / IndividualArrayHeight;
int innerY = y % IndividualArrayHeight;
return (_componentArray[whichArrayX, whichArrayY][innerX, innerY]);
}
}
Note that I create a rectangularly jagged rectangular array. It took a bit to figure out the syntax.
Note that there is no copying at all. You only pay for two integer divisions and two integer modulus operations per element access. If you only use 2x2 arrays, you could reduce that to two bit-shifts and two bit-tests (since division by two is a simple bit-shift, and checking for even/odd is simply a test of the least significant bit).
Here's some code that exercises that class:
int[,] array00 = new int[,]
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int[,] array01 = new int[,]
{
{11, 12, 13},
{14, 15, 16},
{17, 18, 19}
};
int[,] array10 = new int[,]
{
{21, 22, 23},
{24, 25, 26},
{27, 28, 29}
};
int[,] array11 = new int[,]
{
{31, 32, 33},
{34, 35, 36},
{37, 38, 39}
};
CompositeArray<int> bigArray = new CompositeArray<int>(array00.GetLength(0), array00.GetLength(1), 2,2);
bigArray.SetIndividualArray(0, 0, array00);
bigArray.SetIndividualArray(0, 1, array01);
bigArray.SetIndividualArray(1, 0, array10);
bigArray.SetIndividualArray(1, 1, array11);
var shouldBe2 = bigArray.GetOverallElement(0, 1);
var shouldBe6 = bigArray.GetOverallElement(1, 2);
var shouldBe28 = bigArray.GetOverallElement(5, 1);
var shouldBe16 = bigArray.GetOverallElement(1, 5);
var shouldBe32 = bigArray.GetOverallElement(3, 4);
I think the best you can do is copy chunks of 3 values as they are all the source values that are contiguous in the destination array:
var ans = new int[6,6];
for (int row = 0; row < 2; ++row) {
for (int col = 0; col < 2; ++col) {
var srcArray = chunk_array[row, col];
for (int subRow = 0; subRow < 3; ++subRow) {
Array.Copy(srcArray, subRow*3, ans, subRow*6+row*18+col*3, 3);
}
}
}
Some performance testing doesn't show much optimization of this code possible.

Fill a multidimensional array with pairs of ordered values

I have to present 16 financial products in a 4x4 matrix on a website. The matrix replaces the representation of a scatter graph, where the returns of the product are represented in the X axis and the risk in the Y (they are simply pairs of values), so the product in the lowest left place are the one with the minor risk and the minor returns and the ones in the top right are the ones with the major risk and the major return.
To reach this result, I thought of putting the products in a multidimensional 4x4 array, but I don't know how to sort the pairs of values correctly.
I tried some sorting methods but nobody gave me the required result.
Here is an Exammple of what I want to obtain:
Taking this sixteen couple of values:
(3,5)-(2,8)-(7,3)-(4,9)-(3,2)-(4,10)-(6,2)-(1,4)-(5,2)-(8,9)-(7,11)-(10,12)-(3,11)-(5,10)-(2,16)-(9,15)
I would like to show it in the matrix in this order
Y
^
|(7,3)(8,9)(10,12)(9,15)
|(5,2)(6,2)(5,10)(7,11)
|(3,2)(3,5)(4,9)(4,10)
|(1,4)(2,8)(3,11)(2,16)
|_____________________>X
I'm adding another answer because the first one and its comments are before you added an example and that answer was way off.
Your example is helpful. It looks like the first value in your pair is Y and the second is X? If so, that's opposite normal convention.
It seems your unspoken rules for arrangement are to arrange the pairs in such a way that the Y (left) values are increasing upward in each column, and the X (right) values are increasing rightward in each row. Importantly, it seems for Y values the columns are otherwise independent, and for the X values the rows are otherwise independent. Independent meaning you don't care about absolute placement from position to position. Like for Y, you don't care that a 3 in the third column is lower than the 3 in the first column.
But these rules will still produce multiple valid result sets. For example, in your example, (7,3) and (6,2) can be swapped and the rules as outlined above still apply.
If these unspoken rules are correct, try this broad approach:
(1) Put the list into a matrix, (2) sort all of the columns, (3) sort all of the rows, (4) repeat sorting columns and rows a few times.
Here is some code to illustrate this. Because this is just a 4x4 matrix, efficiency isn't important.
public static void Main()
{
Tuple<int,int>[] pairs = {
Tuple.Create(3, 5),
Tuple.Create(2, 8),
Tuple.Create(7, 3),
Tuple.Create(4, 9),
Tuple.Create(3, 2),
Tuple.Create(4, 10),
Tuple.Create(6, 2),
Tuple.Create(1, 4),
Tuple.Create(5, 2),
Tuple.Create(8, 9),
Tuple.Create(7, 11),
Tuple.Create(10, 12),
Tuple.Create(3, 11),
Tuple.Create(5, 10),
Tuple.Create(2, 16),
Tuple.Create(9, 15)
};
var matrix = load(pairs); //Put data into a 4x4 matrix, order doesn't matter
Console.WriteLine("Original input:");
print(matrix);
matrix = sort(matrix);
Console.WriteLine("Ordered output:");
print(matrix);
}
private static Tuple<int,int>[,] load(Tuple<int,int>[] pairs) {
var rv = new Tuple<int, int>[4, 4];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
rv[i, j] = pairs[i * 4 + j];
}
}
return rv;
}
private static Tuple<int, int>[, ] sort(Tuple<int, int>[,] matrix) {
var rv = matrix;
for (int i = 0; i < 4; i++) {
rv = orderCols(rv);
rv = orderRows(rv);
}
return rv;
}
private static Tuple<int,int>[,] orderCols(Tuple<int,int>[,] matrix) {
for (int c = 0; c < 4; c++) {
//Convert column to 1D array, sort it, then apply it back
Tuple<int, int>[] a = new Tuple<int, int>[4];
for (int r = 0; r < 4; r++) a[r] = matrix[r, c];
a = a.OrderByDescending(t => t.Item1).ToArray();
for (int r = 0; r < 4; r++) matrix[r, c] = a[r];
}
return matrix;
}
private static Tuple<int,int>[,] orderRows(Tuple<int,int>[,] matrix) {
for (int r = 0; r < 4; r++) {
//Convert row to 1D array, sort it, then apply it back
Tuple<int, int>[] a = new Tuple<int, int>[4];
for (int c = 0; c < 4; c++) a[c] = matrix[r, c];
a = a.OrderBy(t => t.Item2).ToArray();
for (int c = 0; c < 4; c++) matrix[r, c] = a[c];
}
return matrix;
}
private static void print(Tuple<int, int>[,] matrix) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++)
Console.Write(writeTuple(matrix[i, j]));
Console.WriteLine();
}
Console.WriteLine();
}
private static string writeTuple(Tuple<int, int> t) {
var a = t.Item1.ToString().PadLeft(2, ' ');
var b = t.Item2.ToString().PadLeft(2, ' ');
return String.Format("({0}, {1}) ", a, b);
}
Output:
Original input:
( 3, 5) ( 2, 8) ( 7, 3) ( 4, 9)
( 3, 2) ( 4, 10) ( 6, 2) ( 1, 4)
( 5, 2) ( 8, 9) ( 7, 11) (10, 12)
( 3, 11) ( 5, 10) ( 2, 16) ( 9, 15)
Ordered output:
( 6, 2) ( 7, 3) ( 8, 9) (10, 12)
( 5, 2) ( 4, 9) ( 7, 11) ( 9, 15)
( 3, 2) ( 3, 5) ( 5, 10) ( 4, 10)
( 1, 4) ( 2, 8) ( 3, 11) ( 2, 16)
As you can see, the output does not match your example output exactly, but it is valid per the rules you seem to want. Depending on the ordering of the input, the output will be different because there are multiple valid result sets. If I'm wrong in any assumptions, let me know.
Unless I misunderstand your problem, it seems to me you need to sort your collection linearly (1-dimensional), and then present it (2-dimensional). There's a distinction between data storage and data presentation. Here's what I came up with:
//Sample data to work with
var products = new List<KeyValuePair<string, int>>();
products.Add(new KeyValuePair<string, int>("A", 12));
products.Add(new KeyValuePair<string, int>("B", 23));
products.Add(new KeyValuePair<string, int>("C", 62));
products.Add(new KeyValuePair<string, int>("D", 17));
products.Add(new KeyValuePair<string, int>("E", 11));
products.Add(new KeyValuePair<string, int>("F", 75));
products.Add(new KeyValuePair<string, int>("G", 95));
products.Add(new KeyValuePair<string, int>("H", 24));
products.Add(new KeyValuePair<string, int>("I", 85));
products.Add(new KeyValuePair<string, int>("J", 41));
products.Add(new KeyValuePair<string, int>("K", 76));
products.Add(new KeyValuePair<string, int>("L", 77));
products.Add(new KeyValuePair<string, int>("M", 33));
products.Add(new KeyValuePair<string, int>("N", 81));
products.Add(new KeyValuePair<string, int>("O", 34));
products.Add(new KeyValuePair<string, int>("P", 45));
//Sort the collection
List<KeyValuePair<string, int>> ordered = products.OrderBy(x => x.Value).ToList();
//Put linear results into 2D array (4x4)
var matrix = new KeyValuePair<string, int>[4,4];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
matrix[i, j] = ordered[i * 4 + j];
//Write out results
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
var c = ordered[i * 4 + j];
Console.Write(c.Key + ": " + c.Value.ToString() + " ");
}
Console.WriteLine();
}
Output:
E: 11 A: 12 D: 17 B: 23
H: 24 M: 33 O: 34 J: 41
P: 45 C: 62 F: 75 K: 76
L: 77 N: 81 I: 85 G: 95

Add Int[] array into List<int[]>

I'm having trouble with int[] arrays and adding them to a List<>. I'd like to add the values of my int[] array to something each loop but every time I do this my "something" gets the same value for every element I add. Very annoying. I understand arrays are always reference vars. However even the "new" key word doesn't seem to help. What needs to happen is to add result to some enumerated object like a List or Array or ArrayList.
Here's the codility question:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max_counter − all counters are set to the maximum value of any counter.
A non-empty zero-indexed array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max_counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
I copied some code from others and the variable "result" does indeed load the data correctly. I just wanted to copy it back to the main program so I could see it. The only method that works is += add it into a string. Thus losing any efficiency I might have gained.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testarray
{
class Program
{
static void Main(string[] args)
{
int[] A = new int[7];
A[0] = 3;
A[1] = 4;
A[2] = 4;
A[3] = 6;
A[4] = 1;
A[5] = 4;
A[6] = 4;
List<int[]> finish = solution(5, A);
}
public static List<int[]> solution(int N, int[] A)
{
int[] result = new int[N];
int maximum = 0;
int resetlimit = 0;
int iter = 0;
List<int[]> collected_result = new List<int[]>;
for (int K = 0; K < A.Length; K++)
{
if (A[K] < 1 || A[K] > N + 1)
{
throw new InvalidOperationException();
}
if (A[K] >= 1 && A[K] <= N)
{
if (result[A[K] - 1] < resetlimit)
{
result[A[K] - 1] = resetlimit + 1;
}
else
{
result[A[K] - 1]++;
}
if (result[A[K] - 1] > maximum)
{
maximum = result[A[K] - 1];
}
}
else
{
resetlimit = maximum;
result = Enumerable.Repeat(maximum, result.Length).ToArray<int>();
}
collected_result.Add(result);
}
// for (int i = 0; i < result.Length; i++)
//result[i] = Math.max(resetLimit, result[i]);
return collected_result;
}
}
}
This doesn't work, the collected_result ends up like:
(0,0,1,2,0)
(0,0,1,2,0)
(0,0,1,2,0)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
(3,2,2,4,2)
I know it's the line collected_result.Add(result); adding the reference each time to every instance of result in the List<>. Bother. I've tried adding "new" which is a compiler error. Finally in desperation I just added everything to a very long string. Can someone help me figure out how to properly load an object to pass back to main?
Easiest way to go:
Get a copy of your array before adding it to list:
collected_result.Add(result.ToArray());
Here is a Python solution:
def solution(A, N):
lenA = len(A)
k = 0
max_counter_value = 0
counters = [0 for x in range(0, N)]
for k in range(0, lenA):
if A[k] >= 1 and A[k] <= N:
counters[A[k] - 1] += 1
max_counter_value = max(counters)
if A[k] == N + 1:
counters = [max_counter_value for x in range(0, N)]
print counters
A = [3, 4, 4, 6, 1, 4, 4]
N = 5
solution(A, N)

C# find highest array value and index

So I have an unsorted numeric array int[] anArray = { 1, 5, 2, 7 }; and I need to get both the value and the index of the largest value in the array which would be 7 and 3, how would I do this?
This is not the most glamorous way but works.
(must have using System.Linq;)
int maxValue = anArray.Max();
int maxIndex = anArray.ToList().IndexOf(maxValue);
int[] anArray = { 1, 5, 2, 7 };
// Finding max
int m = anArray.Max();
// Positioning max
int p = Array.IndexOf(anArray, m);
If the index is not sorted, you have to iterate through the array at least once to find the highest value. I'd use a simple for loop:
int? maxVal = null; //nullable so this works even if you have all super-low negatives
int index = -1;
for (int i = 0; i < anArray.Length; i++)
{
int thisNum = anArray[i];
if (!maxVal.HasValue || thisNum > maxVal.Value)
{
maxVal = thisNum;
index = i;
}
}
This is more verbose than something using LINQ or other one-line solutions, but it's probably a little faster. There's really no way to make this faster than O(N).
A succinct one-liner:
var (number, index) = anArray.Select((n, i) => (n, i)).Max();
Test case:
var anArray = new int[] { 1, 5, 7, 4, 2 };
var (number, index) = anArray.Select((n, i) => (n, i)).Max();
Console.WriteLine($"Maximum number = {number}, on index {index}.");
// Maximum number = 7, on index 2.
Features:
Uses Linq (not as optimized as vanilla, but the trade-off is less code).
Does not need to sort.
Computational complexity: O(n).
Space complexity: O(n).
Remarks:
Make sure the number (and not the index) is the first element in the tuple because tuple sorting is done by comparing tuple items from left to right.
The obligatory LINQ one[1]-liner:
var max = anArray.Select((value, index) => new {value, index})
.OrderByDescending(vi => vi.value)
.First();
(The sorting is probably a performance hit over the other solutions.)
[1]: For given values of "one".
Here are two approaches. You may want to add handling for when the array is empty.
public static void FindMax()
{
// Advantages:
// * Functional approach
// * Compact code
// Cons:
// * We are indexing into the array twice at each step
// * The Range and IEnumerable add a bit of overhead
// * Many people will find this code harder to understand
int[] array = { 1, 5, 2, 7 };
int maxIndex = Enumerable.Range(0, array.Length).Aggregate((max, i) => array[max] > array[i] ? max : i);
int maxInt = array[maxIndex];
Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");
}
public static void FindMax2()
{
// Advantages:
// * Near-optimal performance
int[] array = { 1, 5, 2, 7 };
int maxIndex = -1;
int maxInt = Int32.MinValue;
// Modern C# compilers optimize the case where we put array.Length in the condition
for (int i = 0; i < array.Length; i++)
{
int value = array[i];
if (value > maxInt)
{
maxInt = value;
maxIndex = i;
}
}
Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");
}
int[] numbers = new int[7]{45,67,23,45,19,85,64};
int smallest = numbers[0];
for (int index = 0; index < numbers.Length; index++)
{
if (numbers[index] < smallest) smallest = numbers[index];
}
Console.WriteLine(smallest);
public static class ArrayExtensions
{
public static int MaxIndexOf<T>(this T[] input)
{
var max = input.Max();
int index = Array.IndexOf(input, max);
return index;
}
}
This works for all variable types...
var array = new int[]{1, 2, 4, 10, 0, 2};
var index = array.MaxIndexOf();
var array = new double[]{1.0, 2.0, 4.0, 10.0, 0.0, 2.0};
var index = array.MaxIndexOf();
this works like a charm, no need for linq or other extensions
int[] anArray = { 1, 5, 2, 7 };
int i, mx;
int j = 0;
mx = anArray[0];
for (i = 1; i < anArray.Length; i++)
{
if (anArray[i] > mx)
{
mx = anArray[i];
j = i;
}
}
Console.Write("The largest value is: {0}, of index: {1}", mx, j);
anArray.Select((n, i) => new { Value = n, Index = i })
.Where(s => s.Value == anArray.Max());
Output for bellow code:
00:00:00.3279270 - max1
00:00:00.2615935 - max2
00:00:00.6010360 - max3 (arr.Max())
With 100000000 ints in array not very big difference but still...
class Program
{
static void Main(string[] args)
{
int[] arr = new int[100000000];
Random randNum = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr[i] = randNum.Next(-100000000, 100000000);
}
Stopwatch stopwatch1 = new Stopwatch();
Stopwatch stopwatch2 = new Stopwatch();
Stopwatch stopwatch3 = new Stopwatch();
stopwatch1.Start();
var max = GetMaxFullIterate(arr);
Debug.WriteLine( stopwatch1.Elapsed.ToString());
stopwatch2.Start();
var max2 = GetMaxPartialIterate(arr);
Debug.WriteLine( stopwatch2.Elapsed.ToString());
stopwatch3.Start();
var max3 = arr.Max();
Debug.WriteLine(stopwatch3.Elapsed.ToString());
}
private static int GetMaxPartialIterate(int[] arr)
{
var max = arr[0];
var idx = 0;
for (int i = arr.Length / 2; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
if (arr[idx] > max)
{
max = arr[idx];
}
idx++;
}
return max;
}
private static int GetMaxFullIterate(int[] arr)
{
var max = arr[0];
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}
public static void Main()
{
int a,b=0;
int []arr={1, 2, 2, 3, 3, 4, 5, 6, 5, 7, 7, 7, 100, 8, 1};
for(int i=arr.Length-1 ; i>-1 ; i--)
{
a = arr[i];
if(a > b)
{
b=a;
}
}
Console.WriteLine(b);
}
Old post, but this is super easy with Lists:
For Maximum:
List<int> lst = new List<int>(YourArray);
int Max = lst.OrderByDescending(x => x).First();
For Minimum:
List<int> lst = new List<int>(YourArray);
int Max = lst.OrderBy(x => x).First();
Of course you can substitute "int" data type with any numeric variable type (float, decimal, etc).
This is very high performance BTW and beats any other method (IMHO)
int[] Data= { 1, 212, 333,2,12,3311,122,23 };
int large = Data.Max();
Console.WriteLine(large);
Here is a LINQ solution which is O(n) with decent constant factors:
int[] anArray = { 1, 5, 2, 7, 1 };
int index = 0;
int maxIndex = 0;
var max = anArray.Aggregate(
(oldMax, element) => {
++index;
if (element <= oldMax)
return oldMax;
maxIndex = index;
return element;
}
);
Console.WriteLine("max = {0}, maxIndex = {1}", max, maxIndex);
But you should really write an explicit for lop if you care about performance.
Just another perspective using DataTable. Declare a DataTable with 2 columns called index and val. Add an AutoIncrement option and both AutoIncrementSeed and AutoIncrementStep values 1 to the index column. Then use a foreach loop and insert each array item into the datatable as a row. Then by using Select method, select the row having the maximum value.
Code
int[] anArray = { 1, 5, 2, 7 };
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[2] { new DataColumn("index"), new DataColumn("val")});
dt.Columns["index"].AutoIncrement = true;
dt.Columns["index"].AutoIncrementSeed = 1;
dt.Columns["index"].AutoIncrementStep = 1;
foreach(int i in anArray)
dt.Rows.Add(null, i);
DataRow[] dr = dt.Select("[val] = MAX([val])");
Console.WriteLine("Max Value = {0}, Index = {1}", dr[0][1], dr[0][0]);
Output
Max Value = 7, Index = 4
Find a demo here
If you know max index accessing the max value is immediate. So all you need is max index.
int max=0;
for(int i = 1; i < arr.Length; i++)
if (arr[i] > arr[max]) max = i;
This is a C# Version. It's based on the idea of sort the array.
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
Array.Sort(A);
var max = A.Max();
if(max < 0)
return 1;
else
for (int i = 1; i < max; i++)
{
if(!A.Contains(i)) {
return i;
}
}
return max + 1;
}
Consider following:
/// <summary>
/// Returns max value
/// </summary>
/// <param name="arr">array to search in</param>
/// <param name="index">index of the max value</param>
/// <returns>max value</returns>
public static int MaxAt(int[] arr, out int index)
{
index = -1;
int max = Int32.MinValue;
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > max)
{
max = arr[i];
index = i;
}
}
return max;
}
Usage:
int m, at;
m = MaxAt(new int[]{1,2,7,3,4,5,6}, out at);
Console.WriteLine("Max: {0}, found at: {1}", m, at);
This can be done with a bodiless for loop, if we're heading towards golf ;)
//a is the array
int mi = a.Length - 1;
for (int i=-1; ++i<a.Length-1; mi=a[mi]<a[i]?i:mi) ;
The check of ++i<a.Length-1 omits checking the last index. We don't mind this if we set it up as if the max index is the last index to start with.. When the loop runs for the other elements it will finish and one or the other thing is true:
we found a new max value and hence a new max index mi
the last index was the max value all along, so we didn't find a new mi, and we stuck with the initial mi
The real work is done by the post-loop modifiers:
is the max value (a[mi] i.e. array indexed by mi) we found so far, less than the current item?
yes, then store a new mi by remembering i,
no then store the existing mi (no-op)
At the end of the operation you have the index at which the max is to be found. Logically then the max value is a[mi]
I couldn't quite see how the "find max and index of max" really needed to track the max value too, given that if you have an array, and you know the index of the max value, the actual value of the max value is a trivial case of using the index to index the array..
Another answer in this long list, but I think it's worth it, because it provides some benefits that most (or all?) other answers don't:
The method below loops only once through the collection, therefore the order is O(N).
The method finds ALL indices of the maximum values.
The method can be used to find the indices of any comparison: min, max, equals, not equals, etc.
The method can look into objects via a LINQ selector.
Method:
///-------------------------------------------------------------------
/// <summary>
/// Get the indices of all values that meet the condition that is defined by the comparer.
/// </summary>
/// <typeparam name="TSource">The type of the values in the source collection.</typeparam>
/// <typeparam name="TCompare">The type of the values that are compared.</typeparam>
/// <param name="i_collection">The collection of values that is analysed.</param>
/// <param name="i_selector">The selector to retrieve the compare-values from the source-values.</param>
/// <param name="i_comparer">The comparer that is used to compare the values of the collection.</param>
/// <returns>The indices of all values that meet the condition that is defined by the comparer.</returns>
/// Create <see cref="IComparer{T}"/> from comparison function:
/// Comparer{T}.Create ( comparison )
/// Comparison examples:
/// - max: (a, b) => a.CompareTo (b)
/// - min: (a, b) => -(a.CompareTo (b))
/// - == x: (a, b) => a == 4 ? 0 : -1
/// - != x: (a, b) => a != 4 ? 0 : -1
///-------------------------------------------------------------------
public static IEnumerable<int> GetIndices<TSource, TCompare> (this IEnumerable<TSource> i_collection,
Func<TSource, TCompare> i_selector,
IComparer<TCompare> i_comparer)
{
if (i_collection == null)
throw new ArgumentNullException (nameof (i_collection));
if (!i_collection.Any ())
return new int[0];
int index = 0;
var indices = new List<int> ();
TCompare reference = i_selector (i_collection.First ());
foreach (var value in i_collection)
{
var compare = i_selector (value);
int result = i_comparer.Compare (compare, reference);
if (result > 0)
{
reference = compare;
indices.Clear ();
indices.Add (index);
}
else if (result == 0)
indices.Add (index);
index++;
}
return indices;
}
If you don't need the selector, then change the method to
public static IEnumerable<int> GetIndices<TCompare> (this IEnumerable<TCompare> i_collection,
IComparer<TCompare> i_comparer)
and remove all occurences of i_selector.
Proof of concept:
//########## test #1: int array ##########
int[] test = { 1, 5, 4, 9, 2, 7, 4, 6, 5, 9, 4 };
// get indices of maximum:
var indices = test.GetIndices (t => t, Comparer<int>.Create ((a, b) => a.CompareTo (b)));
// indices: { 3, 9 }
// get indices of all '4':
indices = test.GetIndices (t => t, Comparer<int>.Create ((a, b) => a == 4 ? 0 : -1));
// indices: { 2, 6, 10 }
// get indices of all except '4':
indices = test.GetIndices (t => t, Comparer<int>.Create ((a, b) => a != 4 ? 0 : -1));
// indices: { 0, 1, 3, 4, 5, 7, 8, 9 }
// get indices of all '15':
indices = test.GetIndices (t => t, Comparer<int>.Create ((a, b) => a == 15 ? 0 : -1));
// indices: { }
//########## test #2: named tuple array ##########
var datas = new (object anything, double score)[]
{
(999, 0.1),
(new object (), 0.42),
("hello", 0.3),
(new Exception (), 0.16),
("abcde", 0.42)
};
// get indices of highest score:
indices = datas.GetIndices (data => data.score, Comparer<double>.Create ((a, b) => a.CompareTo (b)));
// indices: { 1, 4 }
Enjoy! :-)
Finds the biggest and the smallest number in the array:
int[] arr = new int[] {35,28,20,89,63,45,12};
int big = 0;
int little = 0;
for (int i = 0; i < arr.Length; i++)
{
Console.WriteLine(arr[i]);
if (arr[i] > arr[0])
{
big = arr[i];
}
else
{
little = arr[i];
}
}
Console.WriteLine("most big number inside of array is " + big);
Console.WriteLine("most little number inside of array is " + little);

Categories

Resources