I'm fresh to C# and I've got a homework problem I'm struggling with. I can't copy the contents of a table to another one with loops. I want it to copy positive numerals from a 10-element predefined table to the second and show the contents in the console after it's done.
int[] tab1 = { 4, 6, 32, 16, 5, 22, -3, 61, 11, 99 };
int[] tab2 = new int[tab1.Length];
for (int i = 0; i < tab2.Length; i++)
{
while(i > 0)
{
tab2[i] = tab1[i];
}
}
for (int i = 0; i < tab2.Length; i++)
{
Console.Write(tab2[i] + ", ");
}
Console.ReadKey();
The first item that is positive puts your program into an infinite loop.
Change while inside the for loop to an if. Inside the while you have tab2[i] = tab1[i];, which, for each i, will never change the condition on the while loop. So for each item in the array you will either execute the assignment for an item ad infinitum or never execute the assignment.
Changing while to if removes the loop (in the loop) and evaluates the conditional expression for the single element in the loop.
Another way to think of this is this: "for each of these items, if that item is positive I will assign it to the other array". What you expressed, in code, was "for each of these items, while that item is positive, assign it to the other array", which doesn't do what you want.
If you don't know how many items positive(will be in the tab2), you cannot define the size of the second array. So you better to use List, where you can store the required number of items. if (tab1[i] > 0) will examine the item in the first array.
int[] tab1 = { 4, 6, 32, 16, 5, 22, -3, 61, 11, 99 };
List<int> tab2 = new List<int>();// because you dont know how many items positive
for (int i = 0; i < tab1.Length; i++)
{
if (tab1[i] > 0)
{
tab2.Add(tab1[i]);
}
}
for (int i = 0; i < tab2.Count; i++)
{
Console.Write(tab2[i] + ", ");
}
Console.ReadKey();
Related
I'm trying to create a lottery number program that accepts 10 guesses from the user between the numbers 1-25. The user guesses are stored in the user array. If the user enters the wrong value (< 1 or > 25) the number will not be stored within the user array. The program stores 10 random numbers in another array. So, two arrays in total.
How to compare the two arrays to find common elements, to let the user know how many correct guesses the user made compared to the random numbers array? For this part, I am only allowed to use loops.
I have tried using continue; below the first If, but that messes things up.
I have tried to move the ending curly brackets for the first for-loop to below the first If, but that also messes things up at the "compare the two arrays" part.
//User array
int[] användarTal = new int[10];
//Random numbers array
int[] slumpadeTal = new int[10];
//Generator for 10 random numbers.
Random randomerare = new Random();
//Foor-loop for storing user's 10 guesses in the user array.
for (int i = 0; i < användarTal.Length; i++)
{
Console.Write("Enter your guess: ");
string input = Console.ReadLine();
int num = Convert.ToInt32(input);
användarTal[i] = num;
//If the user enters wrong value
if (num < 1 || num > 25)
{
Console.WriteLine("Wrong! You must enter a number between 1-25!");
användarTal[i] = i--; //Wrong number will not be stored in the user array.
}
// continue;
// }
//For-loop for storing and writing out the 10 random numbers.
for (int j = 0; j < slumpadeTal.Length; j++)
{
Console.WriteLine(randomerare.Next(1, 26));
// Checking if the two arrays have any common numbers
if (användarTal[i] == slumpadeTal[j])
{
Console.WriteLine(användarTal[i]);
}
}
I found this solution which I have tried to implement into my program, but I can't get the program to run the way it's supposed to.
int[] arr1 = { 12, 5, 45, 47, 22, 10 };
int[] arr2 = { 23, 45, 10, 58, 78, 77, 46 };
for (int i = 0; i < arr1.Length; i++)
{
for (int j = 0; j < arr2.Length; j++)
{
if (arr1[i] == arr2[j])
{
Console.WriteLine(arr1[i]);
}
}
}
int[] arr1 = { 12, 5, 45, 47, 22, 10 };
int[] arr2 = { 23, 45, 10, 58, 78, 77, 46 };
for (int i = 0; i < arr1.Length; i++)
{
for (int j = 0; j < arr2.Length; j++)
{
if (arr1[i] == arr2[j])
{
Console.WriteLine(arr1[i]);
}
}
}
I dont see an issue with this code, seems like it should execute fine.
However you can optimise this using Linq
int[] array1 = { 12, 5, 45, 47, 22, 10 };
int[] array2 = { 23, 45, 10, 58, 78, 77, 46 };
int[] commonElements = array1.Intersect(array2);
Console.WriteLine("Common Elements: {0}", string.Join(",", commonElements));
See https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.intersect?view=net-7.0
It seems that you want to store and guess unique numbers only.
To be sure that numbers are unique, let's use HashSet<int> instead
of arrays:
using System.Linq;
...
// Random numbers array
HashSet<int> slumpadeTal = Enumerable
.Range(1, 25)
.OrderBy(item => Random.Shared.NextDouble())
.Take(10)
.ToHashSet();
Then let's ask user to guess
HashSet<int> användarTal = new HashSet<int>();
while (användarTal.Count < slumpadeTal.Count) {
while (true) {
Console.Write("Enter your guess: ");
if (int.TryParse(Console.ReadLine(), out int guess) &&
guess >= 1 && guess <= 25) {
användarTal.Add(guess);
break;
}
Console.WriteLine("Incorrect guess; it should be 1..25");
}
}
Having both collections filled in you can easily compare them
int guessedRight = slumpadeTal
.Count(item => slumpadeTal.Contains(item));
I have a list of numbers and if the number that I am looking for is not in the list I want to be able to find the next value that is in the list above and below the number that I have asked for.
double index = 5;
List<double> list = new List<double>() { 1, 2, 3, 7, 8, 9, };
//do code to find next highest/lowest
double higher = 7;
double lower = 3;
for example, because 5 is not exactly in the list itself I want it to return the next item that is closest to 5 both above and below. so for this case, 3 and 7.
Original version
You can use List's Sort() method, then use LINQ FirstOrDefault() and LastOrDefault()
List<double> numbers = new List<double>()
{
1, 2, 3, 7, 8, 9
};
double input = 5;
numbers.Sort();
double nextHighest = numbers.FirstOrDefault(x => x > input);
double nextLowest = numbers.LastOrDefault(x => x < input);
Better version edit This wont actually work for both cases
Originally I suggested this as a more efficient solution, but this will not work for the number before a given input. It only works for finding a number after the given input.
You can be more efficient since you are using List<T>, there is a Find() method that accepts a predicate:
List<double> numbers = new List<double>()
{
1, 2, 3, 7, 8, 9
};
double input = 5;
numbers.Sort();
double nextHighest = numbers.Find(x => x > input);
This will exit the loop immediately upon finding a match (whereas LastOrDefault() has to iterate the entire collection)
Fiddle for both here
One solution would be sort the list and then iterate over it to find the spot where list[i] < index < list[i+1]. This would take O(n * log(n)) time.
A better solution is simply iterate over the list and use 2 variables that you will update accordingly (let's say max and min).
max will store the maximum value that is below the index.
min will store the minimum value that is above the index.
That last solution takes O(n) time.
LinQ-Solution:
double index = 5;
List<double> list = new List<double>() { 1, 2, 3, 7, 8, 9, };
double higher=list.OrderBy(q=>q).First(q=>q>index); // 7
double lower=list.OrderByDescending(q=>q).First(q=>q<index); // 3
Explanation: First you sort the list Ascending or Descending. After that all you have to do is to find the greater or smaller number;
You might want to replace First() by FirstOrDefault() if you do not want an exception if no higher/lower value exists.
In case you want all the occurency
double index = 5;
List<double> list = new List<double>() { 1, 2, 3, 7, 8, 9, };
for(int i =1 ; i <= 9-5 ; i++)
{
List<double> NextHigh = list.Where(x=> x-i == index).ToList();
if(! (NextHigh.Count == 0))
{
NextHigh.Dump();
break;
}
}
for(int i =1 ; i <= 5-1 ; i++)
{
List<double> NextLow = list.Where(x=> x+i == index).ToList();
if( !(NextLow.Count== 0))
{
NextLow.Dump();
break;
}
}
The other answer given is not very good if you are going to be using a large list of values, because it needs to index the list twice.
If you make your own loop like this:
double higher = Double::MaxValue;
double lower = Double::MinValue;
double index = 5; // the value you want to get.
List<double> list = {1,2,3,7,8,9}; // the list you're searching.
for(int i = 0; i < list.Count; i++)
{
if(list[i] > index && list[i] < higher)
higher = list[i]; // sets the higher value.
else if(list[i] < index && list[i] > lower)
lower = list[i]; // sets the lower value.
}
After execution, this would give you 3 and 7, the correct values.
I should note that this takes O(n) time, because it only loops once. This will be faster than anything posted at the time of this edit (plus it's pretty easy to see what its doing).
You can archieve that by this way. These codes below was tested from my side.
double index = 5;
double higher = 0 ;
double lower = 0;
List<double> list = new List<double>() { 1, 2, 3, 7, 8, 9, };
list.Sort();//Sort list from low to high numbers
if(!list.Contains(index))
{
foreach (var item in list)
{
if(item < index)
{
lower = item;
}
if (item > index)
{
higher = item;
break;
}
}
}
Console.WriteLine(index);//5
Console.WriteLine(lower);//3
Console.WriteLine(higher);//7
Working on a homework question, I'm given the task to re-write a for-loop to a while-loop with this as the for-loop snippet:
int[] numbers = { 2, 3, 5, 7, 11 };
for (int i = 0; i < numbers.Length; ++i)
{
Console.WriteLine(numbers[i]);
}
What I've come up with so far is what I believe to be close, but I may be completely wrong. I've looked in my book and on the internet trying to figure out what's incorrect about the re-write. The re-write is below:
int[] numbers = { 2, 3, 5, 7, 11 };
int i;
while (i = numbers)
{
Console.WriteLine(numbers[i]);
}
you don't seem to be incrementing your i value inside the while loop and the condition has to be changed to something like this i < numbers.Length
You can rewrite like this :
int i=0;
while(true)
{
if(i<numbers.Length)
break;
Console.WriteLine(numbers[i]);
i++;
}
or else you can put the if condition in while itself...
Don't really want to give a complete answer to the assignment. But this should help:
A for loop consists of three parts:
The first part would run before the loop begins
The second part is a while condition. The loop runs while this condition is still true. This is usually the trickiest part.
The third part runs each time after running the body of the loop
Now a while condition simply has the second part: the while condition. So you will need to re-order the rest of the loop accordingly when changing from a for to a while.
int[] numbers = { 2, 3, 5, 7, 11 };
int i = 0;
while (i < numbers.Length)
{
Console.WriteLine(numbers[i]);
i++;
}
You have to increment the value of i like above and condition should be as i < numbers.Length and look at this great example
int[] numbers = { 2, 3, 5, 7, 11 };
int i = 0;
while (i < numbers.Length)
{
Console.WriteLine(numbers[i]);
i++;
}
its a very easy way . only problem in your code is while condition and you are not increment a i which is referring an index of an array.
int[] numbers = { 2, 3, 5, 7, 11 };
int i = 0;
while (i < numbers.Length)
{
Console.WriteLine(numbers[i]);
i++;
}
Make sure to initialize declared variable int i; or you will get an warning / error
Also the i++ in this line (for i=0; i < numbers.Length; ++i) tells the counter for your variable i to increment by i + 1 the < sign tells you that it will iterate at a zero-base starting from 0,1,2,3 which is 4 times .NET arrays are 0 based so to transpose that into a While Loop the key things to look at are the following
i which is your variable, you should always initialize to a value normally 0
the < sign, tells you that you will use that in your while loop vs a <=`
lastly, the i++ at the bottom of the while loop says , increment i by 1 which is i++ which translates to i = i + 1
Im looking for some help with finding subsets of array.
int[] array = { 1,2,3,5,8,10,15,23};
I have to find all subsets of an array. If sum of the subsets elements equal to any number in array then my counter increment. For example: 1+2=3, 2+3=5, 5+8+10=23, 1+2+5=8, 2+3+8+10=23
public static void Main(string[] args)
{
int[] array = { 1, 2, 3, 5, 8, 10, 15, 23 };
int arrayLength = array.Count();
int sum = 0;
int subsetCount = 0;
for (int i = 0; i < arrayLength; i++)
{
for (int j = i + 1; j < arrayLength; j++)
{
sum = array[i] + array[j];
for (int m = j + 1; m < arrayLength; m++)
{
for (int k = 0; k < arrayLength; k++)
{
if (array[k] == sum)
{
subsetCount++;
}
}
sum = array[i] + array[j] + array[m];
}
}
}
Console.WriteLine(subsetCount);
Console.ReadLine();
}
I'm ok with 2-elements and 3-elements of subsets. But 4 and above I can't figured out how to solve it?
Any help would be greatly appreciated
You only need two loops to find the sum of all subsets. The outer loop is the starting point of subsets, and the inner loop is calculating the sums of all subsets from that starting point.
With the first index as starting points the subsets are 1+2, 1+2+3, 1+2+3+5 and so on. As you are only interested in the sum of the subsets you can just add one item after the other to get the sum of the subsets.
Then for each sum loop through the items to check for a match:
int[] array = { 1, 2, 3, 5, 8, 10, 15, 23 };
int subsetCount = 0;
for (int i = 0; i < array.Length; i++) {
int sum = array[i];
for (int j = i + 1; j < array.Length; j++) {
sum += array[j];
for (int k = 0; k < array.Length; k++) {
if (array[k] == sum) {
subsetCount++;
}
}
}
}
Console.WriteLine(subsetCount);
Edit:
I assumed that you meant continuous subsets, but from your examples it seems that you also want non-continuous subsets.
Lets's start with the correct solution:
23 = 15+8, 15+5+3, 15+5+2+1, 10+8+5, 10+8+3+2
15 = 10+5, 10+3+2, 8+5+2
10 = 8+2, 5+3+2
8 = 5+3, 5+2+1
5 = 3+2
3 = 2+1
That gives us 14 different subsets that sums up to an item in the set.
You can count the subsets recursively, only keeping track of the sum and number of items in subsets. You don't need the actual subsets, only to know the sum and that there are at least two items in the subset.
The subsets in a set is the first item combined with all subsets in the rest of the set, plus the subsets in the rest of the set. For example the subsets s() of [1,2,3] is 1,s([2,3]) and s([2,3]).
This gives you:
public static int CountSubsets(int[] arr, int start, int len, int sum) {
int cnt = 0;
if (start < arr.Length) {
if (len >= 1 && arr.Contains(sum + arr[start])) cnt++;
cnt += CountSubsets(arr, start + 1, len + 1, sum + arr[start]);
cnt += CountSubsets(arr, start + 1, len, sum);
}
return cnt;
}
And calling it:
int[] set = { 1, 2, 3, 5, 8, 10, 15, 23 };
Console.WriteLine(CountSubsets(set, 0, 0, 0));
Output:
14
This seems a lot like homework to me. So I will answer in that spirit (i.e. rather than write the code, point you in the right direction).
First, it's not really clear what you mean by "subset". Are you talking about contiguous runs of elements from the array? Or do you literally mean treating the array as an unordered set, from which you examine every possible subset?
The latter is significantly harder than the former. So I'm going to assume the former for the moment.
Then, it seems you really have two different problems:
Find all subsets of the array and sum each one
For a given sum, determine whether it's in the array
The latter is fairly straightforward. If you know these arrays will always be relatively short (and hopefully they will be, otherwise "find all subsets" may take awhile :) ), you can just do a linear search every time you have a new sum to look for.
Alternatively, a more semantically straightforward approach would be to create a HashSet<int> instance once using the members of the array, and then when you want to know if the sum is in the array, just check your set.
For example:
HashSet<int> setOfValues = new HashSet<int>(array);
Then you can just write setOfValues.Contains(sum) to check whether the value held by the variable sum is contained in the array.
As for the first problem, it seems to me that you really should only need two loops:
A loop to iterate on the index of the first element of a subset. I.e. you need to enumerate all subsets, first starting with all subsets that start with element 0, then with all subsets that start with element 1, and so on.
A loop to iterate on the length of the subset. I.e. having determined the starting index for your current group of subsets, now you want to find all the actual subsets: the first has length 1, the second has length 2, and so on up to the maximum possible length (i.e. the length of the array minus the current 0-based starting index value).
Considering for a moment the alternative possibility — that you are treating the array as an unordered set — then it seems to me an obvious, if brute-force approach, would be to generate the subsets recursively.
In that approach, you would again have a loop to enumerate the subset lengths, starting with 1, up to the total length of the original set. Then, given a length, you need to pick all possible subsets.
You can do this recursively:
Given a set, iterate over the elements of the current set (passed in to your recursive method). The current element is the new element of your current subset.
If your current subset is now the correct length, sum it and compare to the original set.
Otherwise, remove the current element from the current set and recurse.
The easiest implementation of the above will create new copies of the current set for each level of recursion, to pass to the method when it calls itself. This way you don't have to worry about one level of recursion interfering with previous levels.
Do note that this is going to be practical only for relatively small initial sets. It won't take very large initial arrays before your computer doesn't have enough time or memory to complete the search of all possible subsets.
First up, you need a method that will return all subsets.
Func<IEnumerable<int>, IEnumerable<IEnumerable<int>>> getAllSubsets = null;
getAllSubsets = xs =>
(xs == null || !xs.Any())
? Enumerable.Empty<IEnumerable<int>>()
: xs.Skip(1).Any()
? getAllSubsets(xs.Skip(1))
.SelectMany(ys => new [] { ys, xs.Take(1).Concat(ys) })
: new [] { Enumerable.Empty<int>(), xs.Take(1) };
So given getAllSubsets(new[] { 1, 2, 3 }) I get:
{ }
{ 1 }
{ 2 }
{ 1, 2 }
{ 3 }
{ 1, 3 }
{ 2, 3 }
{ 1, 2, 3 }
Now's it's easy to compute the result you want.
int[] array = { 1,2,3,5,8,10,15,23};
var result =
getAllSubsets(array)
.Where(ss => array.Contains(ss.Sum()))
.Count();
I get 22.
Using a bit of Linq:
int[] array = {1, 2, 3, 5, 8, 10, 15, 23};
var subsets = new List<IEnumerable<int>>();
int counter = 0;
for (int i = 0; i < array.Length; i++)
{
for (int j = 2; j < array.Length - i; j++)
{
if (array.Contains(array.Skip(i).Take(j).ToList().Sum()))
{
counter++;
}
}
}
Console.WriteLine("Number of subsets:" + counter);
Gives you:
Number of subsets:5
My algorithm should find the greatest right number from the current number in an input array, for example, given the following int[] input:
5, 9, 6, 1, 3, 2
My algorithm will output:
9, 6, 3, 3, 2, 2
Here is my current code:
public static int[] FindGreatestRightNumber(int[] input)
{
var output = new int[input.Length];
for (var i = 0; i < input.Length; i++)
{
int maxRightNumber = (i == input.Length - 1 ? input[i] : 0);
for (var j = i+1; j < input.Length; j++)
{
var currentNumber = input[j];
if (maxRightNumber < currentNumber)
maxRightNumber = currentNumber;
}
output[i] = maxRightNumber;
}
return output;
}
I was told it could be much faster, how? any idea?
UPDATE: Please don't use LINQ in your answers, I would like to get familiar with faster ways to solve the problem using simple code, no LINQ, IEnumerable Extension Methods etc.
You can do this in a single pass from the right hand side. The trick is realizing maxRightVal(n) = max(maxRightVal(n+1), values(n+1)):
var output = new int[input.Length];
output[input.Length-1] = input[input.Length-1];
for(int i = input.Length - 2; i >= 0; i--)
output[i] = output[i+1] > input[i+1] ? output[i+1] : input[i+1];
Why not just using Enumerable.Max() method?
Returns the maximum value in a sequence of Int32 values.
int[] input = new int[] { 5, 9, 6, 1, 3, 2 };
int biggest = input.Max();
Console.WriteLine(biggest); // 9
Here is a DEMO.
Since, I see the question better now, VLad's answer looks the right one.
very simple if you want to skip some items and search the max
int[]arr = {5, 9, 6, 1, 3, 2};
int currentIndex = 2;
int currentValue = 6;
int max = arr.Skip(currentIndex).Where(f => f > currentValue).Max();
EDIT if you want to simply sort an array, then:
int[] sorted = arr.OrderByDescending();
Start from the (n-2)th elements, maintain a current max array which is initialised with nth element. Keep updating it if the current element is greater than the element in max array. Continue this until the first element is reached.
This takes the largest value to the right of each element;
int[] input = {5, 9, 6, 1, 3, 2};
int[] output = input
.Take(input.Length-1)
.Select( (x,i) => input.Skip(i+1).Max()).ToArray();