How to display all members of a given subsequence on the console? - c#

I'm trying to understand why I can't print only the members of a subsequence of an array, that is equal to an integer from the input. The array is also read from the console. When i run the program only the first of these members does come up, but with him also a seemingly random number of zeros, while the rest of the subsequence is omitted. If there's a better way than to use a second array, I'll be grateful if you share it. Okay, to specify- I want to know how to print all the members of the aforementioned subsequence, can you please give me a useful advice or sample? Here's the input, output and code:
4 4 56 57 58
8
4 0 0 0 0
instead of 4 4
int v = int.Parse(Console.ReadLine());
int[] valueHolder = new int[arr1.Length];
int currentSum = 0;
for (int endIndex = 0; endIndex <= arr1.Length -1; endIndex++)
{
currentSum = 0;
for (int currentSumIndex = endIndex; currentSumIndex >= 0; currentSumIndex--)
{
currentSum += arr1[currentSumIndex];
if (currentSum == v)
{
valueHolder[currentSumIndex] = arr1[currentSumIndex];
}
if (currentSum == v)
{
for (int i = 0; i <= valueHolder.Length - 1; i++)
{
Console.Write(valueHolder[i] + " ");
}
}
}

I think you would be best served by putting a break point on the line of the first for loop then stepping through your code. If you take a pad of paper and write each of the variables states as you go through it then it will be pretty obvious what's going on.
However, just to help you out.
In the first pass of the outer loop (endIndex = 0), the inner loop does NOT execute. currentSumIndex = endIndex which equals zero, which does not pass the currentSumIndex >= 0 test. Therefore the first 4 is skipped.
In the second pass, the number 4 is emitted because currentSum equals 4. However, the values of 0 are also emitted because you are walking the entire valueHolder array and spitting all of the empty values out.
From the third pass forward, currentSum will never equal the number you typed in:
The first pass of the inner loop sets currentSum to 56, which does not equal v. The second pass of the inner loops sets it to 56+4 ( currentSum += arr1[currentSumIndex] ) which is 60. Therefore, nothing will ever be emitted again as currentSum will always be the sum of all numbers from the current array position going backward to the beginning array position and therefore will always be greater than v
You don't need a second array. You just need to pay attention to what your code is doing. Side note: I have absolutely no idea why you have that inner loop or even what the 8 is supposed to represent in your example entry above.
If I was writing this, I'd change it to (assuming you can't use LINQ):
int v = int.Parse(Console.ReadLine());
for (int i= 0; i <= arr1.Length -1; i++)
{
if (arr1[i] == v) {
Console.Write(arr1[i].ToString() + " ");
}
}
Console.WriteLine();

Related

What sorting method is this being applied and what is the algorithmic complexity of the method

I came across the code below for implementing sorting array.
I have applied to a very long array and it was able to do so in under a sec may be 20 millisec or less.
I have been reading about Algorithm complexity and the Big O notation and would like to know:
Which is the sorting method (of the existing ones) that is implemented in this code.
What is the complexity of the algorithm used here.
If you were to improve the algorithm/ code below what would you alter.
using System;
using System.Text;
//This program sorts an array
public class SortArray
{
static void Main(String []args)
{
// declaring and initializing the array
//int[] arr = new int[] {3,1,4,5,7,2,6,1, 9,11, 7, 2,5,8,4};
int[] arr = new int[] {489,491,493,495,497,529,531,533,535,369,507,509,511,513,515,203,205,207,209,211,213,107,109,111,113,115,117,11913,415,417,419,421,423,425,427,15,17,19,21,4,517,519,521,523,525,527,4,39,441,443,445,447,449,451,453,455,457,459,461,537,539,541,543,545,547,1,3,5,7,9,11,13,463,465,467,23,399,401,403,405,407,409,411,499,501,503,505,333,335,337,339,341,343,345,347,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,9,171,173,175,177,179,181,183,185,187,269,271,273,275,277,279,281,283,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,133,135,137,139,141,143,145,285,287,289,291,121,123,125,127,129,131,297,299,373,375,377,379,381,383,385,387,389,97,99,101,103,105,147,149,151,153,155,157,159,161,163,165,167,16,391,393,395,397,399,401,403,189,191,193,195,197,199,201,247,249,251,253,255,257,259,261,263,265,267,343,345,347,349,501,503,505,333,335,337,339,341,417,419,421,423,425,561,563,565,567,569,571,573,587,589,591,593,595,597,599,427,429,431,433,301,303,305,307,309,311,313,315,317,319,321,323,325,327,329,331,371,359,361,363,365,367,369,507,509,511,513,515,351,353,355,57,517,519,521,523,525,527,413,415,405,407,409,411,499,435,437,469,471,473,475,477,479,481,483,485,487,545,547,549,551,553,555,575,577,579,581,583,585,557,559,489,491,493,495,497,529,531,533,535,537,539,541,543,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,293,295};
int temp;
// traverse 0 to array length
for (int i = 0; i < arr.Length ; i++)
{
// traverse i+1 to array length
//for (int j = i + 1; j < arr.Length; j++)
for (int j = i+1; j < arr.Length; j++)
{
// compare array element with
// all next element
if (arr[i] > arr[j]) {
///Console.WriteLine(i+"i before"+arr[i]);
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
//Console.WriteLine("i After"+arr[i]);
}
}
}
// print all element of array
foreach(int value in arr)
{
Console.Write(value + " ");
}
}
}
This is selection sort. It's time complexity is O(𝑛²). It has nested loops over i and j, and you can see these produce every possible set of two indices in the range {0,...,𝑛-1}, where 𝑛 is arr.Length. The number of pairs is a triangular number, and is equal to:
𝑛(𝑛-1)/2
...which is O(𝑛²)
If we stick to selection sort, we can still find some improvements.
We can see that the role of the outer loop is to store in arr[i] the value that belongs there in the final sorted array, and never touch that entry again. It does so by searching the minimum value in the right part of the array that starts at this index 𝑖.
Now during that search, which takes place in the inner loop, it keeps swapping lesser values into arr[i]. This may happen a few times, as it might find even lesser values as j walks to the right. That is a waste of operations, as we would prefer to only perform one swap. And this is possible: instead of swapping immediately, delay this operation. Instead keep track of where the minimum value is located (initially at i, but this may become some j index). Only when the inner loop completes, perform the swap.
There is less important improvement: i does not have to get equal to arr.Length - 1, as then there are no iterations of the inner loop. So the ending condition for the outer loop can exclude that iteration from happening.
Here is how that looks:
for (int i = 0, last = arr.Length - 1; i < last; i++)
{
int k = i; // index that has the least value in the range arr[i..n-1] so far
for (int j = i+1; j < arr.Length; j++)
{
if (arr[k] > arr[j]) {
k = j; // don't swap yet -- just track where the minimum is located
}
}
if (k > i) { // now perform the swap
int temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
}
}
A further improvement can be to use the inner loop to not only locate the minimum value, but also the maximum value, and to move the found maximum to the right end of the array. This way both ends of the array get sorted gradually, and the inner loop will shorten twice as fast. Still, the number of comparisons remains the same, and the average number of swaps as well. So the gain is only in the iteration overhead.
This is "Bubble sort" with O(n^2). You can use "Mergesort" or "Quicksort" to improve your algorithm to O(n*log(n)). If you always know the minimum and maximum of your numbers, you can use "Digit sort" or "Radix Sort" with O(n)
See: Sorting alrogithms in c#

Range in for loop using Array

I'm pretty new to C# and want the users to be able to write in 5 numbers between 1 to 25. The issue I'm having is that I don't want the user to type a number over 25 or a number below 1.
Also this is a task for my studies and my teacher want us to use arrays so I'm not allowed to use List.
int[] usernum = new int[4];
for (int i = 0; i < usernum.Length; i++)
{
usernum[i] = Convert.ToInt32(Console.ReadLine());
}
Ok, to start off, some annotations to your code:
int[] usernum = new int[4]; // should be: new int[5];
for (int i = 0; i < usernum.Length; i++)
{
usernum[i] = Convert.ToInt32(Console.ReadLine()); // use int.TryParse instead
}
Now, I don't want to just give you the code, since this should obviously be a learning experience.
What you need to do, though is integrate a "validation" cycle. That means:
Read in string from user
Try to parse string to number
If that fails: back to 1.
Check if number < 1 or > 25
If so: back to 1.
If you are here, you passed both checks and can
set usernum[i] = number
Next "i"
Obviously, there are some slight variations in how you twist and turn your checks and arrange loops which are equally valid.
For example: You can decide if you want to check if number is inside bounds or if you want to check if the number is outside bounds and jump or not jump accordingly ...
Why int.TryParse instead of Convert.ToInt32?
There are some rule of thumbs that can spare you from severe headaches:
"Never trust user input"
"Do not use exceptions for control flow"
Using Convert here, breaks both.
For one, Convert.ToInt32 throws if the string does not represent an integer value (chars other than +-0..9, value > int.Max or < int.Min). So in using it, you trust the user to type in a valid integer. Not a good idea.
Then, it throwing means: the case, that a user (maybe just made a typo) did not provide valid input is controlling your flow to error handling. But this case is not at all "exceptional". In fact, you should expect it. int.TryParse makes this possible, in that it returns you a flag (boolean) that informs you about success or failure of the conversion attempt (instead of throwing).
Though I would recommend you to learn if else loop first https://www.w3schools.com/cs/cs_conditions.asp
here is the code if needed
int[] usernum = new int[4];
for (int i = 0; i < usernum.Length; i++)
{
var result = Console.ReadLine();
int currentResult;
if (!int.TryParse(result, out currentResult))
{
Console.WriteLine("Invalid input - must be a valid integer value");
i--;
continue;
}
if(currentResult < 1 || currentResult > 25)
{
Console.WriteLine("Invalid input - must be between 1 & 25");
i--;
continue;
}
usernum[i] = currentResult;
}
for-loop might not be the ideal solution for this use-case where you need to conditionally increment the index.
This should do the trick:
int[] userNumbers = new int[5];
int i = 0;
while (i < userNumbers.Length)
{
string rawInput = Console.ReadLine();
bool isNumberValid = int.TryParse(rawInput, out int inputNumber); // as suggested by #Fildor
if(isNumberValid && inputNumber >= 1 && inputNumber <= 25) // increment counter only if 1 <= input <= 25
{
userNumbers[i] = inputNumber;
i++;
}
}

How to find subset of numbers in array that equals to 10? [duplicate]

This question already has answers here:
Find if pair of elements with given sum exists in large integer array
(6 answers)
Closed 8 years ago.
I want to find the sum of all subsets of adjacent numbers.
So if the set is 6 1 2 2 5
I want to find (the sum of)
6 1 2 2 5
6 1 2 2
1 2 2 5
6 1 2
1 2 2
2 2 5
6 1
1 2
2 2
2 5
So I want to find not anly subsets of 2 numbers,but more(example input: 6 1 2 2 5 -> 6+2+2=10 or 1+2+2+5=10) and print them.
using System;
class Subset
{
static void Main()
{
string[] num = Console.ReadLine().Split(' ');
int[] number = new int[num.Length];
for (int a = 0; a < 5; a++)
{
number[a] = Convert.ToInt32(num[a]);
}
int sum;
bool found = false;
for (int i = 0; i < 5; i++)
{
sum = 0;
for (int j = i; j < 5; j++)
{
sum = sum + number[j];
if (sum == 10)
{
found = true;
for (int k = i; k < j; k++)
{
Console.Write("{0} + ", number[k]);
}
Console.Write(number[j]);
Console.Write(" = 10\n");
}
}
}
if (found == false)
{
Console.WriteLine("no zero subset\n\n");
}
}
}
This is very similar to the subset sum problem. The only way to really find a combination that adds up to ten (or even all combinations), you will have to test all combinations. I am not sure if you want combinations of any size, or only two numbers. The examples you give only involve examples where two numbers add up to ten, which can be easily done by checking for all pairs.
for (int i = 1; i < numbers.Length; i++)
for (int j = 0, j < i; j++)
if (numbers[i] + numbers[j] == 10)
{
Console.WriteLine("{0} + {1} = 10", numbers[i], numbers[j];
return;
}
Console.WriteLine("no subset that sums up to 10");
If however you want to find any subset of numbers that add up to ten, you have to consider all subsets of the set you are given. The best way to do this is using dynamic programming. You loop through the array of numbers and for each number you make the decision to either include the element in the subset or not. Let's look at the following method:
bool SubsetSum(int[] numbers, int startIndex, int sum)
{
if (startIndex == numbers.Length - 1) // base case, only one element to consider
return numbers[startIndex] == sum || sum = 0;
return SubsetSum(numbers, startIndex + 1, sum) // don't take the current element
|| SubsetSum(numbers, startIndex + 1, sum - numbers[startIndex]; // take the current element
}
This method first checks if we arrived at the last element. In that case, we have two easy cases to consider: the sum we want to reach is 0, so we don't take the element, or the sum we want to reach is equal to the last element, in which case we do take it. Otherwise, there is no valid solution.
In all the other cases, we just branch into two paths, either taking or not taking the element into the subset.
This algorithm will run in exponential time in the amount of numbers as input. You can speed this up by using memorisation. You can create a huge table and save for every pair of startIndex and sum the outcome value. That way you are sure you will never evaluate the same thing twice. (Look up dynamic programming to learn more about this)
The method I described above only returns if a subset exists. To actually find the subset, you will also have to pass back the indices of the elements you have added to the subset. I won't work that out, as it makes the thing a lot more complicated. If you use a table in the dynamic programming approach, you are also able to use some backtracking techniques to find the right indices in linear time.

2d array,adding it values in a weird pattern

i started learning C# and programming a few months ago and have some problems. The idea here is we create a 2 dimensional array (the number of rows / columns are added by the user), the numbers need to be between 1 and 10.
Then when the array is created the number sequence ( 3-5-7-9-11 etc) is started in the first and finishes in the last column. The rest of the numbers in the columns are added via keyboard by the user starting with the first row (ignoring column 1 and the last column cause we have that added).
The questions are :
What will be the best way to check if the numbers of rows/columns are between 1 and 10? (I was thinking of IF-else but isn't there a better way ?)
How will i make it so that the number sequence 3-5-7 etc is started in the first and finishes in the last column?
Yeah i feel lost.
Where i am at the moment :
Console.WriteLine("Add row value of 1-10");
string s1
s1 = Console.ReadLine();
int k = int.Parse(s1);
Console.WriteLine("Add column value of 1-10");
string s2;
s2 = Console.ReadLine();
int p = int.Parse(s2);
int[,] M = new int[k, p];
Example : we added k(row) & p(coulmn) value of 4.So the array should look like :
3 x x 11
5 x x 13
7 x x 15
9 x x 17
Then the X's should be added again manually without overwriting the existing numbers .The value of the numbers doesnt matter.
So... If I get it right you want to ask user the "length and width" of dynamical 2d array?
To check if entered number is between 1 and 10 there's only 1 method:
int [,] M;
if (k >= 1 && k <= 10 && p >= 1 && p <= 10)
{
M = new int[k,p];
}
And better is to do int.TryParse() for case if user enters characters there instead of numbers, or else you can easily get an Exception.
Filling with numbers:
int num = 3;
for (int i = 0; i < k; ++i)
{
M[i,0] = num;
num+=2;
}
for (int i = 0; i < k; ++i)
{
M[i,p] = num;
num+=2;
}
This adds numbers in 1st and last column in each row. After that to fill other cells manually you check every cell thet it is not in firs or last column.
I hope I understood you correctly. Provided code may be simplified, but provided in such way for better understanding.
if(k>0 && k<11 && p>0 && p<11)
{
int i;
int M[,] = new int[k,p];
for (i=0;i<k;i++)
{
M[i,0]=i*2+3;
M[i,p-1]=(i+k)*2+3;
}
}

First Element as pivot in Quick sort

Why this code gives me wrong ? In Quick sort , I have picked up the first element as pivot:
I have traced that on paper,nothing is wrong.
private void QuickSort(ref int [] S ,int l,int h)
{
//partioning
int pivot_index = l;
int j = 0;
int temp = 0;
for(int i=l+1;i<=h;i++)
if (S[pivot_index] > S[i])
{
j++;
temp = S[i];
S[i] = S[j];
S[j] = temp;
}
pivot_index = j;
temp = S[l];
S[l] = S[j];
S[j] = temp;
//end partioning
if (l < h && pivot_index>l && pivot_index<h)
{
QuickSort(ref S, l, pivot_index - 1);
QuickSort(ref S, pivot_index + 1, h);
}
}
here is my main :
int[] List = get_input(textBox1.Text, ref n);
//
QuickSort(ref List, 0, n-1);
Your function is apparently supposed to sort [l, h] range in the array, yet for some reason you are swapping element number i with element number j. The latter (j) is out of [l, h] range (it is always initially 0 and then it becomes 1, 2, 3 and so on). What are you trying to do by this? Why are you swapping your elements to some totally unrelated remote location out of your sorting range?
In other words this does not even remotely look like a QuickSort-style sorting algorithm to me. Your unexplainable manipulations with j is one reason why your implementation cannot really sort anything.
Your algorithm is wrong. Get the pivot value int pivot = S[pivot_index];.
Then determine the two elements that you want to swap. Therefore, determine the first element from the left, which is greater than or equal to the pivot value. This gives i. Then determine the first element from the right, which is less than or equal to the pivot value. This gives j. As long as i is less than j swap S[i] and S[j] and repeat the process.
Only after there are no more swaps to make, look if you can call QuickSort recursively. Here two separate if checks must be made for the left part and the right part.
Also, note that it is better to take the element in the middle as pivot element. QuickSort will perform better, if the elements should be pre-sorted or sorted in descending order.
int pivot = S[(l+h)/2];

Categories

Resources