I am making a lottery program, it's basic and only view-able via console at the moment.
The program executes the following:
User enters 6 numbers ranging from 1 - 46.
Program generates 6 random numbers with the same range.
Program compares indexes to see which numbers the user managed to match with the program.
Program displays the same numbers which the user got right.
But, currently, there is a bug in my code and I am not sure how to proceed.
For example, my inputs are: 1 , 2 , 3 , 4 , 5 , 6
The program generated 6 numbers and I've managed to hit number 2 and 6.
But, the program only displayed number 2.
This means that my code is not comparing each and every index, and I am not sure why.
The user array is lucky, and the program generated array is numbers.
Console.WriteLine("The winning numbers are: , " );
int[] winning = new int[6];
int w = 0;
var x = 0;
var j = 0;
Console.WriteLine("The winning numbers are: , " );
int[] winning = new int[6];
int w = 0;
var x = 0;
var j = 0;
while (x< 6)
{
if (lucky[j] == numbers[x])
{
winning[w] = numbers[x];
Console.WriteLine(winning[w]);
w++;
}
j++;
if (j == 5)
{
x++;
j = 0;
}
}
There is no need to do all that looping these days. LINQ's Intersect function makes it a single function call:
var Matches = lucky.Intersect(numbers);
will return all matching numbers from the two lists in Matches.
A looping equivalent might look like this (writing off the top of my head):
List<int> winning = new List<int>();
for(int i=0; i<numbers.Length; i++)
{
if(numbers.Contains(lucky[i])
winning.Add(lucky[i]);
}
To display it on console, use a simple loop:
for(int i=0; i<winning.Length; i++)
{
Console.WriteLine(winning[i]);
}
Since you run over an array, the standard procedure would be to use a for loop.
Here are three solutions that solve the problem.
Each one is complete and can be tested on https://dotnetfiddle.net/
Linq: Use the Intersects method to find the common items between two IEnumerables.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// at this point unique numbers have been generated and inputted
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int[] guesses = { 2, 6, 7, 8, 9, 10 };
List<int> matches = new List<int>(numbers.Intersect(guesses));
foreach (int n in matches)
{
Console.WriteLine("Hit: " + n.ToString());
}
}
}
Using a single for loop and checking with the Contains method (Array implements the IList interface) if the other array contains the number at the current index. You could also use a foreach loop, since you don't care about the indexes.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// at this point unique numbers have been generated and inputted
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int[] guesses = { 2, 6, 7, 8, 9, 10 };
List<int> matches = new List<int>();
for (int i = 0; i < guesses.Length; i++)
{
if (numbers.Contains(guesses[i]))
{
Console.WriteLine("Hit: " + guesses[i].ToString());
matches.Add(guesses[i]);
}
}
}
}
Of you could use a nested for loops, one for each array, to check each number from one array against every number of the other one.
Again you could use foreach loops.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// at this point unique numbers have been generated and inputted
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int[] guesses = { 2, 6, 7, 8, 9, 10 };
List<int> matches = new List<int>();
for (int i = 0; i < guesses.Length; i++)
{
for (int j = 0; j < numbers.Length; j++)
{
if (guesses[i] == numbers[j])
{
Console.WriteLine("Hit: " + guesses[i].ToString());
matches.Add(guesses[i]);
break; // optional, we found the number and can leave the loop. Not optional if your lottery allows numbers to happen more than once.
}
}
}
}
}
As for the question why your code isn't working:
You set j = 0 when j == 5 just after j++, meaning you set j to 0 after checking index 4. While I do not want to encourage such unorthodox styles you could fix it by comparing j == 6. Again, this approach makes your code unreadable, please use one of the other solutions.
using System;
public class Program
{
public static void Main()
{
// at this point unique numbers have been generated and inputted
int[] numbers = { 1, 2, 3, 4, 5, 6 };
int[] guesses = { 2, 6, 7, 8, 9, 10 };
int[] winning = new int[6];
int w = 0;
var x = 0;
var j = 0;
while (x < 6)
{
if (guesses[j] == numbers[x])
{
winning[w] = numbers[x];
Console.WriteLine(winning[w]);
w++;
}
j++;
if (j == 6)
{
x++;
j = 0;
}
}
}
}
I think what you are looking for is that finding common items from two arrays.
var ar1 = new int[] {1,2,3,4,5,6};
var ar2 = new int[] {2,3,4,6,7,8};
var common = ar1.Intersect(ar2);
In your case
var common = lucky.Intersect(numbers);
Using loops
// Array size is fixed here.
for (int i = 0; i < 6; i++) // OR i < lucky.Length (guessing numbers)
{
if (numbers.Contains(lucky[i]))
{
// NUMBERS DETECTED
}
}
The issue is with the checking of last index(5 in this case). It is never happening!
//say j = 4
lucky[4] == numbers[x] //false/true, whatever value of x is
You increment j
//j is now 5
if(j==5)
Yes and then you are resetting it to 0.
last index which is 5 in this case will never be checked in the next iteration
Solution-
if(j == 6)
I ended up building 2 methods that basically do what everyone here has told me.
Since I did not yet learn LinQ I couldn't understand , I didn't learn LIST as well so I couldn't use it as well.
My functions are like this:
First function: checks the indexes of a specified array
code:
static bool DoesExists(int[] a, int Value)
{
for (int i = 0; i < a.Length; i++)
{
if (Value == a[i])
{
return true;
}
}
return false;
}
second function checks how many repeated elements are in 2 arrays
code:
static int CountCorrect(int[] pc, int[] user)
{
int count = 0;
for (int i = 0; i < user.Length; i++)
{
if (DoesExists(pc, user[i]))
{
count++;
}
}
return count;
}
when using these 2 in conjunction , it solves my problem.
thanks to everyone for taking the time to give me good ideas.
//List Style
using System;
using System.Collections.Generic;
using System.Linq;
public class pr{
static public void Main (){
int n, i, j, k, l, sum,flag = 0;
//int sum = i+j;
//int k = (n-i);
//int l = (n-j);
//System.Console.WriteLine ("Enter a number");
//n = Convert.ToInt32 (Console.ReadLine());
//List <int> primes = new List <int>(); //list to handle the numbers
//HashSet <int> myPrimes = new HashSet <int> (primes);
System.Console.WriteLine ("Enter a number");
n = Convert.ToInt32 (Console.ReadLine());
//myPrimes.Add(n);
//myPrimes.Add(i);
//myPrimes.Add(j);
// var count = string.Join(", ", primes);
//System.Console.WriteLine("The value of n is {0}",myPrimes);
for(i=3; i<n/2; i++){
for(j=3; j<n/2; j++){
if(checkPrime(i) == 1){
if(checkPrime(j) == 1){
if (checkPrime(n-i) == 1){
if (checkPrime(n-j) == 1){
//if(i == j){
//sum = i+j;
System.Console.WriteLine("{0}={1}+{2}\n",n,i,n-i);
//}
}
}
}
}
if (flag == 0 && (n-i) <= 0 && (n-j) <= 0){ //check to avoid dupes
if (n <= 0 && i <= 0 && j <= 0){
Console.Write("{0}\n",n);
}
}
}
}
}
public static int checkPrime(int n){
int i, j, flag = 1;
for (i = 2; i<=(Math.Sqrt(n)); i++){
for (j = 2; j<=(Math.Sqrt(n)); j++){
if (n%i == 0 && n%j == 0 ){ //even number check
i++;
j++;
flag = 0;
}
}
}
return flag;
}
}
So I have been experimenting with this for a while now. I cant seem to print all possible solutions. For example for 24 I am able to print 7+17 but not 2+5+17. There are also some answers being repeated and this might have to do with the fact that I dont have duplicate checks. I tried to push the integers in a list and then use a hashset to only have distinct integers but I got stuck and tried to brute force it. All the numbers to be printed are supposed to be distinct prime integers. I dont understand how to print all distinct numbers and is there an elegant way to print out all the possible.
Thanks for the help!
Don't know if it's elegant enough for you, but I've just mashed a dirty way to make it work:
static void Main()
{
Console.WriteLine("Enter a number");
var numberToSum = Convert.ToInt32(Console.ReadLine());
var primesInRange = GetPrimesUpTo(numberToSum);
var foundSolutions = primesInRange.SubSetsOf().Where(prime => prime.Sum() == numberToSum);
foreach (var solution in foundSolutions.ToList())
{
var formatOperation = solution
.Select(x => x.ToString())
.Aggregate((a, n) => a + " + " + n) + " = " + numberToSum;
Console.WriteLine(formatOperation);
}
Console.ReadLine();
}
public static IEnumerable<int> GetPrimesUpTo(int end)
{
var primes = new HashSet<int>();
for (var i = 2; i <= end; i++)
{
var ok = true;
foreach (var prime in primes)
{
if (prime * prime > i)
break;
if (i % prime == 0)
{
ok = false;
break;
}
}
if (ok)
primes.Add(i);
}
return primes;
}
public static IEnumerable<IEnumerable<T>> SubSetsOf<T>(this IEnumerable<T> source)
{
if (!source.Any())
return Enumerable.Repeat(Enumerable.Empty<T>(), 1);
var element = source.Take(1);
var haveNots = SubSetsOf(source.Skip(1));
var haves = haveNots.Select(set => element.Concat(set));
return haves.Concat(haveNots);
}
I've found your solution quite dirty so I divided the problem to be more understandable. GetPrimesUpTo returns all prime number from 2 to the number you've provided in the input, SubSetsOf returns combination of numbers that summed up equals the input number you've provided and finally the foreach in Main produces formatted output that is easy on the eye. Hope it helps!
Providing that you have collection of primes and IsPrime method
private static int[] primes = new[] {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
private static bool IsPrime(int value) {
return primes.Contains(value);
}
You can implement recoursive solution
private List<List<int>> ToListOfPrimes(int value, List<int> parts = null) {
if (null == parts)
parts = new List<int>();
List<List<int>> result = new List<List<int>>();
if (value == 0) {
result.Add(parts.ToList());
return result;
}
int minPrime = parts.Count <= 0 ? 0 : parts[parts.Count - 1];
if (value <= minPrime)
return result;
// not that efficient: binary search will be a better choice here
for (int i = 0; i < primes.Length; ++i) {
int p = primes[i];
if (p <= minPrime)
continue;
else if (p > value)
break;
var list = parts.ToList();
list.Add(p);
var outcome = ToListOfPrimes(value - p, list);
foreach (var solution in outcome)
result.Add(solution);
}
return result;
}
Test
var result = ToListOfPrimes(28);
string report = String.Join(Environment.NewLine, result
.Select(line => String.Join(", ", line)));
Console.Write(report);
Outcome (28)
2, 3, 5, 7, 11
2, 3, 23
2, 7, 19
3, 5, 7, 13
5, 23
11, 17
For 24
2, 3, 19
2, 5, 17
5, 19
7, 17
11, 13
If you really want to implement it in other languages just throw your solution to rubbish bin. You should be more explicit about what is happening during execution. Nested for loops with multiple if statements are not explicit at all. What's even worse in the sample - you'll need to add new for loop every time you want more numbers in the sum. I do believe it's hard to understand it for a novice, but I find recursion the only way to go here.
See for yourself:
it's hard to say why output of your program is wrong, because of the logic
Variables should be named meaningfully so you know what they store instead of blind guessing.
Your checkPrime method returns int even though you return 0 or 1 so it should really return bool type
Use debugger and a piece of paper to understand how recursion works either in my previous answer or the one provided by Dmitry Bychenko
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 8 years ago.
Improve this question
I have a number 6 and now I need to search inside an array of ints if any of the numbers can be added together to get 6.
Example:
1,2,3,5,4
In the above array I can take 1+2+3 which makes 6.
I can also take 4+2 which is 6.
The question is how do I find those individual numbers that can sum up to the number 6.
One possible option is to get a list of all combinations of items in the array, then check which one of those has the sum of your target number.
I found an extension method for getting the combinations here (copied below).
public static IEnumerable<T[]> Combinations<T>(this IList<T> argList, int argSetSize)
{
if (argList == null) throw new ArgumentNullException("argList");
if (argSetSize <= 0) throw new ArgumentException("argSetSize Must be greater than 0", "argSetSize");
return combinationsImpl(argList, 0, argSetSize - 1);
}
private static IEnumerable<T[]> combinationsImpl<T>(IList<T> argList, int argStart, int argIteration, List<int> argIndicies = null)
{
argIndicies = argIndicies ?? new List<int>();
for (int i = argStart; i < argList.Count; i++)
{
argIndicies.Add(i);
if (argIteration > 0)
{
foreach (var array in combinationsImpl(argList, i + 1, argIteration - 1, argIndicies))
{
yield return array;
}
}
else
{
var array = new T[argIndicies.Count];
for (int j = 0; j < argIndicies.Count; j++)
{
array[j] = argList[argIndicies[j]];
}
yield return array;
}
argIndicies.RemoveAt(argIndicies.Count - 1);
}
}
Now you just need to call it with the number of combinations you want in your groups. For example, if you wanted to find groups of 2:
List<int> ints = new List<int>() { 1, 2, 3, 4, 5 };
int target = 6;
var combs2 = ints.Combinations(2)
.Where(x => x.Sum() == target);
This will return 1,5 and 2,4. You can then repeat this up to the maximum number of items you want in a group.
If you want to get all the results at once, make a new extension method that will do the unioning for you:
public static IEnumerable<T[]> AllCombinations<T>(this IList<T> argsList)
{
for (int i = 1; i <= argsList.Count; i++)
{
foreach (var combo in argsList.Combinations(i))
{
yield return combo;
}
}
}
Then you can get all your combinations at once by running
var allCombos = ints.AllCombinations()
.Where(x => x.Sum() == target);
So for your example, it will return 1,5, 2,4, and 1,2,3 in one collection.
If you want to know whether (and discover these numbers) two numbers sum to X it's an easy task and you can do it O(n) on average.
HashSet<int> numbers = new HashSet<int>(yourNumberArray);
foreach(int number in numbers)
if(numbers.Contains(x-number))
Console.WriteLine(number + " " + "numbers[x-number]");
However when you want to know if x1,x2,...,xk numbers sum to X it's NP-complete problem and no polynominal bounded solution is known (also it is not known does such solution exists). If number of items in your set is small (about ~20-30) you can brute-force your result by enumerating all subsets.
for (int i=1; i< (1 << setSize); ++i)
{
check does number in current set sum to X by bitwise operations on i
(treat number binary representation as information about set
(binary one means item is in set, zero means item is not in set)
}
You can also reduce this problem to knapsack problem and get pseudo-polynominal time, however maximum value in set shouldn't be big. For more information check: http://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/
You can find all combinations which results 6 using Lipski's algorithm like this:
static List<List<int>> FindCombinations(int x)
{
var combinations = new List<List<int>>();
var P = new int[10];
var R = new int[10];
combinations.Add(Enumerable.Repeat(1,x)); // first combination
P[1] = x;
R[1] = 1;
int d = 1, b, sum;
while (P[1] > 1)
{
sum = 0;
if (P[d] == 1)
{
sum = sum + R[d];
d = d - 1;
}
sum = sum + P[d];
R[d] = R[d] - 1;
b = P[d] - 1;
if (R[d] > 0) d++;
P[d] = b;
R[d] = sum/b;
b = sum%b;
if (b != 0)
{
d++;
P[d] = b;
R[d] = 1;
}
List<int> temp = new List<int>();
for (int i = 1; i <= d; i++)
temp = temp.Concat(Enumerable.Repeat(P[i], R[i])).ToList();
combinations.Add(temp);
}
return combinations;
}
Then all you need to is compare each sequence with your numbers:
var combinations = FindCombinations(6);
var numbers = new List<int> {1, 2, 3, 5, 4,6};
var result =
combinations.Where(x => x.Intersect(numbers).Count() == x.Count)
.Select(x => x.Intersect(numbers))
.ToList();
Here is the result in LINQPad:
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);