Stuck on C# code - c#

Ok so im completely lost i have never done any kind of c# coding and am trying to learn.
The task I have to do:
Calculate the parking fee for each customer, and put that out together with the hours parked.
There is a maximum parking fee of $20.00.
Calculate and output the average of the parking fees.
Overall Tasks:
Read the data file ‘hours.txt’ into an array of data type integer
Calculate the parking fee for each customer and output the hours parked and the parking fee.
Calculate the average parking fee
Output the average parking fee (formatted to 2 decimal places)
for now, declare your array and assign the numbers as shown below.
This is what i have come up with so far.
And plaese remember that like i said im very NEW to this and I´m looking for some guidence.
int[] hours;
hours = new int[30];
const decimal HOURLY_RATE = 2.50m;
const decimal MAX_FEE = 20.00m; //Capped at S20.00
decimal parkFee;
decimal parkingCost = HOURLY_RATE;
int[] hoursArray = { 8, 24, 9, 7, 6, 12, 10, 11, 23, 1, 2, 9, 8, 8, 9, 7, 9, 15, 6, 1, 7, 6, 12, 10, 11, 23, 1, 2, 9, 8 };
Console.WriteLine("Hours " + "Parking Fee ");
int total = 0;
double average = 0;
for (int index = 0; index < hours.Length; index++)
if (parkingCost > MAX_FEE)
{
parkFee = parkingCost * MAX_FEE;
Console.WriteLine("Hours " + "Parking Fee ");
}
average = (double)total / hours.Length;
Console.WriteLine("Average = " + average.ToString("N2"));
Console.ReadKey();`

You never calculate your fee before you check if it's bigger than the maximum rate. Therefore you don't see any results, since your fee is never calculated (always 0). Also, you miss some braces for the for loop, so it will not loop through your code under the for loop.
A quick fix:
int[] hours = new int[30]{ 8, 24, 9, 7, 6, 12, 10, 11, 23, 1, 2, 9, 8, 8, 9, 7, 9, 15, 6, 1, 7, 6, 12, 10, 11, 23, 1, 2, 9, 8 };
const decimal HOURLY_RATE = 2.50m;
const decimal MAX_FEE = 20.00m; //Capped at S20.00
Console.WriteLine("Hours and fee's parked per person");
decimal total = 0;
for (int index = 0; index < hours.Length; index++)
{
decimal parkFee = HOURLY_RATE * hours[index];
if (parkFee > MAX_FEE)
parkFee = MAX_FEE;
total += parkFee;
Console.WriteLine("Hours: {0}. Parking Fee: {1}", hours[index], parkFee);
}
decimal average = total / hours.Length;
Console.WriteLine("Average = {0}", average.ToString("N2"));
Console.ReadKey();
I also cleaned up some variables that are double and moved some variable declarations to the place where they are calculated. I also made a decimal value out of your total variable. You were using int which will only give you whole numbers which will lead to an inaccurate total amount of fee's. By using decimal you solve this problem. Lastly, I also changed you average value to a decimal, which seems to make more sense in this case since you use decimal for all variables so far.
EDIT: since you specifically ask for reading the array from a text file. This is how you create your hours array from your text file instead of declaring it in code:
const decimal HOURLY_RATE = 2.50m;
const decimal MAX_FEE = 20.00m; //Capped at S20.00
// See http://stackoverflow.com/a/556142/7397065 why you should use # here
string path = #"C:\your\path\here.txt";
string stringFromFile = File.ReadAllText(path);
// Since your array is delimited on whitespace, use null as parameter
// You also need int's instead of string. So directly convert the results to int.
// We now make a List(), which also gives you more flexibility.
// Want to change your delimiter? See https://msdn.microsoft.com/en-us/library/b873y76a(v=vs.110).aspx
List<int> hours = stringFromFile.Split(null).Select(int.Parse).ToList();
Console.WriteLine("Hours and fee's parked per person");
decimal total = 0;
// Let's change this to a foreach. That's clearer to work with.
foreach (int parkingTime in hours)
{
decimal parkFee = HOURLY_RATE * parkingTime;
if (parkFee > MAX_FEE)
parkFee = MAX_FEE;
total += parkFee;
Console.WriteLine("Hours: {0}. Parking Fee: {1}", parkingTime, parkFee);
}
// We have to use .Count now, since we use List()
decimal average = total / hours.Count;
Console.WriteLine("Average = {0}", average.ToString("N2"));
Console.ReadKey();

Easiest solution would be to just iterate through hoursArray and check for the lowest value between each park period times rate and maximum fee. Then just add this to your total fees and after all divide this by your array's length :
for ( int i = 0; i < hoursArray.Length; ++i )
{
// get the lowest value
parkFee = Math.Min(hoursArray[i] * HOURLY_RATE, MAX_FEE);
// add to total fees
total += parkFee;
// print current iteration state
Console.WriteLine("Hours : {0}, Parking fee : {1}", hoursArray[i], parkFee);
}
// calculate the average
average = total / (double)hoursArray.Length;
// print results
Console.WriteLine("Average : {0}", average.ToString("N2"));

Related

Return number from 1 to 10 based on the number size

Let's say I have some random numbers between 1 and 20 like this:
{3,7,14,8,17,6,12}
Now, I need to obtain a number between 1 and 10 for every number, based on the number size.
So for example the smaller number must return 1 and the greatest must return 10.
How can I achieve this?
EDIT
Here the solution that suits with some small changes, I found here : https://stackoverflow.com/a/7989299/16356535
List<int> list = new List<int> { 3, 7, 14, 8, 17, 6, 12 };
int scaleMin = 10; //the normalized minimum desired
int scaleMax = 1; //the normalized maximum desired
int valueMax = list.Max();
int valueMin = list.Min();
int valueRange = valueMax - valueMin;
int scaleRange = scaleMax - scaleMin;
IEnumerable<int> normalized =
list.Select(i =>
((scaleRange * (i - valueMin))
/ valueRange)
+ scaleMin);
Console.WriteLine(normalized);
You almost have it.
List<int> list = new List<int> { 3, 7, 14, 8, 17, 6, 12 };
int scaleMin = 1; //the normalized minimum desired
int scaleMax = 10; //the normalized maximum desired
int valueMax = list.Max();
int valueMin = list.Min();
int valueRange = valueMax - valueMin;
int scaleRange = scaleMax - scaleMin;
IEnumerable<int> normalized =
list.Select(i =>
((scaleRange * (i - valueMin)) / valueRange) + scaleMin);
Console.WriteLine(string.Join(',', normalized));

Find a number in a list of similar numbers by x%

I have the the following list of numbers in which I need to find a number which meets the 5% difference between min and max value of the closest matched numbers and calculate its average.
Input List
[2500, 2510, 7000, 7500, 1000, 1200, 2460]
Expected Output
2500+2510+2460 / 3 = 2490
Here min 2460, max 2510 and difference is 50 which is lesser than 5% of 2460 i.e 123
var numbers = new int[]{ 2500, 2510, 7000, 7500, 1000, 1200, 2460};
var orderedNumbers = numbers.OrderBy(x => x).ToList();
var numbersToConsider = ???? //2500, 2510, 2460 that they are similar with in 5% range
I stuck to find the numbers here.
I need to find a similar to each other. Basically the numbers are monthly loan payment and some other expenses. The loan payment can vary by x% mostly less than 5%. Now I need to figure out those loan payments from the list and take an average
You can get the "close" numbers in this way:
const int maxPercentage = 5;
List<int> numbers = new List<int>{2500, 2510, 7000, 7000, 7500, 1000, 1200, 2460};
List<List<int>> closeNumbers = new List<List<int>>();
foreach (int i in numbers.OrderBy(i => i))
{
if(closeNumbers.Count == 0)
{
closeNumbers.Add(new List<int> {i});
continue;
}
List<int> lastCloseNumbers = closeNumbers.Last();
int maxDistance = (int)(lastCloseNumbers.Average() / 100.0 * maxPercentage);
if(i - lastCloseNumbers.Last() <= maxDistance)
lastCloseNumbers.Add(i);
else
closeNumbers.Add(new List<int> {i});
}
What you want to do with them is not so clear, but i think this gives you all you need.
Result:
1000
1200
2460
2500
2510
7000
7000
7500
calculate average avg
calculate min=avg-5%
calculate max=avg+5%
iterate your values and output all that are between min and max

Interest On Balance Calculation Repayments

I am trying to design some code that will calculate a repayment plan for a loan, given a principle amount, term period (12 months) and and interest rate. I want the payments each month to be the same value (the last can differ slightly to account for remainders), and the interest is calculated from the remaining loan balance.
The basic rules are
Interest is dependant on the loan balance.
Loan balance is dependant on the total monthly repayment value.
Capital repayment is dependant on total monthly repayment value and interest.
The total monthly repayment amount can vary but must be the same each month (except the last one which can be different).
Here is the code I currently have, it does continous iterations until it finds the correct total monthly repayment value. This does work sort of but seems very inefficient and it takes the balance horribly into negative when it shouldnt . I'm wondering if anyone knows of a better way of doing this?
static void calcRepaymentPlan()
{
decimal loanAmount = 100000; //100,000
decimal ir = 0.10m;
//day counts
int[] days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//get month/days
int dayCount = days.Sum();
int months = days.Length;
//get interest values
decimal interestdaily = ir / dayCount;
//total each month
decimal ideal_total_repayment = (loanAmount / months); //random number but seems like the best place to start
//some arrays to store balances
decimal[] balances = null;
decimal[] interest = null;
decimal[] capitalrepayment = null;
decimal totalRepaymentsValue = 0;
while (totalRepaymentsValue != loanAmount)
{
//array for balance each month
balances = new decimal[months];
for (int i = 0; i < months; i++)
{
balances[i] = loanAmount - ((i+1) * ideal_total_repayment);
}
//array for interest each month
interest = new decimal[months];
for (int i = 0; i < months; i++)
{
interest[i] = (interestdaily * balances[i]) * days[i];
}
//array for capital each month
capitalrepayment = new decimal[months];
for (int i = 0; i < months; i++)
{
capitalrepayment[i] = ideal_total_repayment - interest[i];
}
//how much of the loan are we paying back?
totalRepaymentsValue = capitalrepayment.Sum();
//how much difference between the loan amount and the total we have got now?
decimal difference = loanAmount - totalRepaymentsValue;
//how much to increment
decimal incr = 1;
//are we within 100? if so make the increment finer
if (difference < 100)
incr = 0.1m;
//if the difference is less than 1, then just add/subtract it from the last repayment
if (difference < 1)
{
capitalrepayment[months - 1] += difference;
balances[months - 1] += difference;
//this should now be the
totalRepaymentsValue = capitalrepayment.Sum();
continue;
}
//change the ideal total repayment
ideal_total_repayment += totalRepaymentsValue < loanAmount ? incr : -incr;
}
Console.WriteLine("--------------------------------------------------------------------------------------");
Console.WriteLine(" Balance Capital Interest Total Repayment");
for (int i = 0; i < months; i++)
{
string balanceStr = balances[i].ToString("#,##0.00");
string capitalStr = capitalrepayment[i].ToString("#,##0.00");
string interestStr = interest[i].ToString("#,##0.00");
string totalStr = (capitalrepayment[i] + interest[i]).ToString("#,##0.00");
Console.WriteLine("{0}). {1} {2} {3} {4}", (i + 1),
balanceStr, capitalStr, interestStr, totalStr);
}
Console.WriteLine("Ideal Total Repayment Value : {0}", ideal_total_repayment);
Console.WriteLine("Total Repaying : {0}", totalRepaymentsValue);
Console.WriteLine("-------------------------------------------------------------------------------------");
}

How to get Index of an enum value which has returned as Array?

I have two Problem with this code,
The first is that when I print it, Day 6 is not in order, it prints like this:
On Day1:Temperature was12
On Day2:Temperature was13
On Day3:Temperature was15
On Day4:Temperature was17
On Day5:Temperature was18
On Day7:Temperature was19
On Day8:Temperature was20
On Day9:Temperature was21
On Day6:Temperature was22
On Day10:Temperature was23
The Minimum Tempreature was 12,
The Maximum temperature was 23,
The average Temperature was 18,
The second problem is that when I print the days, I want to include also the days in which the Minimum and Maximum Temperatures toke place like this:
The Minimum Tempreature was 12, at Day 1
The Maximum temperature was 23,at Day 10
How Can I get the name of an enum based on its value?
this is the code for above prints,
This code takes enum (days, temperatures) as parameters and prints the days with their related temperatures and minimum, maximum and average....
// if user select February
if (DropDownList1.SelectedValue.ToString()== "February")
{
ShowsTempreatures(FebruaryMonth.Day2);
}
// The method which print and shows temperatures and minimum and maximum...
private void ShowsTempreatures(Enum February)
{
int Minimumtemperture = 40;
int Maximumtemperture = 0;
int total = 0;
int averageTemperatures = 0;
// Return the values of Enum as an Array
Array januaryData = Enum.GetValues(February.GetType());
for (int i = 0; i < januaryData.Length; i++)
{
//printing the Days and Temperatures of enum February
Label1.Text += string.Format("On {0}:Temperature was{0:D}<br/>", januaryData.GetValue(i));
//finding out minimum and maximum and average temperatures
int MonthTemp = (int)januaryData.GetValue(i);
if (MonthTemp<Minimumtemperture)
{
Minimumtemperture = MonthTemp;
}
if (MonthTemp>Maximumtemperture)
{
Maximumtemperture = MonthTemp;
}
total = total + MonthTemp;
}
int totaltempretures = januaryData.Length;
averageTemperatures = (total / totaltempretures);
// printing the minimum,maximum and average temperature
Label1.Text += string.Format("The Minimum Tempreature was {0},<br/> The Maximum temperature was {1},<br/> The average Temperature was {2},<br/> ",
Minimumtemperture, Maximumtemperture, averageTemperatures);
}
private enum FebruaryMonth
{
Day1 = 12,
Day2 = 13,
Day3 = 15,
Day4 = 17,
Day5 = 18,
Day6 = 22,
Day7 = 19,
Day8 = 20,
Day9 = 21,
Day10 = 23
}
Consider this enum:
public enum DayOfMonth
{
Day2 = 2,
Day1 = 1
}
Here is how to get all the enums:
var days = Enum.GetValues(DayOfMonth.Day1.GetType()).Cast<DayOfMonth>().ToList();
Console.WriteLine(days[0]);
Here is how to get enum by its value. It is a simple cast:
DayOfMonth day2 = (DayOfMonth)2;
Console.WriteLine(day2);
Here is how to order them:
var ordered = days.OrderBy(x => x).ToList(); // or you can use OrderByDescending
Console.WriteLine(ordered[0]);
This is because Enum is order by its Values and not by the order of the name given to each value.
You can create a IComparer which will extract each value the name and compare it.
If we will compare the enum value names stricly by lexicographical order we will intreduce a new bug. A bug which will tell us Day10 is before Day2, because in lexicographical order 10 is small then 2. Thus, it leads us to try a different way.
Another more accurate way, will be extracting the enum names and substring only the number portion, then we will parse them into integers and then apply the comparison.
class Program
{
static void Main(string[] args)
{
Array januaryData = Enum.GetValues(typeof(FebruaryMonth));
Array.Sort(januaryData, new FebruaryMonthSubstringComparer());
for (int i = 0; i < januaryData.Length; i++)
{
string res = string.Format("On {0}:Temperature was{0:D}<br/>", januaryData.GetValue(i));
Console.WriteLine(res);
}
}
}
public class FebruaryMonthSubstringComparer : IComparer
{
public int Compare(object x, object y)
{
int monthX = int.Parse(Enum.GetName(typeof(FebruaryMonth), x).Substring(3)); // Naive parsing
int monthY = int.Parse(Enum.GetName(typeof(FebruaryMonth), y).Substring(3));
return monthX - monthY;
}
}

Array to Sort High Scores

I'm working on a project in C# that involves keeping track of the top five high scores for a rock paper scissors game. Right now I have an array to hold the top five scores (which are integers), I sort the array in descending order, and I use a for loop to compare the score just earned by the user to the scores currently in the array. If the new score is higher than one in the array, right now the new score just takes the space in the array that the lower one occupied.
For example, if the scores were 9, 8, 5, 3, 1 and the user scored a 6, the scores would then look like this: 9, 8, 6, 3, 1. I wondered if there's a way for me to shift the lower scores over and insert the new one, so the list would look like this: 9, 8, 6, 5, 3.
This is the code I currently have, where successPercent is the score, calculated as wins divided by losses and ties:
int[] scoreArray = { 84, 25, 36, 40, 50 };
Array.Sort(scoreArray);
Array.Reverse(scoreArray);
for (int x = 0; x <= scoreArray.Length; ++x)
{
if (successPercent > scoreArray[x])
{
scoreArray[x] = Convert.ToInt32(successPercent);
break;
}
}
Something like this can do the trick:
Create temporary list
Add new score
Sort it by descending order
Take top 5...
int[] scoreArray = { 84, 25, 36, 40, 50 };
var tempList = new List<int>(scoreArray );
int newScore = ...;//Get the new score
tempList.Add(newScore);
scoreArray = tempList.OrderByDescending(x=>x)
.Take(5)
.ToArray();
You can do this without creating a new list.
[Algo]: Replace the smallest number by the new number and then sort!
int[] scoreArray = { 5, 3, 9, 8, 1 };
int new_number = 6;
//Replaces smallest number by your new number
int min_index = Array.IndexOf(scoreArray, scoreArray.Min());
scoreArray[min_index] = new_number;
Array.Sort(scoreArray);
Array.Reverse(scoreArray);
I believe your way is correct and more effient than creating redundant lists, just you are calling the Reverse method unnecessarily.Instead, leave your elements sorted in ascending order, then loop through the array, and sort it in descending order.
int[] scoreArray = { 84, 25, 36, 40, 50 };
int userScore = 100;
Array.Sort(scoreArray);
for (int x = 0; x <= scoreArray.Length; ++x)
{
if (userScore > scoreArray[x])
{
scoreArray[x] = Convert.ToInt32(userScore);
break;
}
}
Array.Sort(scoreArray,(x,y) => y.CompareTo(x));
Note: My first solution was throwing away the second highest score so I have deleted it.

Categories