ATM program, can't figure out how to break down withdraw amount - c#

First off yes, This is a homework assignment, I've been struggling with it for 3 days, and I can't figure it out.
Basically the problem is to take a decimal amount entered by the user in a text box, I then need to take that number and break it down into currency denominations, $50, $20, $10, $5, $1 and if the amount has a decimal then into
$.25, $.10, $.05, $.01.
And I need to break this down in the lowest amount of denominations possible, for example $100 would be broken down into 2 $50 bills.
Here is what I have so far.
private void btnDispense_Click(object sender, EventArgs e)
{
decimal i;
i = decimal.Parse(txtAmountReq.Text);
decimal totalAmount = Convert.ToDecimal(txtAmountReq);
int[] denomBills = { 50, 20, 10, 5, 1 };
int[] numberOfBills = new int[5];
decimal[] denomCoins = { .25m, .10m, .05m, .01m };
int[] numberOfCoins = new int[4];
//For loop for amount of bills
for (numberOfBills[0] = 0; totalAmount >= 50; numberOfBills[0]++)
{
totalAmount = totalAmount - 50;
}
for (numberOfBills[1] = 0; totalAmount < 20; numberOfBills[1]++)
{
totalAmount = totalAmount - 20;
}
for (numberOfBills[2] = 0; totalAmount < 10; numberOfBills[2]++)
{
totalAmount = totalAmount - 10;
}
for (numberOfBills[3] = 0; totalAmount < 5; numberOfBills[3]++)
{
totalAmount = totalAmount - 5;
}
for (numberOfBills[4] = 0; totalAmount <= 0; numberOfBills[4]++)
{
totalAmount = totalAmount - 1;
}
//For loop for the amount of coins
for (numberOfCoins[0] = 0; totalAmount >= .25m; numberOfBills[0]++)
{
totalAmount = totalAmount - .25m;
}
for (numberOfBills[1] = 0; totalAmount < .10m; numberOfBills[1]++)
{
totalAmount = totalAmount - .10m;
}
for (numberOfBills[2] = 0; totalAmount < .05m; numberOfBills[2]++)
{
totalAmount = totalAmount - .05m;
}
for (numberOfBills[3] = 0; totalAmount < .01m; numberOfBills[3]++)
{
totalAmount = totalAmount - .01m;
}
txt50.Text = Convert.ToString(numberOfBills[0]);
txt20.Text = Convert.ToString(numberOfBills[1]);
txt10.Text = Convert.ToString(numberOfBills[2]);
txt5.Text = Convert.ToString(numberOfBills[3]);
txt1.Text = Convert.ToString(numberOfBills[4]);
txtQuarter.Text = Convert.ToString(numberOfCoins[0]);
txtDime.Text = Convert.ToString(numberOfCoins[1]);
txtNickel.Text = Convert.ToString(numberOfCoins[2]);
txtPenny.Text = Convert.ToString(numberOfCoins[3]);
}
Any help would be greatly appreciated.

This is very famous knapsack type problem.You might want to start exploring from here : https://en.wikipedia.org/wiki/Change-making_problem
The best way to address this problem is to find all possible combinations of change and then find the optimal solution.
Below is the code by karamana I found on codeproject.com :
//find all the combinations
private void findAllCombinationsRecursive(String tsoln,
int startIx,
int remainingTarget,
CoinChangeAnswer answer) {
for(int i=startIx; i<answer.denoms.length ;i++) {
int temp = remainingTarget - answer.denoms[i];
String tempSoln = tsoln + "" + answer.denoms[i]+ ",";
if(temp < 0) {
break;
}
if(temp == 0) {
// reached the answer hence quit from the loop
answer.allPossibleChanges.add(tempSoln);
break;
}
else {
// target not reached, try the solution recursively with the
// current denomination as the start point.
findAllCombinationsRecursive(tempSoln, i, temp, answer);
}
}
}
in order to find optimum solution :
public CoinChangeAnswer findOptimalChange(int target, int[] denoms) {
CoinChangeAnswer soln = new CoinChangeAnswer(target,denoms);
StringBuilder sb = new StringBuilder();
// initialize the solution structure
for(int i=0; i<soln.OPT[0].length ; i++) {
soln.OPT[0][i] = i;
soln.optimalChange[0][i] = sb.toString();
sb.append(denoms[0]+" ");
}
// Read through the following for more details on the explanation
// of the algorithm.
// http://condor.depaul.edu/~rjohnson/algorithm/coins.pdf
for(int i=1 ; i<denoms.length ; i++) {
for(int j=0; j<target+1 ; j++) {
int value = j;
int targetWithPrevDenomiation = soln.OPT[i-1][j];
int ix = (value) - denoms[i];
if( ix>=0 && (denoms[i] <= value )) {
int x2 = denoms[i] + soln.OPT[i][ix];
if(x2 <= target && (1+soln.OPT[i][ix] < targetWithPrevDenomiation)) {
String temp = soln.optimalChange[i][ix] + denoms[i] + " ";
soln.optimalChange[i][j] = temp;
soln.OPT[i][j] = 1 + soln.OPT[i][ix];
} else {
soln.optimalChange[i][j] = soln.optimalChange[i-1][j]+ " ";
soln.OPT[i][j] = targetWithPrevDenomiation;
}
} else {
soln.optimalChange[i][j] = soln.optimalChange[i-1][j];
soln.OPT[i][j] = targetWithPrevDenomiation;
}
}
}
return soln;
}
Link to the original code here

Related

Calculate datagridview rows

I have made a shop app for a school project
it adds goods from goods tab to factor tab
everything is working fine but I don't know how to calculate all - total price rows to make a variable that holds the price you have to pay
EDIT: now I'm getting the error in the picture
int n = dgvfactor.Rows.Count - 1;
dgvfactor.Rows.Add();
dgvfactor.Rows[n].Cells[0].Value = txtFGoodsCode.Text;
dgvfactor.Rows[n].Cells[1].Value = lblgoodsname.Text;
dgvfactor.Rows[n].Cells[2].Value = txtFAmount.Text;
dgvfactor.Rows[n].Cells[3].Value = lblprice.Text;
int amount = int.Parse(txtFAmount.Text);
int price = int.Parse(lblprice.Text);
int total = (amount * price);
lbltotal.Text = total.ToString();
dgvfactor.Rows[n].Cells[4].Value = lbltotal.Text;
var totalPrice = 0;
int rowPrice;
for (int i = 0; i < dgvfactor.Rows.Count; i++)
{
if (int.TryParse(dgvfactor.Rows[i].Cells[4].Value.ToString(), out rowPrice))
{
totalPrice += rowPrice;
}
}
lblpricetopay.Text = totalPrice.ToString();
Sorry If im mistaken here, but can't you just simply use a for-loop ?
var totalPrice = 0;
int rowPrice;
for (int i = 0; i < dgvfactor.Rows.Count; i++) {
// Note the NOT (!) new row...
if (!dgvfactor.Rows[i].IsNewRow) {
if (int.TryParse(dgvfactor.Rows[i].Cells[4].Value.ToString(), out rowPrice))
{
totalPrice += rowPrice;
}
}
}

Finding combinations from a list of objects and sorting them according to property value

I have a List of type CardSlot, each of these CardSlot objects will contain different cards , say , Card1, Card2, Card3 (The number may differ).
Each CardSlot object has maximum quantity of Card1, Card2 and Card3 pre-set. Now, user inputs the amount of Cards required and should get a combination of CardSlot that fulfill the criteria.
For Eg:
List<CardSlot> listCardSlot = new List<CardSlot>();
CardSlot cardSlot1 = new CardSlot();
cardSlot1.Name = "cardSlot1";
cardSlot1.Price = 900;
cardSlot1.Card1 = 2;
cardSlot1.Card2 = 3;
cardSlot1.Card3 = 4;
listCardSlot.Add(cardSlot1);
CardSlot cardSlot2 = new CardSlot();
cardSlot2.Name = "cardSlot2";
cardSlot2.Price = 850;
cardSlot2.Card1 = 3;
cardSlot2.Card2 = 2;
cardSlot2.Card3 = 4;
listCardSlot.Add(cardSlot2);
CardSlot cardSlot3 = new CardSlot();
cardSlot3.Name = "cardSlot3";
cardSlot3.Price = 950;
cardSlot3.Card1 = 4;
cardSlot3.Card2 = 3;
cardSlot3.Card3 = 2;
listCardSlot.Add(cardSlot3);
Now, if user inputs Card1 = 4, Card2 = 5 and Card3 = 4, the end result should be the combination of CardSlot objects with the least possible price.
Can someone please give me a nudge in the right direction?Kindly tell me if something is unclear and I'll try and improve it.
Edit
I have tried finding all the possible combinations that can be in the list using following function:
public static List<List<T>> ItemCombinations<T>(List<T> inputList, int minimumItems = 1)
{
int nonEmptyCombinations = (int)Math.Pow(2, inputList.Count) - 1;
List<List<T>> listOfCombinations = new List<List<T>>(nonEmptyCombinations + 1);
if (minimumItems == 0)
listOfCombinations.Add(new List<T>());
for (int i = 1; i <= nonEmptyCombinations; i++)
{
List<T> thisCombination = new List<T>(inputList.Count);
for (int j = 0; j < inputList.Count; j++)
{
if ((i >> j) % 2 != 0)
thisCombination.Add(inputList[j]);
}
if (thisCombination.Count >= minimumItems)
listOfCombinations.Add(thisCombination);
}
return listOfCombinations;
}
This successfully returns all the possible combinations. However, it still does not take care of the situations where repeated occurance of the same card slot may be the correct choice. For e.g in the above mentioned scenario the correct choice would be 1 X CardSlot1 + 1 X CardSlot2
Edit 2
I reached an intermediate solution and have posted it as an answer, It still does not give me required answer in case of mix and match combinations. Could anyone take a look and suggest something towards that end ?
So i have made a solution for this, must say it's a headburn for me, but have tried something.
CardSlot Class I made:
public class CardSlot
{
public string Name { get; set; } = "";
public double Price { get; set; } = 0;
public int Card1 { get; set; } = 0;
public int Card2 { get; set; } = 0;
public int Card3 { get; set; } = 0;
}
and then the rest follows as:
//your code
//as above
//in the question
listCardSlot.Add(cardSlot3); //your code
ValueChecker(1);
double lowestamount = mycards.Any() ? mycards.Min(item => item.Price) : 0;
MessageBox.Show("You need " + multiplier.ToString() + " " +
ReturnLowestCardSlot(lowestamount).Name);
}
int a = 4, b = 5, c = 4; //User entered values
int multiplier = 0;
List<CardSlot> mycards = new List<CardSlot>();
CardSlot ReturnLowestCardSlot(double lowestPrice)
{
CardSlot cardslot = null;
foreach (var item in mycards)
{
if (item.Price == lowestPrice)
{
cardslot = item;
break;
}
}
return cardslot;
}
void ValueChecker(int increment)
{
multiplier += increment;
foreach (CardSlot item in listCardSlot)
{
if (((multiplier * item.Card1) >= a) &&
((multiplier * item.Card2) >= b) &&
((multiplier * item.Card3) >= c))
{
if (!(mycards.Contains(item)))
mycards.Add(item);
}
}
if (mycards.Count == 0)
ValueChecker(1);
}
The Output I'm getting is:
You need 2 cardSlot1
Hope you could tweak this one somehow to fit your need
EDIT
I see that you want output as 2 cardslot2 which has :
cardSlot2.Card1 = 3;
cardSlot2.Card2 = 2;
cardSlot2.Card3 = 4;
2 x CardSlot2 will give:
cardSlot2.Card1 = 6;
cardSlot2.Card2 = 4;
cardSlot2.Card3 = 8;
But the user's requirement is usercard1 = 4 , usercard1 = 5 & usercard1 = 4.
Here Card2 = 4 is still lesser than usercard2 = 5
I don't see how it fulfils the requirement.
EDIT 2
your comment is right, I didn't though of that. now this will give you the result:
//codes same
//as your question
ValueChecker(1);
double lowestamount = mycards.Any() ? mycards.Min(item => item.Price) : 0;
CardSlot leastcard = ReturnLowestCardSlot(lowestamount, mycards);
double lowestamount2 = listCardSlot.Any() ? listCardSlot.Min(item => item.Price) : 0;
CardSlot lowestcard = ReturnLowestCardSlot(lowestamount2, listCardSlot);
if ((leastcard.Price + lowestcard.Price) > (multiplier * leastcard.Price))
MessageBox.Show("You need " + multiplier.ToString() + " " + leastcard.Name);
else
MessageBox.Show("You need 1 " + leastcard.Name + " and 1 " + lowestcard.Name);
}
And modified ReturnLowestCardSlot
CardSlot ReturnLowestCardSlot(double lowestPrice, List<CardSlot> list)
{
CardSlot cardslot = null;
foreach (var item in list)
{
if (item.Price == lowestPrice)
{
cardslot = item;
break;
}
}
return cardslot;
}
Output:
You need 1 cardSlot1 and 1 cardSlot2
Thanks to Nobody (this sure sounds rude :D ), here is an intermediate (albeit not very optimal) solution I reached. This gives a combination (List of CardSlots) that will be the cheapest.
It does not however provide an answer when the answer should be a heterogenous solution (say 5 X CardSlot1, 3 X CardSlot2, 1 X CardSlot3). Any help towards this will be much appreciated.
static void Main(string[] args)
{
//Some Code
// Get user input card1, card2, card3
List<List<CardSlot>> validCombination = GetAllCombinations(card1, card2, card3, listCardSlot);
List<CardSlot> CheapestCombo = GetLeastPricedCombination(validCombination);
//Here I get the cheapest homogenous combination
}
private static List<List<CardSlot>> GetAllCombinations(int card1, int card2, int card3, List<CardSlot> listCardSlot)
{
var listOfCombinations = ItemCombinations(listCardSlot, 1);
List<List<CardSlot>> validCombination = new List<List<CardSlot>>();
int multiplier;
foreach (List<CardSlot> combination in listOfCombinations)
{
multiplier = 1;
if (CheckMaterialSum(combination, card1, card2, card3, ref multiplier))
{
validCombination.Add(combination);
}
else
{
GetMultiplierCombination(combination, card1, card2, card3, ref validCombination, ref multiplier);
}
}
return validCombination;
}
private static bool CheckMaterialSum(List<CardSlot> combination, int card1, int card2, int card3, ref int multiplier)
{
int sumcard1 = multiplier * (combination.Sum(comb => comb.Card1));
int sumcard2 = multiplier * (combination.Sum(comb => comb.Card2));
int sumcard3 = multiplier * (combination.Sum(comb => comb.Card3));
if (sumcard1 >= card1 && sumcard2 >= card2 && sumcard3 >= card3)
{
return true;
}
return false;
}
private static void GetMultiplierCombination(List<CardSlot> combination, int card1, int card2, int card3, ref List<List<CardSlot>> validCombination, ref int multiplier)
{
while (!CheckMaterialSum(combination, card1, card2, card3, ref multiplier))
{
multiplier += 1;
}
List<CardSlot> interMediateCombo = new List<CardSlot>();
for (int i = 0; i < multiplier; i++)
{
interMediateCombo.AddRange(combination);
}
validCombination.Add(interMediateCombo);
}
private static List<CardSlot> GetLeastPricedCombination(List<List<CardSlot>> validCombination)
{
List<CardSlot> cheapestCombo = new List<CardSlot>();
int leastPrice = int.MaxValue;
int priceTotal;
//Find better way for finding least priced combination
foreach (List<CardSlot> combination in validCombination)
{
priceTotal = combination.Sum(combo => combo.Price);
if (priceTotal < leastPrice)
{
leastPrice = priceTotal;
}
}
foreach (List<CardSlot> combination in validCombination)
{
priceTotal = combination.Sum(combo => combo.Price);
if(priceTotal == leastPrice)
{
cheapestCombo.AddRange(combination);
break;
}
}
return cheapestCombo;
}

Different output between Emulator and Samsung Galaxy S3 with Xamarin

I am having issues with the output of the the result of a math calculation. I have a basic average of an array of double and I assign the result to a Label object, using the ToString() method. When I emulate the average, the label shows the correct value of 15.96 for example, but the same average of the same array, on my Galaxy S3 shows 159.6.
Is there anyone who know what's up and what can I do to make the S3 show the correct value?
Thank you all!
EDIT: passing the result to a label and adding the label to the grid:
double result = Math.Round(NP122.DoAverage(parameters), 2);
CustomLabel label = new CustomLabel();
label.ColNo = grid.ColumnDefinitions.IndexOf(c);
label.FontSize = 25;
label.TextColor = Color.Green;
if (result.ToString() == "NaN")
label.Text = "0";
else
label.Text = result.ToString();
label.IsVisible = true;
for (int i = 0; i < numberOfRows.Length + 2; i++) {
if(i == numberOfRows.Length +1)
Grid.SetRow(label, i);
}
Grid.SetColumn(label, grid.ColumnDefinitions.IndexOf(c));
listaRez.Add(label);
foreach (CustomLabel a in listaRez)
{
if (a.ColNo == grid.ColumnDefinitions.IndexOf(c))
{
grid.Children.Add(a);
}
}
EDIT 2: Custom function for NP122.DoAverage:
public static class NP122
{
public static double Vx, sx, Xm, kn, Xkinf, Xksup;
public static double sum;
public static double sumaProvizorie;
public static double[] valoriKn = new double[25];
public static double ValoareCaracteristicaSuperioara(double[] l)
{
Vx = 0;
sx = 0;
Xm = 0;
kn = 0;
Xkinf = 0;
Xksup = 0;
sum = 0;
sumaProvizorie = 0;
valoriKn[0] = 0;
//more here
valoriKn[24] = 0.35;
if (l.Length < 2 )
{
Xksup = 0;
Xkinf = 0;
}
else
{
Xm = (l.Sum()) / (l.Length);
for (int j = 0; j < l.Length; j++)
{
sumaProvizorie = Math.Round(Math.Pow((l[j] - Xm), 2), 2);
sum += sumaProvizorie;
}
kn = valoriKn[l.Length - 1];
double elements = (1.00 / (l.Length - 1));
double putere = sum;
sx = Math.Round(Math.Sqrt(elements * putere), 4);
Vx = sx / Xm;
Xksup = Xm * (1 + kn * Vx);
Xkinf = Xm * (1 - kn * Vx);
}
return Xksup;

Need help assigning values to array C# (noob)

I am trying to write a method that will assign each day of the year a value for rainfall after checking if it rain at all.
So I want my days array to contain 365 random numbers below 28, 3/4 of them being 0.
note: I have a global random variable
static void Generate()
{
int[] days = new int[365];
int going_to_rain = 0;
for (int i = 0; i < days.Length; i++)
{
going_to_rain = randomValue.Next(3);
if (going_to_rain == 1)
{
days[i] = randomValue.Next(1, 28);
}
else
{
days[i] = 0;
}
}
Console.WriteLine(days);
}
You can create an array that its first 274 cells are 0, and the others are random.
Afterward you shuffle this array randomally:
int[] days = new int[365];
int i = 0;
for(i = 0;i < 274;++i)
{
days[i] = 0;
}
for (i = 275;i < 365; ++i)
{
days[i] = randomValue.Next(1,28);
}
//Shuffle
for (i = 0; i < 365; ++i)
{
int randVal = randomValue.Next(364);
int tmp = day[randVal];
day[randVal] = day[i];
day[i] = tmp;
}

Breaking down currency in c#

i'm trying to get this program to break down a user defined amount of dollars into the fewest possible bills. i don't think my for loops are running because if i put a writeline line in them it doesn't show up when i run it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication13
{
class Program
{
static void Main(string[] args)
{
Console.Write("Enter the amount of money: $");
int totalAmount = Convert.ToInt32(Console.ReadLine());
calculateNumberOfBills(totalAmount);
}
static void calculateNumberOfBills(int totalAmount)
{
int[] denominations = { 20, 10, 5, 1 };
int[] numberOfBills = new int[4];
for (numberOfBills[0] = 0; totalAmount < 20; numberOfBills[0]++)
{
totalAmount = totalAmount - 20;
}
for (numberOfBills[1] = 0; totalAmount < 10; numberOfBills[1]++)
{
totalAmount = totalAmount - 10;
}
for (numberOfBills[2] = 0; totalAmount < 5; numberOfBills[2]++)
{
totalAmount = totalAmount - 5;
}
for (numberOfBills[3] = 0; totalAmount <= 0; numberOfBills[3]++)
{
totalAmount = totalAmount - 1;
}
Console.WriteLine("Number of twenties" + numberOfBills[0]);
Console.WriteLine("Number of tens" + numberOfBills[1]);
Console.WriteLine("Number of fives" + numberOfBills[2]);
Console.WriteLine("Number of ones" + numberOfBills[3]);
}
}
}
Take a look at this:
for (numberOfBills[0] = 0; totalAmount >= 20; numberOfBills[0]++)
{
totalAmount = totalAmount - 20;
}
for (numberOfBills[1] = 0; totalAmount >= 10; numberOfBills[1]++)
{
totalAmount = totalAmount - 10;
}
for (numberOfBills[2] = 0; totalAmount >= 5; numberOfBills[2]++)
{
totalAmount = totalAmount - 5;
}
for (numberOfBills[3] = 0; totalAmount > 0; numberOfBills[3]++)
{
totalAmount = totalAmount - 1;
}
This is a homework question, right?
for (numberOfBills[0] = 0; totalAmount < 20; numberOfBills[0]++)
make it
for (numberOfBills[0] = 0; totalAmount >= 20; numberOfBills[0]++)
and try again :)
The center piece is the condition where the loop should run.
Sorry, at this point this is "not a real question" and should most probably be tagged as homework.
Your "smaller than" comparisons should be changed to "greater than" comparisons and you're good to go with your solution. What's happening now is an integer overflow, eventually causing your first for-loop , which was infinitely looping until then to break.
There are easier ways to solve your problem, try it with a single loop and the modulo operator).
in your "for" loops you have inverse condition => totalAmount < 20 means that it executes loop while totalAmount is less than 20 - that is the opposite of what you want.
Change it to
for(...;totalAmount > 20; ...)
Try this, a bit of less code
int amt = 73;
Dictionary<int, int> dic = new Dictionary<int, int>() {{20,0},{10,0},{5,0},{1,0}};
int[] keys =new int[dic.Count];
dic.Keys.CopyTo(keys, 0);
foreach (int i in keys)
{
if (amt >= i)
{
dic[i] = amt / i;
amt = amt % i;
}
}

Categories

Resources