C#, Rotate a List to the Right by specified places - c#

I'm trying to rotate a List to the right by a certain specified numbers of places. I think that an array (or List) rotation can be seen as a circular, which means elements that fall off the end would wrap around to the beginning, and vice versa. A good example of this could possibly be if we have an array or list, then we rotated it to the right by three places, the result will be as follow:
Initial Array (or List): 20, 30, 40, 50, 60, 70
Rotated to the right by 3 places: 50, 60, 70, 20, 30, 40.
I've written some code down, based of what the little I understand of this concept. I would like to know, what's the correct way to do this manually (without any sort of fancy code nor LINQ) as it will help me to understand it better.
i'm asking for the manual way to solve this problem, not with anything fancy.
public void Test8(List<int> items, int places)
{
int[] copy = new int[items.Count];
items.CopyTo(copy, 0);
for (int i = 0; i < items.Count; i++)
{
int RotateRight = (i + places) % items.Count;
items[i] = copy[RotateRight];
}
}

Here is a approache with Linq with Skip() and Take().
List<int> iList = new List<int>() { 20, 30, 40, 50, 60, 70 };
int rotate = 3;
List<int> lResult = iList.Skip(rotate).Concat(iList.Take(rotate)).ToList();
another approach with a simple loop
int[] items = new int[] { 20, 30, 40, 50, 60, 70 };
int[] result = new int[items.Length];
int rotate = 3;
for (int i = 0; i < items.Length; i++)
{
result[i] = items[(i+rotate)% items.Length];
}

Related

How do I compare two arrays to find common elements (random numbers vs. user input)?

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));

Copying table contents to another with loops

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();

C# Random algorithm until fulfills condition

I have the following scenario:
Generate n numbers of random number from a certain range
Sum all the numbers
Check if the sum == x (x is a number set by user)
if sum != x then keep running the loop
If sum == x, then display the list of random numbers that sum up to x
Based on this logic, I was able to do so but it takes forever to achieve the result, is there any better / way to solve this problem?
static void Main(string[] args)
{
Console.WriteLine("starting...");
List<int> checkList = generate(5);
while(!checkSum(checkList, 100))
{
checkList = generate(5)
}
Console.WriteLine("done!");
}
private static bool checkSum(List<int> n, int sum)
{
if(n.Sum() == sum)
{
return true;
}
else
{
return false;
}
}
public static List<int> generate(int n)
{
Random rng = new Random();
List<int> list = new List<int>();
for (int i = 0; i < 5; i++)
{
//int ran = some random number
list.Add(ran);
}
return list;
}
EDIT
My scenario here is to obtain n combinations of random integer that sums up to 100. The number of combinations is taken from input by user. So the program will give the n number of possible combinations that sums up to 100.
Possible combinations:
25+37+9+20+9 = 100
46+21+13+8+12 = 100
If you have a fixed sum and a fixed number of elements you want, look at the problem as partitioning. For example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PartitionAndAllocateTEst
{
class Program
{
static void Main(string[] args)
{
var rand = new Random();
int desiredTotal = 100;
int partitions = 5;
for (int i = 0; i < 10; i++)
{
List<int> result = GetRandomCollection(rand, desiredTotal, partitions);
Console.WriteLine(string.Join(", ", result.Select(r => r.ToString()).ToArray()));
}
}
private static List<int> GetRandomCollection(Random rand, int desiredTotal, int partitions)
{
// calculate the weights
var weights = new List<double>();
for (int i = 0; i < partitions; i++)
{
weights.Add(rand.NextDouble());
}
var totalWeight = weights.Sum();
// allocate the integer total by weight
// http://softwareengineering.stackexchange.com/questions/340393/allocating-an-integer-sum-proportionally-to-a-set-of-reals/340394#340394
var result = new List<int>();
double allocatedWeight = 0;
int allocatedCount = 0;
foreach (var weight in weights)
{
var newAllocatedWeight = allocatedWeight + weight;
var newAllocatedCount = (int)(desiredTotal * (newAllocatedWeight / totalWeight));
var thisAllocatedCount = newAllocatedCount - allocatedCount;
allocatedCount = newAllocatedCount;
allocatedWeight = newAllocatedWeight;
result.Add(thisAllocatedCount);
}
return result;
}
}
}
Example output:
30, 6, 19, 15, 30
36, 8, 22, 10, 24
2, 25, 32, 21, 20
22, 7, 30, 12, 29
36, 21, 22, 0, 21
24, 24, 2, 29, 21
18, 13, 10, 39, 20
11, 19, 20, 27, 23
24, 19, 7, 25, 25
24, 14, 27, 18, 17
You could try using a genetic algorithm. Start with a population of, say, 100 sets of five random integers. Sum each set. Select 50 of the better sets, the ones with a sum closer to 100. Keep the better 50, dump the other 50 and replace them with tweaked versions of the best 50. The tweak is replacing one integer in the set with another random integer.
Whenever a member of the population sums to exactly 100, pull it out into your output array and make up the population with a newly generated set of five integers.
Genetic algorithms work a lot faster than brute force.
I don't see why you're being downvoted. Your problem is clear, and you already knew you had a bad algorithm.
I would solve this in two passes. Pass 1 is figuring out how many ways there are to get from each partial point you could be to a final answer. Pass 2 is picking a random path.
For pass 1 you build up an array of arrays. By number of numbers left to pick, by what you need them to sum to, how many ways are there to get that answer? (Search for dynamic programming for more on how to do this.)
In pass 2 you go forward. You know at each step how many ways there are to complete your task, and how many there are for each value you can pick. You therefore know the probability of picking each value. So pick a random value in (0, 1), walk through the answers, pick your next number, and proceed.
This general strategy is not just for numbers. It can be used to generate a random sample of anything that you can count using dynamic programming techniques.

multiplying 2D arrays in C#

I am quite new to C# and I need some help with multiplying two numbers from a 2d array. I have this code:
int[,] myArray = { {50,74}, {9,88}, {75,53}, {46,98}, {100,99} };
I need to multiply each pair e.g. 50 * 0.4 and 74 * 0.6, then the two answers from each added together to get my total and the same with the others. Any help would be much appreciated, Thank you
Simply the following:
double[] result = new double[myArray.GetLength(0)];
for(int i = 0; i < myArray.GetLength(0); ++i)
result[i] = myArray[i, 0] * 0.4 + myArray[i, 1] * 0.6;
// result now contains what you need
The first index of multidimensional "2D" arrays refers to row position (each constituent array) and the second index refers to the column position (position in each constituent array).
GetLength(0) means getting the 0th dimension length of your multidimensional array. In this case, it is 5 because there are five rows in your array. On the other hand GetLength(1) will return 2 because there are 2 columns.
First, to go through all pairs, we will need to know how long your array is. To achieve that, we can use myArray.GetLength(0). This will return the total number of elements in the first dimension. Using only Length would return the total number of elements, which is not what we want.
Once we have that, we can loop through all pairs with a classic for loop.
For each pair, we can multiply the first element, myArray[i,0] by 0.4d and the other one, myArray[i,1], by 0.6d. The d here indicate the double data type. int won't do it here, because we have a number with decimals.
We simply add up the result of those two operations and add it as a new entry in our final list.
Here's the code:
int[,] myArray = { { 50, 74 }, { 9, 88 }, { 75, 53 }, { 46, 98 }, { 100, 99 } };
var result = new List<double>();
for (int i = 0; i < myArray.GetLength(0); i++)
{
result.Add(myArray[i,0] * 0.4d + myArray[i,1] * 0.6d);
}
If your final list explicitly needs to be an array, you can use this instead:
int arrayLength = myArray.GetLength(0);
double[] result = new double[arrayLength];
for (int i = 0; i < arrayLength; i++)
{
result[i] = myArray[i, 0] * 0.4d + myArray[i, 1] * 0.6d;
}
It's pretty much the same thing, but we first need to define an array with the size of our collection.

Trying to fix outside the bounds of array by avoiding using if, else, if else and switch statements as I can only user if once

How can I make it so that if the quantityPurchased is greater than or equal to 200 it does not go out of the bounds of array without using an if, if else, else or a switch statement.
static double DeterminePercentage(int quantityPurchased)
{
double[] quantity = { 1, 11, 50, 100, 200 };
double[] discount = { 0, 7.5, 15, 17.5, 20 };
int x = 0;
for (int i = 0; i < quantity.Length; i++)
{
if (quantityPurchased >= quantity[i] && quantityPurchased < quantity[i + 1])
{
x = i;
}
break;
}
return discount[x];
}
Just loop one item less:
for (int i = 0; i < quantity.Length - 1; i++) {
To have the code work for >200 value you can add another dummy item:
double[] quantity = { 1, 11, 50, 100, 200, Int32.MaxValue };
double[] discount = { 0, 7.5, 15, 17.5, 20, 100 };
This will have quantity between 200 and Int32.MaxValue have discount of 20%.
If your 'quantity' array grows and is still sorted, the optimal and generic answer would be to use a BinarySearch for the value 'quantityPurchased'. It will give you the insertion point ie. point at which the key would be inserted into the array.
Use this index to return the appropriate value from the discount array.
I don't provide code as i'm not a C# user but implementation should not be very complicated.
Cheers.
Add Double.MAX_VALUE to the end of your quantity array:
double[] quantity = { 1, 11, 50, 100, 200, Double.MAX_VALUE };
Try this Linq expression.
return discount[discount.IndexOf(quantity.Where(x => x > quantityPurchased).DefaultIfEmpty().Max());

Categories

Resources