How do I replace an array element within an if statement? C# - c#

This is the second version of this code I've gone through as the first version ran too quickly for the Random function to work properly. I'm trying to make sure none of the randomly generated numbers are the same and if they are replace them in the array but it's not letting me call the array. Can someone tell me what I'm doing wrong?
using System;
using System.Timers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp4
{
class Program
{
public static Timer aTimer;
static void Main(string[] args)
{
//Create three different random integers and store them
Random rnd = new Random();
int RandA = rnd.Next(0, 26);
int RandB = rnd.Next(0, 26);
int RandC = rnd.Next(0, 26);
//Turn those three variables into an array
int[] RandArray = { RandA, RandB, RandC };
//Make sure there are no duplicates
if (RandArray[0] == RandArray[1])
{
int RandArray[0] = rnd.Next(0, 26);
}
if (RandArray[1] == RandArray[2])
{
int RandArray[1] = rnd.Next(0, 26);
}
if (RandArray[2] == RandArray[0])
{
int RandArray[2] = rnd.Next(0, 26);
}
//Print out all three values seperately
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Value of: {1}", i, RandArray[i]);
continue;
}
Console.ReadKey();
}
}
}

Well, I would potentially alter your approach.
public static class Randomizer
{
private static const generator = new Random();
public static int Generate(int minimum, int maximum) => generator.Next(minimum, maximum);
}
Then I would do the following:
public static class BuildRandom
{
public IEnumerable<int> FillCollection(int capacity)
{
for(int index = 0; index < capacity; index++)
yield return Randomizer.Generate(0, 26);
}
public static int GetRandomNumber() => Randomizer.Generate(0, 26);
}
Then I would simply do the following.
// Build Collection
var randomized = BuildRandom.FillCollection(5);
// Remove Duplicates
var filter = randomized.Distinct();
while(filter.Count != randomized.Count)
{
var value = BuildRandom.GetRandomNumber();
if(!filter.Any(number => number == value))
filter.Concat(new { value });
}

int RandArray[0] = is a syntax error. Try RandArray[0] =

Related

Array of random numbers in C# / .NET framework

I am trying to create a lottery program that would generate random numbers between 1 - 35. These numbers need to be unique as well, they can not be the same. With C#, running on the .NET framework.
I have been trying to get it to work, but I keep getting errors and I don't understand why. I have been googling and looking at videos - still I don't get what I am doing wrong.
This is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace help
{
public partial class Form1 : Form
{
// The array
TextBox[] TextBoxArray;
// the counter on how many times u pressed btn
private int counter = 1;
public Form1()
{
InitializeComponent();
this.StartPosition = FormStartPosition.CenterScreen;
// The text boxes name 1 - 7
//TextBoxArray = new TextBox[] { Nr1, Nr2, Nr3, Nr4, Nr5, Nr6, Nr7 };
}
private void button1_Click(object sender, EventArgs e)
{
NrOfPull.Text = counter.ToString();
counter++;
// Keep getting an error
// Error CS0443 Syntax error; value
// they are talking about the Parse(TextBoxArray[].Text);
int number = int.Parse(TextBoxArray[].Text);
// Loop through
Random rand = new Random();
for (int i = 0; i < number; i++)
{
// Generate a alotter by turn
int storedNumber;
int[] randomLottoRow = new int[7];
for (int row = 0; row < 7; row++)
{
do
{
storedNumber = rand.Next(1, 35);
}
while (randomLottoRow.Contains(storedNumber));
randomLottoRow[row] = storedNumber;
}}
/*
* This will only let me generate numbers.. but wanna use Parse...
Random generator = new Random();
for (int x = 0; x < 7; x++)
{
TextBoxArray[x].Text = generator.Next(1, 35).ToString();
Console.WriteLine(TextBoxArray[x].Text = generator.Next(1, 35).ToString());
}
*/
}
}
}
Would love to get feedback on what I am doing wrong Thank you so much :)
This is one way of generating random sequences of numbers:
using System.Linq;
public static class Ex
{
static readonly Random rng = new Random();
/// <summary>
/// Randoms the sequence.
/// </summary>
/// <param name="maxValue">The maximum number in drawing.</param>
/// <param name="count">The number of numbers drawn.</param>
public static int[] Lottery(int maxValue, int count)
{
return Enumerable.Range(1, maxValue+1)
.OrderBy((x)=>rng.NextDouble())
.Take(count).ToArray();
}
}
static class Program
{
static void Main(string[] args)
{
var seq = Ex.Lottery(35, 8);
// draw 8 numbers ranging between 1-35
Console.WriteLine(string.Join(",", seq));
// 14,24,1,3,25,5,31,30
}
}
Here you go:
private TextBox[] TextBoxArray;
private Random rand = new Random();
public Form1()
{
InitializeComponent();
TextBoxArray = new TextBox[] { Nr1, Nr2, Nr3, Nr4, Nr5, Nr6, Nr7 };
}
private void button1_Click(object sender, EventArgs e)
{
int[] picks = Enumerable.Range(1, 35).OrderBy(x => rand.NextDouble()).Take(7).ToArray();
for(int i=0; i<picks.Count(); i++)
{
TextBoxArray[i].Text = picks[i].ToString();
}
}
This uses the same approach as John Alexiou for generating the random lottery pick numbers, but then also shows you how to put those numbers into your TextBoxes.

Weighted Job Scheduler - Retrieve Job Details

I am learning C# and want to created a weighted job scheduler.
The max profit is working fine. But I need to be able to get the JobIDs associated with it so I am trying to save it in an array jobsId, similar to this implementation in C++: https://onlinegdb.com/a9wx3nHoN.
But then in this snippet, I am getting an error: Wrong number of indices inside []; expected 2
if (profitSum > dp[i-1]) {
dp[i] = profitSum;
jobsId[i,0] = jobsId[task]; // Problem is here
jobsId[i].Append(jobs[i].id).ToArray(); //And here
}
What am I doing wrong? Please help, thanks!
Codes can be accessed here:
https://rextester.com/NXM85235
Alternatively, here is my entire snippet:
using System.IO;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;
class Program
{
public int JobScheduling(int[] startTime, int[] endTime, int[] profit) {
var jobs = startTime
.Select((_, i) => new // create custom obj
{
id = i,
s = startTime[i],
e = endTime[i],
p = profit[i],
}
)
.OrderBy(x => x.e) // sort by end-time
.ToArray();
int[] dp = new int[jobs.Length];
int [,] jobsId = new int[,] {{jobs[0].id}};
int profitSum = jobs[0].p;
int task = -1;
dp[0] = jobs[0].p;
for (var i = 1; i < jobs.Length; i++) {
for (var j = i-1; j >= 0; j--) {
if (jobs[j].e <= jobs[i].s) {
task = j;
break;
}
}
if (task != -1) {
profitSum += dp[task];
}
if (profitSum > dp[i-1]) {
dp[i] = profitSum;
jobsId[i,0] = jobsId[task]; // Problem is here
jobsId[i].Append(jobs[i].id).ToArray();
}
}
// Need to implement this
for (var iter = 0; iter < jobsId.Length; iter++) {
Console.WriteLine(jobsId[iter,0]);
}
return dp[jobs.Length-1];
}
public static void Main(string[] args)
{
int[] startTime = { 1,3,6,2 };
int[] endTime = { 2,5,7,8 };
int[] profit = { 50,20,100,200 };
// Creating object
Program job = new Program();
Console.WriteLine(job.JobScheduling(startTime, endTime, profit));
}
}
int [,] jobsId = new int[,] {{jobs[0].id}};
The multi-dimensional 3d array that you are using has a fixed size .i.e. only one. You can't add any more elements to that array. Instead, try using List< List < int > >.
jobsId[i,0] = jobsId[task]; // problem here
Here jobsId is a 2d-array. You can't access the individual rows. You can only access elements within. For this too you need to create an array of array .i.e List< List < int > >.
And I could not figure out why are trying to get an array here.
jobsId[i].Append(jobs[i].id).ToArray();

No errors in Visual Studio, Code Executes but something not right C# (updated! problem in String.Insert)

I'm writing a program for schoolwork, that's supposed to generate a 10 000 "movie" list. A single "movie" consist of a string in a form "moviename year director". I say "movie" because movie name and director are supposed to be randomly generated with letters from a-z.
I wrote the following logic to generate one such "movie". Movie name and director are random letter combination in length between 4-10 charachters. Code gives no errors in visual studio, executes, but shows blank. If I wrote correctly, then this code should generate one such string and print it, yet console is blank.
Do while loop is there to check if, however unlikely, there is a double item in the List (this is for when I do the 10 000 version).
In short, I dont understand what am I doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
namespace Experiment
{
class Program
{
static void Main(string[] args)
{
Movies();
Console.ReadKey();
}
public static void Movies()
{
List<string> movieList = new List<string>();
bool check = false;
do
{
string movie = "";
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
movie.Insert(0, " ");
movie.Insert(0, Convert.ToString(GetYear()));
movie.Insert(0, " ");
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
if (movieList.Contains(movie))
{
check = false;
}
else
{
movieList.Add(movie);
check = true;
}
} while (check == false);
Console.WriteLine(movieList[0]);
}
public static Random _random = new Random();
public static char GetLetter()
{
int num = _random.Next(0, 26);
char let = (char)('a' + num);
return let;
}
public static int GetNum()
{
int num = _random.Next(4, 11);
return num;
}
public static int GetYear()
{
int num = _random.Next(1920, 2020);
return num;
}
}
}
Strings are immutable, so calling the Insert() method on the movie string doesn't do anything to the current movie variable. Instead it returns the new string.
You are however better off changing the movie type from string to StringBuilder, which is a dynamically allocated buffer of characters, so your example becomes:
using System;
using System.Text;
using System.Collections.Generic;
namespace sotest
{
class Program
{
static void Main(string[] args)
{
Movies();
Console.ReadKey();
}
public static void Movies()
{
List<string> movieList = new List<string>();
bool check = false;
do
{
StringBuilder movie = new StringBuilder();
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
movie.Insert(0, " ");
movie.Insert(0, Convert.ToString(GetYear()));
movie.Insert(0, " ");
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
if (movieList.Contains(movie.ToString()))
{
check = false;
}
else
{
movieList.Add(movie.ToString());
check = true;
}
} while (check == false);
Console.WriteLine(movieList[0]);
}
public static Random _random = new Random();
public static char GetLetter()
{
int num = _random.Next(0, 26);
char let = (char)('a' + num);
return let;
}
public static int GetNum()
{
int num = _random.Next(4, 11);
return num;
}
public static int GetYear()
{
int num = _random.Next(1920, 2020);
return num;
}
}
}
The problem is that you are using movie.Insert incorrectly.
If you read the documentation for String.Insert it says
https://learn.microsoft.com/en-us/dotnet/api/system.string.insert?view=netframework-4.8
Returns a new string in which a specified string is inserted at a
specified index position in this instance
public string Insert (int startIndex, string value);
So it returns a new String, it does not amend the existing one. So you would need to do.
movie = movie.Insert(0, Convert.ToString(GetYear()));
However, I must also say that using String.Insert in this way is not the best approach.
You should instead look at using the StringBuilder class. It is very efficient when you want to amend strings (which are immutable objects).
You might want to read parts of this to help you understand. If you scroll down then it also suggests StringBuilder.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/
Insert() method is used to return a new string from the specified string at a specified index position. In your case, you are not capturing the updated string.
The best approach to solve this is through using StringBuilder object. Please note that StringBuilder object is much efficient rather than playing with immutable string.

Generate 4 differents numbers randomly

I am a novice in Xamarin ,
I want to generate randomly 4 numbers which are in a list and this 4 numbers must be different .
In the example below I have a list of Ids and I am trying to pick 4 id randomly in the list and those 4 Ids must be each differents.
Here is my methode, I cannot see how I can continue and make it simple :
public MyWordsList()
{
InitializeComponent();
Dictionary<int, int> WordId = new Dictionary<int, int>();
int u= 0;
// TestAnswer.IsVisible = false;
foreach (var w in mywords)
{
WordId[u] = w.ID;
u++;
}
Random rnd = new Random();
// this is not ok because I can have the same number
word11.Text = WordsList[rnd.Next(1, 20)];
word12.Text = WordsList[rnd.Next(1, 20)];
word13.Text = WordsList[rnd.Next(1, 20)];
word14.Text = WordsList[rnd.Next(1, 20)];
}
If you have a better solution, I will take.
Thanks
You can write a short generic function which picks X amount of random and unique items from a specified collection and returns them:
private static IEnumerable<T> GetUniqueRandomItems<T>(int count, IList<T> allItems)
{
if (new HashSet<T>(allItems).Count < count)
{
throw new ArgumentException(nameof(allItems));
}
Random random = new Random();
HashSet<T> items = new HashSet<T>();
while (items.Count < count)
{
T value = allItems[random.Next(0, allItems.Count)];
items.Add(value);
}
return items;
}
You can later use it like this:
string[] randomIds = GetUniqueRandomItems(4, WordsList).ToArray();
word11.Text = randomIds[0];
word12.Text = randomIds[1];
word13.Text = randomIds[2];
word14.Text = randomIds[3];
call a method like the following:
private int CreateUniqueRandom(int min, int max, ICollection<int> existingNums)
{
var rnd = new Random();
var newNum = rnd.Next(min, max);
while (existingNums.Contains(newNum))
newNum = rnd.Next(min, max);
return newNum;
}
Passing through a list of the numbers that you have created so far
You probably won't need this, but just to show a method of unique random number generation with no duplicate check:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var randoms = GenerateRandoms(10, 1, 10).OrderBy(v => v);
foreach (var random in randoms)
{
Console.WriteLine(random);
}
Console.ReadLine();
}
private static int[] GenerateRandoms(int randomCount, int min, int max)
{
var length = max - min + 1;
if (randomCount > length) { throw new ArgumentException($"Cannot generate {randomCount} random numbers between {min} and {max} (inclusive)."); }
var values = new List<int>(length);
for (var i = 0; i < length; i++)
{
values.Insert(i, min + i);
}
var randomGenerator = new Random();
var randoms = new List<int>();
for (var i = 0; i < randomCount; i++)
{
var val = randomGenerator.Next(0, values.Count);
randoms.Add(values[val]);
values.RemoveAt(val);
}
return randoms.ToArray();
}
}
}

Foreach list search without repetition [duplicate]

This question already has answers here:
C# creating a list of random unique integers
(6 answers)
Closed 4 years ago.
How I can put randomize numbers to list without repetition?
Here's my code, sometimes the numbers are repeated but I do not know why
Random losowa = new Random();
List<int> pula = new List<int>();
private void LosujPytania()
{
int a = losowa.Next(1,20);
while (pula.Count < 10)
{
foreach (int i in pula)
{
if (a == i)
{
a = losowa.Next(1, 20);
break;
}
}
pula.Add(a);
}
}
Code below create list of numbers without repetition. Key to resolve problem is use list.Contains().
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var list = new List<int>();
var rand = new Random();
while(list.Count <10)
{
var number = rand.Next(1,20);
if(! list.Contains(number))
list.Add(number);
}
foreach(var item in list)
Console.WriteLine(item);
}
}
You should check if this number was previously generated and generate another number if it is repeated.
Change this:
private void LosujPytania()
{
int a = losowa.Next(1,20);
while (pula.Count < 10)
{
foreach (int i in pula)
{
if (a == i)
{
a = losowa.Next(1, 20);
break;
}
}
pula.Add(a);
}
}
by this:
private void LosujPytania()
{
int a = losowa.Next(1,20);
pula.Add(a);
while (pula.Count < 10)
{
do
{
a = losowa.Next(1, 20);
} while(pula.Contains(a));
pula.Add(a);
}
}
You can do this, you can check my comments additional details:
private static void LosujPytania()
{
Random losowa = new Random();
List<int> pula = new List<int>();
int a = losowa.Next(1,20);
while (pula.Count < 10)
{
//Your code is not really checking for duplicates so I replace it with boolean condition below
//foreach (int i in pula)
//{
// if (a == i)
// {
// a = losowa.Next(1, 20);
// break;
// }
//}
a = losowa.Next(1, 20);
//This will check if your list doesn't contain your numbers yet before adding to make sure everything is unique
if (!pula.Contains(a))
pula.Add(a);
}
}
if you want numbers without replications,
I think it will be better to use HashSet.
Random losowa = new Random();
HashSet<int> pula = new HashSet<int>();
while (pula.Count < 10)
{
pula.Add(r.Next(20));
}
or if you really need the List, you can use a helper method
something like:
private void LosujPytania()
{
Random losowa = new Random();
List<int> pula = new List<int>();
int a = losowa.Next(1, 20);
pula.AddRange(Get10RandomNumbers(losowa));
}
private IEnumerable<int> Get10RandomNumbers(Random losowa)
{
HashSet<int> ints = new HashSet<int>();
while (ints.Count < 10)
{
ints.Add(losowa.Next(20));
}
return ints;
}
A simple 2 lines solution:
var rnd = new Random();
var list = Enumerable.Range(0, 20).OrderBy(x => rnd.Next()).Take(10).ToList();
Explanation:
Enumerable.Range(0, 20) will return an IEnumerable<int> with the numbers 0 to 19.
OrderBy(x => rnd.Next()) will sort the values to a random order.
Take(10) will return the first 10 numbers from the IEnumerable<int>,
and finally, ToList() will return a list of these int values.

Categories

Resources