How do I manage multiple growing lists? - c#

The program starts by gathering the amount of allied/enemy minions in the game.
var eminions = MinionManager.GetMinions(Player.ServerPosition, 1500 MinionTypes.All, MinionTeam.Enemy).ToList();
var aminions = MinionManager.GetMinions(Player.ServerPosition, 1500, MinionTypes.All, MinionTeam.Ally).ToList();
Then i use a function that translates each object found in the lists into distances:
emd.Add(eminions[0].ServerPosition.Distance(aminions[i].ServerPosition)); //the count is 5
Our list 'emd' contains (aminions.Count) of distances which in our example = 5.
emd[0] = 500
emd[1] = 400
emd[2] = 300
emd[3] = 200
emd[5] = 100
Here's where it get's tricky, we want to find out where the smallest distance is located in the list. If we theorize we can see it's emd[5] = 100. But how do i get '5'?
Summary: The program must find the smallest number in the list, and then get the position in the list where it found it.
Here's what i tried: I tried comparing each number to see what's the smallest, if true, add to a new list, the problem im facing is that im creating too many lists and i am not prepared to handle varied amounts of minions.
var eminions = MinionManager.GetMinions(Player.ServerPosition, 1500, MinionTypes.All, MinionTeam.Enemy).ToList();
var aminions = MinionManager.GetMinions(Player.ServerPosition, 1500, MinionTypes.All, MinionTeam.Ally).ToList();
if (eminions.Count > 0 && aminions.Count > 0)
{
List<double> emd = new List<double>();
List<bool> bdistance = new List<bool>();
for (int i = 0; i < aminions.Count; i++)
{
emd.Add(eminions[0].ServerPosition.Distance(aminions[i].ServerPosition));
for (int j = 0; j < aminions.Count; j++)
{
if (emd[i] > emd[j])
{
bdistance.Add(true);
}
}
}
}

int pos = 0; // set index to zero
int min = emd[0]; // set minimum to first value
for (int i = 1; i < emd.Count; i ++)
{
var val = emd[i]; // get value from position
if (val < min) //check if value is smaller then current minimum
{
// set minimum to value
min = val;
// set minimum pos to current value pos
pos = i;
}
}
//found minimum
//minimum index == pos

You can find it easily!
var minIndex = emd.IndexOf(emd.Min());

This should work
int indexMin
= !emd.Any() ? -1 :
emd.Select( (value, index) => new { Value = value, Index = index } )
.Aggregate( (a, b) => (a.Value < b.Value) ? a : b )
.Index;
1.The !emd.Any() ? -1 : will force a -1 if the list is empty;
2.The Select will project each int element into an anonymous type with two properties: Value and Index;
3.The Aggregate will get the element with the minimum Value;
4.Finally, we get the Index of the chosen element.

Related

Write a program to find an index of Max item in an array

Write a console app in C# to find an index i in an array that is the maximum number in the array.
If the maximum element in the array occurs several times, you need to display the minimum index.
If the array is empty, output -1.
Please let me know what is wrong in my code?
If I input the array a = { 1, 2, 46, 14, 64, 64 };, for instance, it returns 0, while it should be returning 4.
public static void Main()
{
double[] a = { 1, 9, 9, 8, 9, 2, 2 };
Console.WriteLine(MaxIndex(a));
}
public static double MaxIndex(double[] array)
{
var max = double.MinValue;
int maxInd = 0, maxCount = 0;
int minIndex = 0;
var min = double.MaxValue;
for (var i = 0; i < array.Length; i++)
{
if (min > array[i])
{
min = array[i];
minIndex = i;
}
if (max == array[i])
maxCount++;
if (max < array[i])
{
maxCount = 1;
max = array[i];
maxInd = i;
}
}
if (array.Length == 0)
return -1;
if (maxCount > 1)
return minIndex;
return maxInd;
}
Your calculation is correct, but you return the wrong variable minIndex instead of maxIndex. Don't do more than necessary in a method. This calculates also the min-index and the count how often it appears, then it does nothing with the results. Here is a compact version:
public static int MaxIndex(double[] array)
{
var max = double.MinValue;
int maxInd = -1;
for (int i = 0; i < array.Length; i++)
{
if (max < array[i])
{
max = array[i];
maxInd = i;
}
}
return maxInd;
}
It also sets maxInd = -1 which was part of your requirement. Since MatthewWatson had an objection regarding repeating double.MinValue in the array, here is an optimized version:
public static int MaxIndex(double[] array)
{
if(array.Length == 0)
return -1;
else if (array.Length == 1)
return 0;
double max = array[0];
int maxInd = 0;
for (int i = 1; i < array.Length; i++)
{
if (max < array[i])
{
max = array[i];
maxInd = i;
}
}
return maxInd;
}
If code-readability/maintainability is more important and you don't care of few milliseconds more or less, you could use LINQ (a version that enumerates only once):
int minIndexOfMaxVal = a.Select((num, index) => new {num, index})
.OrderByDescending(x => x.num)
.Select(x => x.index)
.DefaultIfEmpty(-1)
.First();
This works with every kind of sequence and types not only with arrays and doubles.
Try this simple line of code:
int[] numbers = { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
var index = numbers.ToList().IndexOf(numbers.Max());
I think code is simple enough to be self-explanatory.
However, if you aim for performance, conversion to List could be omitted and you could wirte own code to find index of maximum number.
Or even simplier, proposed by #fubo:
Array.IndexOf(numbers, numbers.Max());
A lot of simplification is possible in this code:
int? maxVal = null; // null because of array of negative value;
int index = -1;
for (int i = 0; i < array.Length; i++)
{
int current = array[i];
if (!maxVal.HasValue || current > maxVal.Value)
{
maxVal = current ;
index = i;
}
}
Will get you the first index of the max value. If you just need a short code and Don't mind iterating twice a simple linq can do the trick
var index = array.ToList().IndexOf(array.Max());
It returns zero, because minIndex is indeed zero:
Change minIndex to maxIndex:
if (maxCount > 1) return maxIndex;
In order to compare doubles use the following code instead of ==:
if (Math.Abs(a-b)<double.Epsilon)
Your code in general is way too complicated with way too many variables for what it has to do.
You want the index of the first occurence of the highest value, so there isn't any real reason to store anything but a MaxValueIndex and a MaxValue.
All other variables should be local so garbage collection can dispose of them.
As for what is actually wrong with your code, I can't help out, since the variable names are confusing to me.
But here is some code that achieves the goal you want to achieve.
double[] a = { 1, 9, 9, 8, 9, 2, 2 };
var highestValueInArray = a.Max();
var arrayLength = a.Length;
for (int i = 0; i < arrayLength; i++)
{
if (a[i] == highestValueInArray)
{
Console.WriteLine(i);
break;
}
}
instead of manually calculating the max value, you can just use YourArray.Max() to get the highest value.
then just iterate through it like normal, but at the first occurence, you break; out of the loop and return the index it is at.
I'm pretty sure there's also a way to use FirstOrDefault in combination with IndexOf, but couldn't get that to work myself.

get the final result after looping through a list of data

I have a set of data in an array. Where the first value will denote the number of records and second number will denote the number of data in one record accordingly. Data will loop and calculate until the number of records equals to 0.
3 -> set 1 - no of records 3
2 -> record 1 contain two data values
10.00 -> data1
20.00 -> data2
4 -> record 2 contain four data values
15.00
15.01
3.00
3.01
3
5.00
9.00
4.00
2 -> set 2 - no of records 2
2
8.00
6.00
2
9.20
6.75
0
I need to calculate the sum of one set of records and need to divide it from the no of records and then need to minimise that value from each of the record to get the value (which gets after reduction of summation/no of records)
output
(1st set of records)
1.99
8.01
10.01
(2nd set of records)
0.98 -> ((8.00+6.00) + (9.20+6.75))/2 - (8.00+6.00)
0.98
This is the code I came up with but the results I am getting are different and could not find where it got wrong.
my output
171.38 <- 1st set of records
135.36
117.36
118.57 <- 2nd set of records
102.62
// (inputLines is the name of the array with data)
int data = 0;
float temp = 0;
List<string> tempOutputFileList = new List<string>();
while (inputLines[data] != "0")
{
var listOfPeople = new List<float>();
int people = int.Parse(inputLines[data]);
for (int n = 0; n < people; n++)
{
data = data + 1;
int receipts = int.Parse(inputLines[data]);
for (int p = 0; p < receipts; p++)
{
data = data + 1;
temp += float.Parse(inputLines[data]);
listOfPeople.Add(temp);
if (listOfPeople[n].ToString() != null)
{
listOfPeople[n] = temp;
}
}
}
float sum = 0;
string tempValue = null;
double receiptValue = 0;
foreach (float item in listOfPeople)
{
sum += item;
}
for (int v = 0; v < people; v++)
{
receiptValue = (sum / people - listOfPeople[v]);
}
data++;
tempOutputFileList.Add(" ");
listOfPeople.Clear();
}
foreach (string val in tempOutputFileList)
{
Console.WriteLine(val);
}
You need to compute average after summing a whole set of records. However, on the other hand you can also simplify the way to compute the average if you only store the sums per people. See the following code that produces the results you expected (however some with different sign):
int data = 0;
List<string> tempOutputFileList = new List<string>();
while (inputLines[data] != "0")
{
var listOfPeople = new List<float>();
int people = int.Parse(inputLines[data++]);
for (int n = 0; n < people; n++)
{
int receipts = int.Parse(inputLines[data++]);
float tempPeople = 0;
for (int p = 0; p < receipts; p++)
{
tempPeople += float.Parse(inputLines[data++]);
}
listOfPeople.Add(tempPeople);
}
foreach (float item in listOfPeople)
{
Console.WriteLine(listOfPeople.Average() - item);
}
}
Console.ReadLine();

find number with no pair in array

I am having trouble with a small bit of code, which in a random size array, with random number pairs, except one which has no pair.
I need to find that number which has no pair.
arLength is the length of the array.
but i am having trouble actually matching the pairs, and finding the one which has no pair..
for (int i = 0; i <= arLength; i++)
{ // go through the array one by one..
var number = nArray[i];
// now search through the array for a match.
for (int e = 0; e <= arLength; e++)
{
if (e != i)
{
}
}
}
I have also tried this :
var findValue = nArray.Distinct();
I have searched around, but so far, i haven't been able to find a method for this.
This code is what generates the array, but this question isn't about this part of the code, only for clarity.
Random num = new Random();
int check = CheckIfOdd(num.Next(1, 1000000));
int counter = 1;
while (check <= 0)
{
if (check % 2 == 0)
{
check = CheckIfOdd(num.Next(1, 1000000)); ;
}
counter++;
}
int[] nArray = new int[check];
int arLength = 0;
//generate arrays with pairs of numbers, and one number which does not pair.
for (int i = 0; i < check; i++)
{
arLength = nArray.Length;
if (arLength == i + 1)
{
nArray[i] = i + 1;
}
else
{
nArray[i] = i;
nArray[i + 1] = i;
}
i++;
}
You can do it using the bitwise operator ^, and the complexity is O(n).
Theory
operator ^ aka xor has the following table:
So suppose you have only one number without pair, all the pairs will get simplified because they are the same.
var element = nArray[0];
for(int i = 1; i < arLength; i++)
{
element = element ^ nArray[i];
}
at the end, the variable element will be that number without pair.
Distict will give you back the array with distinct values. it will not find the value you need.
You can GroupBy and choose the values with Count modulo 2 equals 1.
var noPairs = nArray.GroupBy(i => i)
.Where(g => g.Count() % 2 == 1)
.Select(g=> g.Key);
You can use a dictionary to store the number of occurrences of each value in the array. To find the value without pairs, look for a (single) number of occurrences smaller than 2.
using System.Linq;
int[] data = new[] {1, 2, 3, 4, 5, 3, 2, 4, 1};
// key is the number, value is its count
var numberCounts = new Dictionary<int, int>();
foreach (var number in data) {
if (numberCounts.ContainsKey(number)) {
numberCounts[number]++;
}
else {
numberCounts.Add(number, 1);
}
}
var noPair = numberCounts.Single(kvp => kvp.Value < 2);
Console.WriteLine(noPair.Key);
Time complexity is O(n) because you traverse the array only a single time and then traverse the dictionary a single time. The same dictionary can also be used to find triplets etc.
.NET Fiddle
An easy and fast way to do this is with a Frequency Table. Keep a dictionary with as key your number and as value the number of times you found it. This way you only have to run through your array once.
Your example should work too with some changes. It will be a lot slower if you have a big array.
for (int i = 0; i <= arLength; i++)
{
bool hasMatch = false;
for (int e = 0; e <= arLength; e++)
{
if (nArray[e] == nArray[i])//Compare the element, not the index.
{
hasMatch = true;
}
}
//if hasMatch == false, you found your item.
}
All you have to do is to Xor all the numbers:
int result = nArray.Aggregate((s, a) => s ^ a);
all items which has pair will cancel out: a ^ a == 0 and you'll have the distinc item: 0 ^ 0 ^ ...^ 0 ^ distinct ^ 0 ^ ... ^0 == distinct
Because you mentioned you like short and simple in a comment, how about getting rid of most of your other code as well?
var total = new Random().Next(500000) * 2 + 1;
var myArray = new int[total];
for (var i = 1; i < total; i+=2)
{
myArray[i] = i;
myArray[i -1] = i;
}
myArray[total - 1] = total;
Then indeed use Linq to get what you are looking for. Here is a slight variation, returning the key of the item in your array:
var key = myArray.GroupBy(t => t).FirstOrDefault(g=>g.Count()==1)?.Key;

How To Add Two List<> at run time ? Index out of range error My code Attached (ASP.net C#)

I am trying to add two lists in a loop by adding first index value of one list to the first index value of another list but both list are populating at run time after calculation issue is that how to track that list<> posses value at that index or not as shown below ,
Result[var]=first[var]+second[var]
complete code is give below,
List<double> Result = new List<double>();
for (int var = 0; var < 30; var++)
{
if (first[var] == null)
{
first[var] = 0;
}
if (second[var] == null)
{
second[var] = 0;
}
}
Result[var]=first[var]+second[var];
}
we do are not sure that both list may have value up to 10,15 .. index but i need if list one have 15 values and list two have 10 values then add two list in this way ,
A list[0]+B list[0]=
A list[1]+B list[1]=
A list[2]+B list[2]=
if it add
A list[11]+B list[11]=
then it add 0 from second list because it has only 10 values then how to validate b list[11] and use 0 if index 11 not exist in second list
one more thing list can have upto 30 values maximum not more then 30
You may need something like this (assuming that first and second are List):
List<double> Result = new List<double>();
for (int i = 0; i < 30; i++)
{
double firstVal = 0;
double secondVal = 0;
if (first.Count > i)
{
firstVal = first[i];
}
if (second.Count > i)
{
secondVal = second[i];
}
Result.Add(firstVal + secondVal);
}
If I understood correctly, you are trying to add two list values into another list. If one of the list is ended, consider the value as zero and continue till max available limit of either of the lists.
If so,
// assume i1, i2 are sources and i3 is result
int max = i1.Count>i2.Count?i1.Count:i2.Count;
for (int i = 0; i < max; i++)
{
i3[i] = (i1.Count > i ? i1[i] : 0) + (i2.Count > i ? i2[i] : 0);
}
// another varient:
for (int i = 0; i < i1.Count; i++)
{
i3[i] = i1[i] + (i2.Count > i ? i2[i] : 0);
}
for (int i = i1.Count; i < i2.Count; i++)
{
i3[i] = i2[i];
}

1-Dimensional Array Counting Same Elements

I have a 1-dimensional array that fills up a table of 40 random elements (all the values are either 0 or 1). I want to find the longest consecutive span of values.
For example:
In 111100101 the longest row would be 1111 because it has four consecutive values of 1.
In 011100 the result is 111.
I have no idea how to check upon the "next element" and check if it's a 0 or 1.
Like the first would be 1111 (count 4) but the next would be a 0 value, meaning I have to stop counting.
My idea was placing this value (4) in a other array (example: 111100101), and place the value of the 1's back on zero. And start the process all over again.
To find the largest value I have made another method that checks up the biggest value in the array that keeps track of the count of 0's 1's, this is not the problem.
But I cannot find a way to fill the array tabelLdr up, having all the values of the group of elements of the same kind (being 0 or 1).
In the code below I have 2 if's and of course it will never go into the second if (to check if the next value in the array is != to its current state (being 0 or 1).
public void BerekenDeelrij(byte[] tabel, byte[] tabelLdr)
{
byte LdrNul = 0, Ldréén = 0;
//byte teller = 0;
for (byte i = 0; i < tabel.Length; i++)
{
if (tabel[i] == 0)
{
LdrNul++;
//this 2nd if cleary does not work, but i have no idea how to implend this sort of idea in my program.
if (tabel[i] == 1) //if value != 0 then the total value gets put in the second array tabelLdr,
{
tabelLdr[i] = LdrNul;
LdrNul = 0
}
}
if (tabel[i] == 1)
{
Ldréén++;
if (tabel[i] == 0)
{
tabelLdr[i] = Ldréén;
Ldréén = 0;
}
}
}/*for*/
}
This method should do what you need:
public int LargestSequence(byte[] array) {
byte? last = null;
int count = 0;
int largest = 0;
foreach (byte b in array) {
if (last == b)
++count;
else {
largest = Math.Max(largest, count);
last = b;
count = 1;
}
}
return Math.Max(largest, count);
}
Even while i is the loop counter, it is still just a variable. A valid for statement is for (;;), which is an infinite loop. Notice the for statement increments i, as in i++. The expression i = i + 1 works just as well.
Im unsure if you need the longest "row" of ones or longest row of either 0 or 1. This will work for the latter
var max = 0;
var start = 0;
var current = -1;
var count = 0;
for(int i = 0;i<table.Length;i++)
{
if(current = table[i])
{
count++;
}
else
{
current = table[i];
if(max < count)
{
max = count;
start = i-count;
}
count = 1;
}
}
if(max < count)
{
max = count;
start = i-count;
}
//max is the length of the row starting at start;

Categories

Resources