Delete a percent of list elements - c#

Let's say I have a list of numbers like
1 2 3 4 5 6 7 8 9 10
Now I want to delete 50% of the list so i would have now a list like
1 3 5 7 9
I don't want to remove the first 50% , so not this
6 7 8 9 10
I want to regularly delete from the list.
I'm trying to implement this in C# or JAVA.
I know that sometime is not possible to remove that percent exactly but something close will be ok.
My procent is always an integer, so is from 0 to 100 .
I'm trying to do this with an N percent for a list, how should I start?

You can use Linq:
List<int> source = new List<int>() {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// Take every other item from the list
List<int> result = source
.Where((item, index) => index % 2 == 0)
.ToList();
General case should be elaborated a little bit:
int percent = 50;
List<int> result = source
.Where((item, index) =>
(index == 0) ||
(index * percent / 100) > ((index - 1) * percent / 100))
.ToList();

int halfNumOfList = myList.Count / 2;
int itemsRemoved = 0;
for (int i = 0; i < myList.Count; i++)
{
if (itemsRemoved < halfNumOfList)
{
if (i % 2 != 0)
{
myList.Remove(myList[i]);
itemsRemoved++;
}
}
}

Related

Sum of selected values in an int Array in c#

I'm learning how to program using c#. I'm really new to this.
My question is I'm trying to create an array that shows 10 numbers. I want my code to check which numbers below 10 are divisible for 3 or 5 and sum the total.
I've tried to use the .Sum() function but says int doesn't contain a definition for Sum. I've put using System.Linq on my program.
Does anyone have an idea how to make this sum happens?
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int sum = 1 + 2;
foreach (int n in numbers)
{
if (n % 3 == 0 || n % 5 == 0)
{
int total = n.Sum();
Console.WriteLine(total);
}
else
{
Console.WriteLine("not divisible");
}
}`
So your problem is that you are trying to call .Sum() on a variable n which is of type int (you define it here: foreach (int n in numbers), and that is not a method.
Using LINQ you could do something like:
var numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var total = numbers.Where(n => n % 3 == 0 || n % 5 == 0).Sum();
If I understand it correct and using your code this is what you want.
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int sum = 1 + 2;
int total=0;
foreach (int n in numbers)
{
if (n % 3 == 0 || n % 5 == 0)
{
int total += n;
}
else
{
Console.WriteLine("not divisible");
}
}
Console.WriteLine(total);
I moved the printing out to after the foreach so you get one result when it is done
Everybody forgot that array should contain 10 numbers but some numbers values maybe greater than 10. Only number values below 10 should be checked. So a right answer should be
var numbers = new int[] { 1, 9, 5, 6, 8, 10,4, 15, 25, 3};
var total = numbers.Where( n => (n<10) && ( n % 3 == 0 || n % 5 == 0)).Sum();

C# - fair team allocation with ratings

I have a list of rankings for players in a sport and would like to assign them to teams so that the distribution of ratings is as fair as possible (i.e. eliminating teams with lots of high rated players and vice versa).
Currently I am doing this but it doesn't seem to give the optimal solution:
ratingList.Sort();
ratingList.Reverse();
var team1List = ratingList.Where((r, i) => i % 2 != 0).ToList();
var team2List = ratingList.Where((r, i) => i % 2 == 0).ToList();
After sorting them in descending order try this
var team1List = ratingList.Where((r, i) => i % 2 != 0).ToList();
var team2List = ratingList.Where((r, i) => i % 2 == 0).ToList();
For the optimal solution, the idea is to consider the ratingList twice side by side
ascending vs descending and take the first half (the other one is just mirrored)
Ex:
0, 1, 2, 3, 4 | 5, 6, 7, 8, 9
9, 8, 7, 6, 5 | 4, 3, 2, 1, 0
and keep the first half
team1 team2 team1 team2 |
0, 1, 2, 3, | 4 team1
9, 8, 7, 6, | 5 team2
The evens go in team1 and the odds in team2. If we have an even number of pairs, the last pair will be redistributed between the two teams (also please note that this works only for ratingList >= 4 (it's up to you to handle for less). Also for even number of ratings I propose to exclude the middle rating and decide later what to do with it.
Considering all the above, the solution should look like this
ratingList.Sort();
var count = ratingList.Count();
// if even number of players, keep aside the one in the middle (as rating)
int? middle = null;
if (count % 2 != 0)
{
middle = ratingList[count / 2];
ratingList.RemoveAt(count / 2);
}
var ratingListDesc = ratingList.OrderByDescending(i => i).ToList();
var half = count / 2;
var take = half % 2 != 0 ? half - 1 : half;
var team1List = ratingList.Take(take).Where((r, i) => i % 2 == 0).ToList();
team1List.AddRange(ratingListDesc.Take(take).Where((r, i) => i % 2 == 0));
var team2List = ratingList.Take(take).Where((r, i) => i % 2 != 0).ToList();
team2List.AddRange(ratingListDesc.Take(take).Where((r, i) => i % 2 != 0));
// we just have to redistribute the remaining pair between each team
if (half % 2 != 0)
{
team1List.Add(ratingList[half - 1]);
team2List.Add(ratingListDesc[half - 1]);
}
if (middle.HasValue)
{
// do something, or not ...
}

How to find all instances of mirrored duplicates?

I have been searching for some time now for any answers on how to do this.
What I am trying to do is, take an array of numbers, e.g. {1, 3, 5, 6, 8, 7, 6 ,5, 3, 1} (but it will use user input) and find the duplicates of these numbers that are mirrored and return how many indexes are involved in just one instance of said array.
I know the basics of C# but can't grasp this task. No, this is not homework. This is my own project to further my knowledge.
I am not currently around the code I have for parts of this, but would really appreciate any help/advice anyone could give me.
int[] array = {1, 3, 5, 6, 8, 7, 6 ,5, 3, 1};
//holds left index of mirrored pair, you can easily find the right one
var mirroredIndexes = new List<int>();
var length = array.Length;
for (int i = 0; i < length / 2; i++)
{
if(array[i] == array[length - i - 1])
mirroredIndexes.Add(i);
}
mirroredIndexes.ForEach(Console.WriteLine);
Console.WriteLine ("total of {0} mirrored pairs ({1})",
mirroredIndexes.Count,
string.Join(", ", mirroredIndexes.Select(i => array[i])));
prints next indexes:
0
1
2
3
total of 4 mirrored pairs (1, 3, 5, 6)
I think this is what you are after. This will return a list of matching indices.
Eg. first == last, second == second to last, third == third to last
var matches = new List<Tuple<int, int>>();
var array = new [] { 0, 1, 2, 3, 4, 5, 3, 2, 1, 0 };
if (array.Length % 2 != 0)
throw new Exception("Array must have an even amount of elements");
for (int i = 0; i < array.Length / 2; i++)
{
if (array[i] == array[array.Length - 1 - i])
{
matches.Add(new Tuple<int, int>(i, array.Length - 1 - i));
}
}
var firstMatchingIndex1 = matches[0].Item1;
// This will be 0
var firstMatchingIndex2 = matches[0].Item2;
// This will be 9
You could go further, using a custom class, and capture the actual value that matched (eg. index1 is 1, index2 is 8 and the value was 1.

reorder List starting at given position

List:
List<int> list1 = new List<int>(){ 0, 1, 2, 3, 4, 5, 6 };
let's say we want to reorder it. The beginning should be at number "2"
// 2,3,4,5,6,0,1
or at number 5
// 5,6,0,1,2,3,4
how do you do it with C#?
the reason: Imagine that you have an index of a given number in the List (number 3, index 3). You want to get the second number from the right - it'll be 5.
Unfortunately, if the starting number is at the end of the List (numbers 5 and 6) - out of range exception will be thrown, because there's no 7 and 8!
The idea is to reorder the List!
We enter Nr. 5 - we get 0 (5,6,0).
We enter Nr. 6 - we get 1 (6,0,1), etc.
or maybe there is some other (read - better) way to solve this problem?
The better way to do it is to use the mod operator %. This gives you the remainder when you divide an int by another int. The way this works is something like this:
int nextIndex = (currentIndex + offset) % length;
So, if your current index is 5, your offset is 2 and your length is 6 then:
5 + 2 = 7
7 / 6 = 1 remainder 1 (or 7 mod 6 = 1)
therefore nextIndex = 1
A little Linq can do this pretty easily:
List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 });
var numToStart = 4;
//reorderedList will be {4,5,6,0,1,2,3}
var reorderedList = list1.Skip(numToStart).Concat(list1.Take(numToStart));
You don't need to reorder the list. You could get the number with the following function:
int GetNumber(List<int> list, int fromValue, int index)
{
return list[(list.IndexOf(fromValue) + index) % list.Count()];
}
You could call the function like this:
List<int> list1 = new List<int>(new[] { 0, 1, 2, 3, 4, 5, 6 });
int number = GetNumber(list1, 5, 2); // number = 0

How to get alternate numbers using Enumerable.Range?

If Start=0 and Count=10 then how to get the alternate values using Enumerable.Range()
the out put should be like { 0, 2, 4, 6, 8 }
and if Start=1 and Count=10 then { 1, 3, 5, 7, 9 }
The continuous value can be get like
var a = Enumerable.Range(0,10).ToList();
but how to get the alternate values?
Halving the number of items that Range should generate (its second parameter) and then doubling the resulting values will give both the correct number of items and ensure an increment of 2.
Enumerable.Range(0,5).Select(x => x * 2)
Enumerable.Range(0, 10).Where(i => i % 2 == 0); // { 0, 2, 4, 6, 8 }
Enumerable.Range(0, 10).Where(i => i % 2 != 0); // { 1, 3, 5, 7, 9 }
The count parameter in your code looks like an end point of the loop.
public static MyExt
{
public static IEnumerable<int> Range(int start, int end, Func<int, int> step)
{
//check parameters
while (start <= end)
{
yield return start;
start = step(start);
}
}
}
Usage: MyExt.Range(1, 10, x => x + 2) returns numbers between 1 to 10 with step 2
MyExt.Range(2, 1000, x => x * 2) returns numbers between 2 to 1000 with multiply 2 each time.
What you are after here does not exist in the BCL as far as I'm aware of, so you have to create your own static class like this to achieve the required functionality:
public static class MyEnumerable {
public static IEnumerable<int> AlternateRange(int start, int count) {
for (int i = start; i < start + count; i += 2) {
yield return i;
}
}
}
Then you can use it like this wherever you want to:
foreach (int i in MyEnumerable.AlternateRange(0, 10)) {
//your logic here
}
You can then also perform LINQ queries using this since it returns IEnumerable
So if you want you can also write the above like this if you want to exclude the number 6
foreach (int i in MyEnumerable.AlternateRange(0, 10).Where( j => j != 6)) {
//your logic here
}
I hope this is what you are after.
You can't have this as an extension method on the Enumerable class directly since that is a static class, and extension methods work on an object of a class, and not the class itself. That's why you have to create a new static class to hold this method if you want to mimic the Enumerable class.
This can be done more simply using Linq and by specifying the minimum, length, and step values:
Enumerable.Range(min, length).Where(i => (i - min) % step == 0);
Usage with 0 through 10 at a step size of 2:
var result = Enumerable.Range(0, 10).Where(i => (i - 10) % 2 == 0);
Output:
0, 2, 4, 6, 8
Usage with 1 through 10 at a step size of 2:
var result = Enumerable.Range(1, 10).Where(i => (i - 10) % 2 == 0);
Output:
1, 3, 5, 7, 9
You could go further and make a simple function to output it using a minimum, maximum, and step value:
public static IEnumerable<int> RangedEnumeration(int min, int max, int step)
{
return Enumerable.Range(min, max - min + 1).Where(i => (i - min) % step == 0);
}
The reason to set the range length to max - min + 1 is to ensure the max value is inclusive. If the max should be exclusive, remove the + 1.
Usage:
var Result = RangedEnumeration(0, 10, 2); // 0, 2, 4, 6, 8, 10
var Result = RangedEnumeration(1, 10, 2); // 1, 3, 5, 7, 9
var Result = RangedEnumeration(1000, 1500, 150); // 1000, 1150, 1300, 1450

Categories

Resources