Output a reserve random list (list function) in C# - c#

I use List function in C# and make it random parameter. This is my code. If it output a list like this: 15 20 10 3 6
How can I output again with the reseve of list above like: 6 3 10 20 15
List<int> dso = new List<int>(20);
Random a = new Random();
for (int i = 0; i < dso.Capacity; i++)
{
int k = a.Next(100);
dso.Add(k);
Console.Write("{0} ", k);
}
for(int i=dso.Capacity;i<20;i--)
{
Console.Write("{0} ", dso[i]);
}

If you're just trying to reverse the list order then use Reverse() like this:
dso.Reverse();
foreach (var number in dso)
{
Console.Write(number + " ");
}
As you appear to be simply writing out the list in full once it's reversed you can use a foreach loop. If however you need more control of where you start in the list or jump around in the list then a for loop is better.

If you want for loop, it should be
for (int i = dso.Count - 1; i >= 0; i--) {
Console.Write("{0} ", dso[i]);
}
Comments:
Count is the number of actual list items; Capacity is reserved memory
List<T> is zero based that's why dso.Count - 1
since you loop in reversed order, condition is i >= 0
However, I suggest using String.Join and Linq instead of loop and let .Net do all the work for you:
// List has its own Reverse() method so we have to put Reverse<int>() to use Linq one
Console.Write(String.Join(" ", dso.Reverse<int>()));

Related

Split a list into n equal parts

Given a sorted list, and a variable n, I want to break up the list into n parts. With n = 3, I expect three lists, with the last one taking on the overflow.
I expect: 0,1,2,3,4,5, 6,7,8,9,10,11, 12,13,14,15,16,17
If the number of items in the list is not divisible by n, then just put the overflow (mod n) in the last list.
This doesn't work:
static class Program
{
static void Main(string[] args)
{
var input = new List<double>();
for (int k = 0; k < 18; ++k)
{
input.Add(k);
}
var result = input.Split(3);
foreach (var resul in result)
{
foreach (var res in resul)
{
Console.WriteLine(res);
}
}
}
}
static class LinqExtensions
{
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
{
int i = 0;
var splits = from item in list
group item by i++ % parts into part
select part.AsEnumerable();
return splits;
}
}
I think you would benefit from Linq's .Chunk() method.
If you first calculate how many parts will contain the equal item count, you can chunk list and yield return each chunk, before yield returning the remaining part of list (if list is not divisible by n).
As pointed out by Enigmativity, list should be materialized as an ICollection<T> to avoid possible multiple enumeration. The materialization can be obtained by trying to cast list to an ICollection<T>, and falling back to calling list.ToList() if that is unsuccessful.
A possible implementation of your extension method is hence:
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
{
var collection = list is ICollection<T> c
? c
: list.ToList();
var itemCount = collection.Count;
// return all items if source list is too short to split up
if (itemCount < parts)
{
yield return collection;
yield break;
}
var itemsInEachChunk = itemCount / parts;
var chunks = itemCount % parts == 0
? parts
: parts - 1;
var itemsToChunk = chunks * itemsInEachChunk;
foreach (var chunk in collection.Take(itemsToChunk).Chunk(itemsInEachChunk))
{
yield return chunk;
}
if (itemsToChunk < itemCount)
{
yield return collection.Skip(itemsToChunk);
}
}
Example fiddle here.
I see two issues with your code. First, the way you're outputting the results, it's impossible to tell the groupings of the values since you're just outputing each one on its own line.
This could be resolved buy using Console.Write for each value in a group, and then adding a Console.WriteLine() when the group is done. This way the values from each group are displayed on a separate line. We also might want to pad the values so they line up nicely by getting the length of the largest value and passing that to the PadRight method:
static void Main(string[] args)
{
var numItems = 18;
var splitBy = 3;
var input = Enumerable.Range(0, numItems).ToList();
var results = input.Split(splitBy);
// Get the length of the largest value to use for padding smaller values,
// so all the columns will line up when we display the results
var padValue = input.Max().ToString().Length + 1;
foreach (var group in results)
{
foreach (var item in group)
{
Console.Write($"{item}".PadRight(padValue));
}
Console.WriteLine();
}
Console.Write("\n\nDone. Press any key to exit...");
Console.ReadKey();
}
Now your results look pretty good, except we can see that the numbers are not grouped as we expect:
0 3 6 9 12 15
1 4 7 10 13 16
2 5 8 11 14 17
The reason for this is that we're grouping by the remainder of each item divided by the number of parts. So, the first group contains all numbers whose remainder after being divided by 3 is 0, the second is all items whose remainder is 1, etc.
To resolve this, we should instead divide the index of the item by the number of items in a row (the number of columns).
In other words, 18 items divided by 3 rows will result in 6 items per row. With integer division, all the indexes from 0 to 5 will have a remainder of 0 when divided by 6, all the indexes from 6 to 11 will have a remainder of 1 when divided by 6, and all the indexes from 12 to 17 will have a remainder of 2 when divided by 6.
However, we also have to be able to handle the overflow numbers. One way to do this is to check if the index is greater than or equal to rows * columns (i.e. it would end up on a new row instead of on the last row). If this is true, then we set it to the last row.
I'm not great at linq so there may be a better way to write this, but we can modify our extension method like so:
public static IEnumerable<IEnumerable<T>> Split<T>(
this IEnumerable<T> list, int parts)
{
int numItems = list.Count();
int columns = numItems / parts;
int overflow = numItems % parts;
int index = 0;
return from item in list
group item by
index++ >= (parts * columns) ? parts - 1 : (index - 1) / columns
into part
select part.AsEnumerable();
}
And now our results look better:
// For 18 items split into 3
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
// For 25 items split into 7
0 1 2
3 4 5
6 7 8
9 10 11
12 13 14
15 16 17
18 19 20 21 22 23 24
This should work.
So each list should (ideally) have x/n elements,
where x=> No. of elements in the list &
n=> No. of lists it has to be split into
If x isn't divisible by n, then each list should have x/n (rounded down to the nearest integer). Let that no. be 'y'. While the last list should have x - y*(n - 1). Let that no. be 'z'.
What the first for-loop does is it repeats the process of creating a list with the appropriate no. of elements n times.
The if-else block is there to see if the list getting created is the last one or not. If it's the last one, it has z items. If not, it has y items.
The nested for-loops add the list items into "sub-lists" (List) which will then be added to the main list (List<List>) that is to be returned.
This solution is (noticeably) different from your signature and the other solutions offered. I used this approach because the code is (arguably) easier to understand albeit longer. When I used to look for solutions, I used to apply solutions where I could understand exactly what was going on. I wasn't able to fully understand the other solutions to this question (yet to get a proper hang of programming) so I presented the one I wrote below in case you were to end up in the same predicament.
Let me know if I should make any changes.
static class Program
{
static void Main(string[] args)
{
var input = new List<String>();
for (int k = 0; k < 18; ++k)
{
input.Add(k.ToString());
}
var result = SplitList(input, 5);//I've used 5 but it can be any number
foreach (var resul in result)
{
foreach (var res in result)
{
Console.WriteLine(res);
}
}
}
public static List<List<string>> SplitList (List<string> origList, int n)
{//"n" is the number of parts you want to split your list into
int splitLength = origList.Count / n; //splitLength is no. of items in each list bar the last one. (In case of overflow)
List<List<string>> listCollection = new List<List<string>>();
for ( int i = 0; i < n; i++ )
{
List<string> tempStrList = new List<string>();
if ( i < n - 1 )
{
for ( int j = i * splitLength; j < (i + 1) * splitLength; j++ )
{
tempStrList.Add(origList[j]);
}
}
else
{
for ( int j = i * splitLength; j < origList.Count; j++ )
{
tempStrList.Add(origList[j]);
}
}
listCollection.Add(tempStrList);
}
return listCollection;
}
}

How to find repetitions/duplicates in the array within 10 elements apart

I have an array like following:
{1,5,5,4,5,6,7,8,9,10,11,12,13,14,1,16,17,5}
I want to find duplicates within each 10 elements from one to another.
I need a code that can tell me that 5 was duplicated 3 times within 10 elements (there are at most only 1 element between 5s (4). It should igore last 5 as it is too far away. Only three 5s are within 10 elements).
I don't want code to return 1, because there are 13 element in between both 1s.
I have a code that can count duplicates but how to change it so it can count duplicates withing 10 elements?
var dict = new Dictionary<string, int>();
foreach (var count in combined2)
{
if (dict.ContainsKey(count))
dict[count]++;
else
dict[count] = 1;
}
foreach (var val in dict)
{
MessageBox.Show(val.Key + " occurred " + val.Value + " times");
}
I'm only concerned with duplicates that occur the most. If some number get duplicated twice but another gets duplicated 3 times. I would only like to know about number that got duplicated 3 times (withing 10 items). Thank you
Make a dictionary max defaulting to 0
Make a dictionary seen defaulting to 0
Count count from 0 up to N, where N is number of elements.
after N >= 10, decrement seen[array[count - 10]]
Increment seen[array[count]]
If that number is higher than max[array[count]], update it
Repeat
Return the key of the highest value in max.
This way, seen always has the accurate count in the 10-element window, and max will have the maximum number of appearances of each element in a 10-element window.
This code finds the first item with the higher number of occurrences inside the "numbers" array (within n = 10 elements):
int n = 10;
int[] numbers = new int[] {1,5,5,4,5,6,7,8,9,10,11,12,13,14,1,16,17,5};
int mostDuplicatedNumber = 0, numberOfMaxOccurrences = 0;
for(int count = 0; count < numbers.Length - n; count++)
{
var groupOfNumbers = numbers.Skip(count).Take(n).GroupBy(i => i).OrderByDescending(i => i.Count());
if(numberOfMaxOccurrences < groupOfNumbers.First().Count())
{
numberOfMaxOccurrences = groupOfNumbers.First().Count();
mostDuplicatedNumber = groupOfNumbers.First().Key;
}
}
Console.WriteLine("Most duplicated number is " + mostDuplicatedNumber + " with " + numberOfMaxOccurrences + " occurrences");
Try out this way. I have not tested using IDE just wrote while travelling. Let me know if you encounter any error. What it does simply take first 10 elements and finds number of occurrence i.e. repetition but then ( you would like to display most repeated number in that case you have to hold those repeated numbers in another array and swap the elements to get most repeated and least repeated one as you asking in your question I have not implemented this part ) .
.................
int[] inputArray= {1,5,5,4,5,6,7,8,9,10,11,12,13,14,1,16,17,5} // total input elements
int[] mostAndLeastOccuranceArray=new int[10] ;
int skip=0;
int limit=10;
int[] resultArray=new int[10];
for (int i = skip; i < inputArray.Length; i++)
{
if(i<limit)
{
resultArray[i]=inputArray[i];
skip=skip+1;
}else
{
findOccurance(resultArray); // call in every 10 elements array subset
resultArray=new int[10]; // re-initialize the array
limit=limit+10; // increase the limit for next iteration remember loop has not finished yet
}
}
public void findOccurance(int[] resultArray)
{
var dict = new Dictionary < int,int > ();
foreach(var value in resultArray)
{
if (dict.ContainsKey(value)) dict[value]++;
else dict[value] = 1;
}
foreach(var pair in dict)
{
mostAndLeastOccuranceArray[pair.Key]=pair.Value; // store the repeated value
Console.WriteLine("Value {0} occurred {1} times", pair.Key, pair.Value);
}
// call the method to find most and least occurance elements within each array subsets
findMostAndLeastOccuranceElements(mostAndLeastOccuranceArray)
// re-initialize
mostAndLeastOccuranceArray=new int[10] ;
}
public void findMostAndLeastOccuranceElements(int[] mostAndLeastOccuranceArray)
{
// now find most and least repeated elements within each 10 elements block
}
A simpler solution would be to use LINQ. Here I wrote a simple method to count the number of time a value is repeated.
public int CountRepetitions(List<int> myLists,int maxValues,int number)
{
if (myLists.Count > maxValues)
return myLists.Take(maxValues).Count(v => v == number);
else return 0;
}

Creating 1000 arrays and sorting them using the bubble and selection sort (C#) [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 4 years ago.
Improve this question
I am new to programming. C# is my first programming language.
I have an assignment where I have to create and test out a bubble sort algorithm and a selection sort algorithm using arrays. I think I understand those now.
The next part of the assignment I am having some trouble on.
I have to write a program that will ask the user for a number (n) and create 1000 arrays of n size.
So if the user enters 5 for the number, my program has to create and sort 1000 arrays that are of length 5.
I have to use the bubble sort and the selection sort methods I created.
After I do that, I have to initiate a variable called running_time to 0. I have to create a for loop that iterates 1000 times and in the body of the loop i have to create an array of n random integers.
Then I have to get the time and set this to the start time. My professor said to notice that the sort is started after each array is built, so I should time the sort process only.
Then I have to get the time and set it to end time. I have to subtract the start time from end time and add the result to the total time.
Once the program has run, note
1. the number of items sorted
2. the average running time for each array (total time/1000)
Then I have to repeat the process using 500, 2500, and 5000 as the size of the array.
This is my code for creating one array with n number of spaces and filled with random integers.
//Asks the user for number
Console.WriteLine("Enter a number: ");
n = Convert.ToInt32(Console.ReadLine());
//Creates an array of the length of the user entered number
int[] randArray = new int[n];
//Brings in the random class so we can use it.
Random r = new Random();
Console.WriteLine("This is the array: ");
//For loop that will put in a random number for each spot in the array.
for (int i = 0; i < randArray.Length; i++) {
randArray[i] = r.Next(n);
Console.Write(randArray[i] + " ");
}
Console.WriteLine();
THIS IS MY CODE FOR THE BUBBLE SORT ALGORITHM:
//Now performing bubble sort algorithm:
for (int j = 0; j <= randArray.Length - 2; j++) {
for (int x = 0; x <= randArray.Length - 2; x++) {
if (randArray[x] > randArray[x + 1]) {
temp = randArray[x + 1];
randArray[x + 1] = randArray[x];
randArray[x] = temp;
}
}
}
//For each loop that will print out the sorted array
foreach (int array in randArray) {
Console.Write(array + " ");
}
Console.WriteLine();
THIS IS MY CODE FOR THE SELECTION SORT ALGORITHM:
//Now performing selection sort algorithm
for (int a = 0; a < randArray1.Length - 1; a++) {
minkey = a;
for (int b = a + 1; b < randArray1.Length; b++) {
if (randArray1[b] < randArray1[minkey]) {
minkey = b;
}
}
tempSS = randArray1[minkey];
randArray1[minkey] = randArray1[a];
randArray1[a] = tempSS;
}
//For loop that will print the array after it is sorted.
Console.WriteLine("This is the array after the selection sort algorithm.");
for (int c = 0; c < randArray1.Length; c++) {
Console.Write(randArray1[c] + " ");
}
Console.WriteLine();
This is very overwhelming as I am new to this and I am still learning this language.
Can someone guide me on the beginning on how to create 1000 different arrays filled with random numbers and then the rest. I would appreciate it greatly. Thank you.
So you have a several questions that has overwhelmed you.
Let's look at each one
Take user input
Console.WriteLine("Enter a length");
while (!int.TryParse(Console.ReadLine(), out var length))
Console.WriteLine("omg! you had one job");
Calling a method with an out argument
Starting with C# 7.0, you can declare the out variable in the argument
list of the method call, rather than in a separate variable
declaration. This produces more compact, readable code, and also
prevents you from inadvertently assigning a value to the variable
before the method call. The following example is like the previous
example, except that it defines the number variable in the call to the
Int32.TryParse method.
Fill Array
private static Random _rand = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
...
public static string RandomString(int length)
{
var result = Enumerable.Range(0, length)
.Select(s => chars[_rand.Next(length)])
.ToArray();
return new string(result);
}
Create array of random chars
var arr = Enumerable.Range(0, size)
.Select(i => RandomString(length)).ToArray();
How to time something
var sw = Stopwatch.StartNew();
// something to time
var milliseconds = sw.ElapsedMilliseconds
Now map it all together, I'll leave these details up to you
Additional Resources
Enumerable.Range(Int32, Int32) Method
Generates a sequence of integral numbers within a specified range.
Enumerable.Select Method
Projects each element of a sequence into a new form.
Stopwatch Class
Provides a set of methods and properties that you can use to
accurately measure elapsed time.
Random Class
Represents a pseudo-random number generator, which is a device that
produces a sequence of numbers that meet certain statistical
requirements for randomness.

Nesting loop to get one of each

I'm trying to make a look to print each of every value once:
Something like this.
Lets pretend that the object letters contains "one,two ...ten"
And then there is the object numbers that contains "1,2,3,4...10"
Now if I want the loop to print:
One
1
Two
2
Three
3
How would the loop look like?
I tried it like this:
foreach (var i in letters)
{
Console.WriteLine(i);
foreach(var a in numbers)
{
Console.WriteLine(a);
}
}
But this returns:
One
1
2
Two
1
2
Three
1
2
And that result isn't what I want..
How can I nest the loops to make it print the way I want it?
Maybe you can use IEnumerable<T>.Zip(...), see here, to make combinations.
var data = letters.Zip(numbers, (l, n) => new { letter = l, number = n})
foreach (var item in data) {
Console.Writeline(item.letter);
Console.Writeline(item.number);
}
use forloop insted of foreach use it like this
for (int i=0;i<letters.length;i++)
{
Console.WriteLine(letters[i]);
Console.WriteLine(numbers[i]);
}
Don't do two nested loops, they are for enumerating over all possible pairs from two collections.
Instead, make a loop on the index, and use it for both collections, or use LINQ's Zip method:
foreach (var pair in letters.Zip(numbers, (l, n) => new {Letter=l, Number=n})) {
Console.WriteLine("{0} - {1}", pair.Letter, pair.Number);
}
Assuming your Numbers and Letters are collections that derive from IEnumerable, you could do something like this:
var zipped = letters.Zip(numbers, Tuple.Create);
foreach (var tuple in zipped)
{
Console.WriteLine(tuple.Item1);
Console.WriteLine(tuple.Item2);
}
You need a single loop to iterate over both lists:
for (int index = 0; index < letters.Count; index++)
{
Console.WriteLine(letters[index]);
Console.WriteLine(numbers[index]);
}
This presupposes that your lists are the same length. If they're not you'd have to set the upper limit to the length of the shorter list.
for (int index = 0; index < Math.Min(letters.Count, numbers.Count); index++)
You're close - the second loop should not be within the first, but you should use one loop to iterate over both arrays. Try:
for (int i = 0; i < letters.size(); i++) {
Console.WriteLine(letters.getItem(i));
Console.WriteLine(numbers.getItem(i));
}
Note that this assumes a size() method to return the number of items and a getItem() method to return a specific item from the object.
What's happening is that for every time your outside loop runs, the inside one runs twice.
That's because your loops are nested, there's no getting around this.
If you absolutely must use nested loops for this, you'd have to add a check whether your number has been printed yet
Something like:
foreach(var i in letters)
{
Console.WriteLine(i);
foreach(var a in numbers)
{
if (a.isPrinted) //if it has been printed already
{
continue; //skip ahead
}
else
{
Console.WriteLine(a.number);
a.isPrinted = true;
break; //stop and jump out of the foreach loop
}
}
}
This also means that each number is actually an object that holds the bool isPrinted and int number
I wouldn't doing it like that, it's ridiculously inefficient.
You should do what others have already suggested.

How to retrieve values from Queue using for loop in C#?

class Program
{
static void Main(string[] args)
{
Queue ar = new Queue();
ar.Enqueue(45);
ar.Enqueue(23);
ar.Enqueue(2);
ar.Enqueue(87);
foreach (int x in ar)
{
Console.Write("{0} ", x);
}
Console.ReadLine();
}
}
I know how to retrieve values from a queue using foreach loop. but May I know it is possible to do same thing with the help of for loop ?
I tried following code. but ar[i] is not a valid code. what is the suitable code for ar[i] ?
for (int i = 0 ; i < ar.count ; i++) {
Console.Write("{0} ", ar[i]);
}
It doesn't make much sense to use a for-loop for a Queue since it's not a collection with an index(like IList<T>). So you cannot access items randomly (as with an array: ar[0]). You can use Queue<T>.Dequeue to get the first and remove it or use Queue<T>.Peek to return the first without removing it.
If you used a for-loop you would even get an expected behaviour:
for(int i = 0; i < ar.Count; i++)
Console.Write("{0} ", ar.Dequeue());
Does this display and show all 4 items? No, only the first two because Queue.Count decreases dynamically in the loop whereas the counter variable i increases, hence the loop stops at 2.
So a for-loop is simply the wrong type of loop for this collection. A while is more appropriate:
while(ar.Count > 0)
Console.Write("{0} ", ar.Dequeue());

Categories

Resources