This question already has answers here:
Most efficient way to randomly "sort" (Shuffle) a list of integers in C#
(13 answers)
Closed 8 years ago.
I'm trying to create a console application for basic banking functions. I understand how the random number generator works, but I need to set up an array so that the random numbers don't repeat, considering that the random number that is generated represents the users personalized PIN number. How would I implement this into my current code?
class BankAccount
{
private string firstName;
private string lastName;
private int accountNumber;
private decimal balance;
static public int customers = 0;
private int pinNumber;
public decimal Balance
{
get
{
return balance;
}
set
{
if (value >= 0)
balance = value;
else
{
Console.WriteLine("There will be an overdraft fee of $10.00.");
balance = value - 10;
}
}
}
public string FirstName
{
get
{
return firstName;
}
}
public string LastName
{
get
{
return lastName;
}
}
public int AccountNumber
{
get
{
return accountNumber;
}
}
public int PinNumber
{
get
{
return pinNumber;
}
}
public BankAccount(string firstNameValue, string lastNameValue)
{
firstName = firstNameValue;
lastName = lastNameValue;
accountNumber = customers + 1;
Random pin = new Random();
pinNumber = pin.Next(1111, 9999);
Balance = 0;
customers++;
}
public BankAccount()
{
Balance = 0;
customers++;
}
public void Credit(decimal amount)
{
Balance = Balance + amount;
}
public void Debit(decimal amount)
{
if (amount > Balance)
Console.WriteLine("Debit amount exceeded account balance.");
Balance = Balance - amount;
}
public static decimal AverageBalance(BankAccount[] accounts)
{
int count = 0;
decimal total = 0;
for (int i = 0; i < accounts.Length; i++)
{
if (accounts[i] != null)
{
total += accounts[i].Balance;
count++;
}
}
return total / count;
}
}
When you do new Random(), .Net uses the current time as seed. If you do this more than once in a short span of time, you'll generate the same string of random numbers. You might want to just make a static Random variable in BankAccount.
static Random random = new Random();
// later, in the constructor
pinNumber = random.Next(0, 10000); // 0 <= pinNumber < 10000
I changed the range on Next so that it will generate in the full range.
This method initializes an array with distinct random numbers. I didn't test it but it should work.
Create an array, initialize it using the code below and then pass it to your method.
public void SetValues(int[] array)
{
Random randomNumber = new Random();
for (int i = 0; i < array.Length; i++)
{
bool distinctNumber = true;
int number = randomNumber.Next(1, 100);
for (int j = 0; j < i; j++)
{
if (number == array[j])
{
distinctNumber = false;
break;
}
}
if ( distinctNumber )
array[i] = number;
else
--i;
}
}
While I do not understand the concern about repeating digits in a PIN number, the solution should be pretty straight forward. Your array will only contain very few (four) digits, so there is no problem in checking if a number is repeated. The simplest way would be to use the Contains method and only append if the number is unique. Contains will however look at all numbers in the array, so you should either initialize it to something you do not allow (negative values), or build it using a list.
Random rnd = new Random();
var pin = new[] {-1, -1, -1, -1};
for(var i = 0; i < pin.length; i++)
int nextDigit = rnd.Next(0, 10);
while (pin.contains(nextDigit)){ nextDigit + rnd.Next(0, 10); }
pin[i] = nextDigit;
}
By borrowing an extension method from this excellent answer based on the Fisher-Yates shuffle this can be accomplished relatively cleanly.
First define an extension method to shuffle a given List<T>:
public static void Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
Then define the function to generate a PIN consisting of distinct digits:
public IEnumerable GeneratePIN() {
var pinDigits = new List<int>(Enumerable.Range(0,10));
pinDigits.Shuffle();
return pinDigits.Take(4);
}
Or, as an even better option, you can also use a more generalized pin generation function to generate pins of arbitrary lengths from arbitrary types.
public static IEnumerable<T> GeneratePIN<T>(IEnumerable<T> valueRange, int length)
{
var pinValues = new List<T>(valueRange);
pinValues.Shuffle();
return pinValues.Take(length);
}
That said, it's worth mentioning that restricting the PINs to distinct values reduces to number of possible PINs from 10000 to 5040, making it significantly less secure.
Related
This question already has answers here:
Random number generator with no duplicates
(12 answers)
Closed 2 years ago.
We are making our first 2D mobile game in Unity and we need some help. We coded on Java but is also our first time coding C#.
We are making a card game and we want to give to every player a random number, but (here's the important and difficult part for us) we want each random number not to repeat.
For example if we have 5 players and we want to assign a random number from 5 to 10, if number 6 is assigned to player 1 then number 6 cant be assigned to other player.
Here's where we are:
//Player class only have string name and int trabajo
public static void assignRandom(Player jug)
{
int randomnum;
bool aleatorio;
do
{
randomnum= Random.Range(1, 5);
aleatorio = comprobarAleatorio(randomnum);
}
while (aleatorio);
jug.setTrabajo(randomnum);
}
public static bool comprobarAleatorio(int numaleatorio)
{
bool exists = false;
int longitud = jugadoresList.Count;
for (int i = 0; i < 5; i++)
{
if (jugadoresList[i].getTrabajo().Equals(numaleatorio))
{
exists = true;
}
}
}
Then with the int we make a switch and show on screen what type of player you are. But clearly we are doing something wrong because the numbers repeat itselfs, even with 0 (we dont know how).
We appreciate every help. Thank you very much! (and sorry for our english)
One solution is you can generate a list that contains valid numbers and then shuffle them.
Code to shuffle a list from here:
// A Function to generate a
// random permutation of arr[]
static void randomize(int []arr, int n)
{
// Creating a object
// for Random class
Random r = new Random();
// Start from the last element and
// swap one by one. We don't need to
// run for the first element
// that's why i > 0
for (int i = n - 1; i > 0; i--)
{
// Pick a random index
// from 0 to i
int j = r.Next(0, i+1);
// Swap arr[i] with the
// element at random index
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// Prints the random array
for (int i = 0; i < n; i++)
Console.Write(arr[i] + " ");
}
Check the code below :
public static void assignRandom(Player jug) //Player class only have string name and int trabajo
{
int randomnum;
private Random random = new Random(); //Declared an instance of Random
ArrayList randomNumsList = new ArrayList(); //Create arraylist to add random nums
bool aleatorio;
do
{
randomnum= random.next(1, 5); //Changed Random.ranged to random.next();
randomNumsList.add(randomnum); //add the random num to list
aleatorio = comprobarAleatorio(randomnum);
}
while (aleatorio);
if (!randomNumsList.Contains(randomnum) { //Only call setTrabajo if the randomNumsList don't have currently generated randomnum
jug.setTrabajo(randomnum);
}
}
public static bool comprobarAleatorio(int numaleatorio)
{
bool exists = false;
int longitud = jugadoresList.Count;
for (int i = 0; i < 5; i++)
{
if (jugadoresList[i].getTrabajo().Equals(numaleatorio))
{
exists = true;
}
}
return exists;
}
}
Tell me if it helps or if it does not help.
I implemented jarowinkler algorithm. In that algorithm I have taken string source and string target. String target taking as input string source taking as array like source[0]. How can implement jarowinkler algorithm as array list input? Please see below code
public static class JaroWinklerDistance
{
private static readonly double mWeightThreshold = 0.7;
private static readonly int mNumChars = 4;
public static double distance(string source, string target)
{
return 1.0 - proximity(source, target);
}
public static double proximity(string aString1, string aString2)
{
int lLen1 = aString1.Length;
int lLen2 = aString2.Length;
if (lLen1 == 0)
return lLen2 == 0 ? 1.0 : 0.0;
int lSearchRange = Math.Max(0, Math.Max(lLen1, lLen2) / 2 - 1);
bool[] lMatched1 = new bool[lLen1];
bool[] lMatched2 = new bool[lLen2];
int lNumCommon = 0;
for (int i = 0; i < lLen1; ++i)
{
int lStart = Math.Max(0, i - lSearchRange);
int lEnd = Math.Min(i + lSearchRange + 1, lLen2);
for (int j = lStart; j < lEnd; ++j)
{
if (lMatched2[j]) continue;
if (aString1[i] != aString2[j])
continue;
lMatched1[i] = true;
lMatched2[j] = true;
++lNumCommon;
break;
}
}
if (lNumCommon == 0) return 0.0;
int lNumHalfTransposed = 0;
int k = 0;
for (int i = 0; i < lLen1; ++i)
{
if (!lMatched1[i]) continue;
while (!lMatched2[k]) ++k;
if (aString1[i] != aString2[k])
++lNumHalfTransposed;
++k;
}
int lNumTransposed = lNumHalfTransposed / 2;
double lNumCommonD = lNumCommon;
double lWeight = (lNumCommonD / lLen1
+ lNumCommonD / lLen2
+ (lNumCommon - lNumTransposed) / lNumCommonD) / 3.0;
if (lWeight <= mWeightThreshold) return lWeight;
int lMax = Math.Min(mNumChars, Math.Min(aString1.Length, aString2.Length));
int lPos = 0;
while (lPos < lMax && aString1[lPos] == aString2[lPos])
++lPos;
if (lPos == 0) return lWeight;
return lWeight + 0.1 * lPos * (1.0 - lWeight);
}
}
The above code is static class need to implement as array list for that class. Array list must compare as per jaro winkler algorithm. The below code I posting my main class.
class Program
{
static void Main(string[] args)
{
string target;
string[] source1 = new string[]
{
"xyz technology solutions"
};
while (true)
{
Console.Write("Please enter target string: ");
target = Console.ReadLine();
numbersInput.Add(target);
Console.WriteLine("jarowinkler::{0}%", JaroWinklerDistance.proximity(source1[0].ToLower(), target.ToLower()) * 100);
}
}
}}
so i need to implement array list for this code take input from arraylist. Split that list to words. Words compare must compare source and target then it give matching percentage.
You need to provide desired usage example. From what I understood You would like something like:
ArrayList targets = new ArrayList();
targets.Add("word1");
targets.Add("word2");
targets.Add("word3");
double distPercentage = JaroWinklerDistance.meanProximity("sourceWord", targets);
In this case You should just iterate over ArrayList elements and call ".proximity" for each item transformed into string.
By the way, it's better to use
List<string>
instead of ArrayList because You are dealing specifically with strings
I've created a Dice program which rolls a dice dependant on how many times the user wishes to roll. The problem I'm having is being able to calculate how many times each number appears.
Example. Roll Twice - Number is 5.
Number is 4.
I want to be able to count that a 4 and a 5 has being rolled and display it back to the user.
My Code so far
using System;
namespace Dice
{
class Dice
{
private Random randy;
int total;
public static void Main()
{
Dice myDice = new Dice();
myDice.randy = new Random();
Console.Clear();
myDice.manyThrow();
myDice.throwDice();
Console.ReadKey();
}
//*******************************************************
public void throwDice()
{
double count = 0;
while(count != total)
{
count++;
Console.WriteLine("Throw No " + count + " is " + oneThrow());
}
}
//*******************************************************
public int oneThrow()
{
return randy.Next(6) + 1; // pick a number from 1 to 6 and return this
}
public int manyThrow()
{
Console.Write("How many times do you want to roll\t");
total = Convert.ToInt32(Console.ReadLine());
return total;
}
public void countEm()
{
// This is where I intend to place the code
}
}
}
I've being trying to solve this for hours.
Add an array to count roll results:
using System;
namespace Dice
{
class Dice
{
private Random randy;
int total;
int [] rolls = new int[7];
public static void Main()
{
Dice myDice = new Dice();
myDice.randy = new Random();
Console.Clear();
myDice.manyThrow();
myDice.throwDice();
myDice.countEm();
Console.ReadKey();
}
//*******************************************************
public void throwDice()
{
double count = 0;
while (count != total)
{
count++;
Console.WriteLine("Throw No " + count + " is " + oneThrow());
}
}
//*******************************************************
public int oneThrow()
{
var result = randy.Next(6) + 1; // pick a number from 1 to 6 and return this
this.rolls[result]++;
return result;
}
public int manyThrow()
{
Console.Write("How many times do you want to roll\t");
total = Convert.ToInt32(Console.ReadLine());
return total;
}
public void countEm()
{
for (int i = 1; i<7; i++)
{
Console.WriteLine("{0} rolled {1} times", i, rolls[i]);
}
}
}
}
Try this:
static int[] counts = new int[6];
And in oneThrow():
int result = randy.Next(6);
counts[result]++;
return result + 1;
Then in countEm():
for (int i = 0; i < counts.Length; i++)
{
Console.WriteLine("{0}: {1}", i + 1, counts[i]);
}
Keep an array of the possible outcomes count.
class Dice
{
private Random randy;
private int total;
private static const int NUM_SIDES = 6;
private int[] counts;
public Dice()
{
randy = new Random();
counts = new int[ NUM_SIDES ];
}
public static void Main()
{
Dice myDice = new Dice();
Console.Clear();
int throws = myDice.manyThrow(); // need to save the number of throws
myDice.throwDice( throws );
countEm();
Console.ReadKey();
}
public void throwDice( int throws )
{
double count = 0;
while(count != throws)
{
count++;
int result = oneThrow();
counts[ result - 1 ]++; // NOTE: result-1 because arrays are 0-based.
Console.WriteLine("Throw No " + count + " is " + oneThrow());
}
}
// ...
public void countEm()
{
for( int i = 0; i < counts.Count; ++i )
Console.WriteLine( (i+1) + " thrown " + counts[i] + " times." );
}
If you just want to keep track of the count of each number rolled, then you add to your class an array of integers to store the count of each number rolled. The number of the dice roll could be the index into the array.
If you need to keep track of the order of the numbers rolled. Your class could could use a linked list or other ordered list to keep track of the numbers.
This sort of sounds like a homework assignment, so I'll leave the implementation details to the reader :)
Modify the countEM like this:
public void countEm(int numberOfThrows)
{
List<int> Throws = new List<int>(); //Create list, where value of throws will be stored.
for(int i = 0; i < numberOfThrows) //Loop as many times as are given by parameter.
{
Throws.Add(OneThrow()); //Add return value of throw to the list.
}
//Show values in Throws list.
foreach(var diceValue in Throws)
{
Console.WriteLine(string.Format("Value of throw: {0}", diceValue ));
}
}
coutEM should be called with the number of times you want to throw like:
countEM(5);
Above represents 5 throws. The result for example could be filled with:
1, 4, 6, 3, 4
I've become rusty at the brain teaser questions since I have been using fancy IDEs and C#. I have a solution for this question, but my real question is How should I deal with the array size? Assuming I can't use a list. This is written in C#.
The array size could be too small, or just be a waste of memory in its current state. I left out checks for negative coins, etc. so we could just focus on the algorithm. So I want to get rid of this line: double [] minList = new double[1000];
Here's the interview question, return the minimum number of coins that sum to a value (-1 if impossible:
public static Main(string [] args) {
double[] coins = {0.01, 0.05, 0.10, 0.25};
Console.WriteLine(MinNumberOfCoinsToSum(0.24, coins));
}
public static int MinNumberOfCoinsToSum(double sum, double [] coins)
{
double [] minList = new double[1000];
minList[0] = sum;
for (int i = 1; i < minList.Length; i++)
{
double buffer = minList[i-1];
for (int j = 0; j < coins.Length; j++)
{
if(minList[i-1] - coins[j] >= 0.0)
{
buffer = Math.Min(buffer, minList[i-1] - coins[j]);
}
}
minList[i] = Math.Min(minList[i-1], Math.Round(buffer, 2));
if (minList[i] == 0.0)
{
return i;
}
}
return -1;
}
Well Here's an answer taking in what you guys said (though it doesn't return -1 if not found):
private static int MinNumberOfCoinsToSumRecursiveDecimalVersion(decimal sum, decimal [] coins)
{
decimal buffer = sum;
for(int i = 0; i < coins.Length; i++)
{
if(sum - coins[i] >= 0)
{
buffer = Math.Min(buffer, sum - coins[i]);
}
}
if (buffer == sum && sum == 0m)
return 0;
if(buffer == sum && sum != 0m)
{
return Int32.MinValue;
}
int result = 1 + MinNumberOfCoinsToSumRecursiveDecimalVersion(Math.Min(buffer, sum), coins);
return result;
}
However my real is question is how do I deal with an array size when I do not know the size beforehand. Thanks btw for the decimal note... that would have been embarrassing at an interview.
public int MinNumberForCoinSum(int sum, decimal [] coins) {
// I assume there is a custom Util class, but it would be checking null, empty, or any other business requirement
foreach(var verification in VerificationUtil.GetArrayVerifications()) {
verification.Verify(coins);
}
if(sum < 0 ) { Throw new InvalidArgumentException()); }
return MinNumberOfCoinsToSumRecursiveDecimalVersion(sum, coins);
}
The classic solution to deal with unknown array sizes is to use an initial capacity and then start resizing when it gets full. The growth factor is typically 2. This is what most of the growing data structures in the .NET framework do (list, stack, queue etc.)
Forgive if I sound obnoxious: you are way off. The question has nothing to do with resizing arrays. Here is a solution.
public static int numberOfCoins(double[] coins, double sum){
int total = 0;
Arrays.sort(coins);
int amount = (int)(sum*100);//convert to int for precision
for(int i=coins.length-1; i>=0 && amount > 0; i--){
int coin = (int)(100*coins[i]);//convert to int for precision
total+=amount/coin;
amount%=coin;
}
if(amount>0)
return -1;
return total;
}//numberOfCoins
Test the code with
public static void main(String... args){
double[] den = {0.01,.10,.05,.25};
System.out.println(numberOfCoins(den,1.65));
}
EDIT TO HANDLE INT CASE:
In that case I recommend overloading the function. by adding below as well
public static int numberOfCoins(int[] coins, int sum){
int total = 0;
Arrays.sort(coins);
int amount = sum;
for(int i=coins.length-1; i>=0 && amount > 0; i--){
total+=amount/coins[i];
amount%=coins[i];
}
if(amount>0)
return -1;
return total;
}//numberOfCoins
This relates to another code I posted earlier but since this is a different question I decided to make a new post. I'm currently stuck with this code, I'm a c# beginner so this look complicated to me. I've been working on this code that is supposed to get an array from the user, calculate its average then display the results inside show(). I got this working to show the average of the array but now I need to actually display the array each value individually i.e. The 1st value you entered was : 12
The 2nd value you enteres was : 32
Thank guys!
private static int Array()
{
string inValue;
int[] score = new int[10];
int total = 0;
for (int i = 0; i < score.Length; i++)
{
Console.Write("Enter Value {0}: ", i + 1);
inValue = Console.ReadLine();
score[i] = Convert.ToInt32(inValue);
}
for (int i = 0; i < score.Length; i++)
{
total += score[i];
}
return total;
}
Change your GetValues() function to actually return the array of integers, then use the return value in your other functions.
i.e. change GetValues() to:
private static int[] GetValues()
{
string inValue;
int[] score = new int[5];
int total = 0;
for (int i = 0; i < score.Length; i++)
{
Console.Write("Enter Value {0}: ", i + 1);
inValue = Console.ReadLine();
score[i] = Convert.ToInt32(inValue);
}
return score;
}
EDIT: Here is how to use the GetValues() function above in a function to print out all the values. You should be able to work out the rest from here:
private static void PrintArray(int[] scoreArray)
{
for (int i = 0; i < scoreArray.Length; i++)
{
Console.WriteLine("Value #{0}: {1}", i + 1, scoreArray[i]);
}
}
Note how the scoreArray is passed in, as well as how each value is accessed, using scoreArray[i] (where i is a number from 0 to 4 inclusive).
Move int[] score out of GetValues and declare it at the class level making it static:
static int[] score = new int[5];
My next recommendation is that you don't do inside your functions more than what they claim to do from their name; for example, GetValues() should only get the values from user; not calculate totals (as you are doing) because it's misleading; it forces you to look at the implementation to know exactly what it does. Similarly for Show(); if the purpose is to show values entered by user, then call it ShowValues(); If the purpose is to show values entered by user as well as calculate the average, then name it something along the lines of ShowValuesAndAverage()
Here's a complete implementation of your program with my recommendations:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testscores
{
class Program
{
static int[] score = new int[5];
//Get Values
private static void GetValues()
{
string inValue;
for (int i = 0; i < score.Length; i++)
{
Console.Write("Enter Value {0}: ", i + 1);
inValue = Console.ReadLine();
score[i] = Convert.ToInt32(inValue);
}
}
//FIND AVERAGE
private static double FindAverage()
{
double total = 0.0;
for (int i = 0; i < score.Length; i++)
{
total += score[i];
}
double average = total / 5.0;
return average;
}
//Show
static void ShowValuesAndAverage()
{
Console.WriteLine("The values are:");
for (int i = 0; i < score.Length; i++)
{
Console.WriteLine(string.Format("The {0} value you entered was {1}", i + 1, score[i]));
}
Console.WriteLine("The average is: {0}", FindAverage());
}
//Main
static void Main()
{
GetValues();
ShowValuesAndAverage();
Console.ReadKey();
}
}
}
Make one function for GetValues() and return the array. Then pass the array into a AddValues() function, and into Show().
Either that or read up on how to use pointers, but that might be overcomplicating things a little.