Pennies on Pay - Math Calculation - C# - c#

I'm trying to double the amount of pennies for X amount of days.
So, 3 days = 4 pennies, 4 days = 8 pennies, etc
I'm stuck on getting the right code put in: (I know I'm close and I know I'm missing something silly. I've spent 5 hours on this. I just want to see the solution so my mind will put it together on how it works...)
I finally got it... now... how can I clean this up?? I'm still learning to write in less code... but I'm following the Starting Out w/ Visual C# book for now...
// Local variables. /
int daysWorkedInputValue;
decimal currentPayRate, newPayRate, totalPaySalary;
int daysWorked;
int count = 0;
currentPayRate = 0.01m;
totalPaySalary = 0m;
daysWorkedInputValue = int.Parse(daysWorkedInputTextBox.Text);
if (int.TryParse(daysWorkedInputTextBox.Text, out daysWorked))
{
if (daysWorked >= 0)
{
// Continue to process the input. /
if (daysWorkedInputValue == 0)
{
totalPayCalcLabel.Text = "$0.00";
}
if (daysWorkedInputValue == 1)
{
totalPayCalcLabel.Text = "$0.01";
}
// The following loop calculates the total pay. /
while (count <= (daysWorked - 1))
{
// Calculate the total pay amount. /
if (count == 1)
{
currentPayRate = 0.01m;
totalPayCalcLabel.Text = currentPayRate.ToString("c");
}
currentPayRate = currentPayRate * 2;
totalPaySalary = currentPayRate;
if (count >= 1)
{
totalPayCalcLabel.Text = totalPaySalary.ToString("c");
}
// Add one to the loop counter. /
count = count + 1;
// Return focus back to the organisms TextBox. /
daysWorkedInputTextBox.Focus();
}

I see a pretty obvious pattern here:
3 days -> 2^(3-1) = 4 pennies
4 days -> 2^(4-1) = 8 pennies
So you want to solve for the equation:
pennies = 2^(days-1)
I haven't run your code to see what's wrong (nothing's changing the value of count or daysWorked so I'm assuming you'll end up stuck in an infinite loop), but this should work just fine:
var pennies = Math.Pow(2, days - 1);

Related

C# WinsForm, Frequency Distribution Table [Updated]

Update 01
Thanks to Caius, found the main problem, the logic on the "if" was wrong, now fixed and giving the correct results. The loop still create more positions than needed on the secondary List, an extra position for each number on the main List.
I've updated the code bellow for refence for the following question:
-001 I can figure out why it create positions that needed, the for loop should run only after the foreach finishes its loops correct?
-002 To kind of solving this issue, I've used a List.Remove() to remove all the 0's, so far no crashes, but, the fact that I'm creating the extra indexes, and than removing them, does means a big performance down if I have large list of numbers? Or is an acceptable solution?
Description
It supposed to read all numbers in a central List1 (numberList), and count how many numbers are inside a certain (0|-15 / 15|-20) range, for that I use another List, that each range is a position on the List2 (numberSubList), where each number on List2, tells how many numbers exists inside that range.
-The range changes as the numbers grows or decrease
Code:
void Frequency()
{
int minNumb = numberList.Min();
int maxNumb = numberList.Max();
int size = numberList.Count();
numberSubList.Clear();
dGrdVFrequency.Rows.Clear();
dGrdVFrequency.Refresh();
double k = (1 + 3.3 * Math.Log10(size));
double h = (maxNumb - minNumb) / k;
lblH.Text = $"H: {Math.Round(h, 2)} / Rounded = {Math.Round(h / 5) * 5}";
lblK.Text = $"K: {Math.Round(k, 4)}";
if (h <= 5) { h = 5; }
else { h = Math.Round(h / 5) * 5; }
int counter = 1;
for (int i = 0; i < size; i++)
{
numberSubList.Add(0); // 001 HERE, creating more positions than needed, each per number.
foreach (int number in numberList)
{
if (number >= (h * i) + minNumb && number < (h * (i + 1)) + minNumb)
{
numberSubList[i] = counter++;
}
}
numberSubList.Remove(0); // 002-This to remove all the extra 0's that are created.
counter = 1;
}
txtBoxSubNum.Clear();
foreach (int number in numberSubList)
{
txtBoxSubNum.AppendText($"{number.ToString()} , ");
}
lblSubTotalIndex.Text = $"Total in List: {numberSubList.Count()}";
lblSubSumIndex.Text = $"Sum of List: {numberSubList.Sum()}";
int inc = 0;
int sum = 0;
foreach (int number in numberSubList)
{
sum = sum + number;
int n = dGrdVFrequency.Rows.Add();
dGrdVFrequency.Rows[n].Cells[0].Value = $"{(h * inc) + minNumb} |- {(h * (1 + inc)) + minNumb}";
dGrdVFrequency.Rows[n].Cells[1].Value = $"{number}";
dGrdVFrequency.Rows[n].Cells[2].Value = $"{sum}";
dGrdVFrequency.Rows[n].Cells[3].Value = $"{(number * 100) / size} %";
dGrdVFrequency.Rows[n].Cells[4].Value = $"{(sum * 100) / size} %";
inc++;
}
}
Screen shot showing the updated version.
I think, if your aim is to only store eg 17 in the "15 to 25" slot, this is wonky:
if (number <= (h * i) + minNumb) // Check if number is smaller than the range limit
Because it's found inside a loop that will move on to the next range, "25 to 35" and it only asks if the number 17 is less than the upper limit (and 17 is less than 35) so 17 is accorded to the 25-35 range too
FWIW the range a number should be in can be derived from the number, with (number - min) / number_of_ranges - at the moment you create your eg 10 ranges and then you visit each number 10 times looking to put it in a range, so you do 9 times more operations than you really need to

Find the number whose digits have the highest sum in a given range [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 years ago.
Improve this question
For a given input n, the task is to find the largest integer that is <= n and has the highest digit sum.
For example:
solve(100) = 99. Digit Sum for 99 = 9 + 9 = 18. No other number <= 100 has a higher digit sum.
solve(10) = 9
solve(48) = 48. Note that 39 is also an option, but 48 is larger.
Input range is 0 < n < 1e11
What have I tried?
I tried 2 methods. Firstly, I tried getting each digit with Math operations like this:
public static long solve(long n)
{
var answer = 0;
var highestSum = 0;
for (var i = 1; i <= n; i++)
{
var temp = i;
var sum = 0;
while (temp > 0)
{
sum += temp % 10;
temp /= 10;
}
if (sum >= highestSum)
{
highestSum = sum;
answer = i;
}
}
return answer;
}
My second try, I tried using Linq extensions, like this:
public static long solve(long n)
{
var answer = 0;
var highestSum = 0;
for (var i = 1; i <= n; i++)
{
var sum = i.ToString().Sum(x => x - '0');
if (sum >= highestSum)
{
highestSum = sum;
answer = i;
}
}
return answer;
}
Both of my solutions seem to return the correct value and work for smaller values, but for larger input, they seem to take a very long time to execute. How to make it run through numbers faster? Is there a specific algorithm for this task, or am I doing something else wrong?
We can achieve this O(number of digits in n)
We can achieve this if we iteratively reduce a digit and change all other digits on its right to 9.
Let n be our current number.
We can find next number using the below :
b is a power of 10 to represent position of current digit. After every iteration we reduce n to n/10 and change b to b*10.
We use (n – 1) * b + (b – 1);
For eg, if the number is n = 521 and b = 1, then
(521 – 1) * 1 + (1-1) which gives you 520, which is the thing we need to do, reduce the position number by 1 and replace all other numbers to the right by 9.
After n /= 10 gives you n as 52 and b*=10 gives you b as 10, which is again executed as (52-1)*(10) + 9 which gives you 519, which is what we have to do, reduce the current index by 1 and increase all other rights by 9.
static int findMax(int x)
{
int b = 1, ans = x;
while (x!=0)
{
int cur = (x - 1) * b + (b - 1);
if (sumOfDigits(cur) >= sumOfDigits(ans) && cur > ans))
ans = cur;
x /= 10;
b *= 10;
}
return ans;
}
int sumOfDigits(int a)
{
int sum = 0;
while (a)
{
sum += a % 10;
a /= 10;
}
return sum;
}
The accepted answer is brilliant, but I was dead-set on figuring out a way to determine the correct answer without actually summing the digits and comparing the sums to each other.
I tried a few things (as you can see if you look at the edit history), but I couldn't find the formula. In desperation, I wrote a utility to show me all the numbers from 1 to 9999999 that did not have a smaller number with a larger sum to see what pattern I was missing by not looking on a large enough scale.
I was somewhat surprised that only 253 numbers out of the first 10 million have the largest sum compared to their lessers! Somehow I thought that number would be bigger.
Also, it turns out that there is an obvious pattern that appears fairly quickly, and it remained constant for 10 million iterations, so I think it's a good one.
Here's a small sample of some blocks of consecutive output:
0,1,2,3,4,5,6,7,8,9,
18,19,28,29,38,39,48,49,
58,59,68,69,78,79,88,89,98,99,189,198
8899,8989,8998,8999,
9899,9989,9998,9999,
18999,19899,19989,19998,19999
98999,99899,99989,99998,99999,
189999,198999,199899,199989,199998,199999
7899999,7989999,7998999,7999899,7999989,7999998,7999999,
8899999,8989999,8998999,8999899,8999989,8999998,8999999,
9899999,9989999,9998999,9999899,9999989,9999998,9999999
It's so obviously clear!
If the number is one digit, then it's the highest.
If all but the first digit are either all 9's or all 9's with a single 8, then it's sum is the highest.
Otherwise the highest number is the one whose first digit is one less than the original, followed by all 9's.
Here's a code implementation:
public static long Solve(long n)
{
if (HasValidSuffix(n)) return n;
long firstDigit;
int numDigits;
// Loop to determine the first digit and number of digits in the input
for (firstDigit = n, numDigits = 1; firstDigit > 9; firstDigit /= 10, numDigits++) ;
return Enumerable.Range(0, numDigits - 1)
.Aggregate(firstDigit - 1, (accumulator, next) => accumulator * 10 + 9);
}
// Returns true for positive numbers less than 10 or
// numbers that end in either all 9's or all 9's and one 8
public static bool HasValidSuffix(long input)
{
var foundAnEight = false;
for (var n = input; n > 9; n /= 10)
{
var lastDigit = n % 10;
if (lastDigit < 8) return false;
if (lastDigit == 9) continue;
if (foundAnEight) return false;
foundAnEight = true;
}
return true;
}

Convert money input into coins

ive just started some classes on c# and have been given an assignment with the following rules:
Prompt the user to enter an amount of dollars and cents. For example 1.18
- Display the number of quarters, dimes, nickels, and pennies to make that amount
Example If they entered 2.16 it should say:
8 quarters, 1 dimes, 1 nickels, 1 pennies
the problem that i run into is that this only seems to work if they type the money value as a whole. so if they wanted to type $1.18 they would type 118 and it would work just fine, but as soon as they type 1.18 it crashes. another example would be if they were to type 765 for $7.65 it would work fine, however if they type it correctly as 7.65 it would fail. sorry for the lame question, im super new, thanks for the help!
int totalCash;
Console.WriteLine("input money");
string moneyString = Console.ReadLine();
totalCash = int.Parse(moneyString);
int quarter = totalCash / 25;
totalCash %= 25;
int dime = totalCash / 10;
totalCash %= 10;
int nickel = totalCash / 5;
totalCash %= 5;
int penny = totalCash / 1;
totalCash %= 1;
Console.WriteLine("{0} quarters, {1} dimes, {2} nickels, {3} pennies", quarter, dime, nickel, penny);
```
There are lots of ways get the result but this the best approach I ever tried :
public static string ConvertMoneyIntoCoins(double money)
{
int cents = (int)(Math.Round(money, 2) * 100);
var coins = new[] {
new { Name = "Quarters", Value = 25 }, new { Name = "Dimes", Value = 10 },
new { Name = "Nickels", Value = 5 }, new { Name = "Pennies", Value = 1 }
};
var changes = coins.Select(coin => new { Amt = Math.DivRem(cents, coin.Value, out cents), Coin = coin }).Where(x => x.Amt != 0).ToList();
var strBld = new StringBuilder();
foreach (var change in changes)
{
strBld.Append(change.Amt + " " + change.Coin.Name + ", ");
}
return strBld.ToString();
}
It's working when you enter whole number should be the clue you pay attention to. If you assume the whole number is dollars, you can not mod by a whole number. All of your divisors are a factor of 100 too big. When you do that, you'll notice that you have the wrong data type as well. Note that i disagree with using tryparse when debugging as it eats errors. You should be running it in debug mode and then you would get an actual stack trace and a line it crashes at.

C# Strange issue with checking progress

I have a loop inside a constructor, that creates and initialises a jagged array of objects. Inside the loop I have it print to the console on each iteration, so that I know how far through the process it is. It only prints to the console on a multiple of 5 (although it's only printing on a multiple of 10 for some reason) so that it doesn't spam the screen. Eg, 15% 20% 25%.
When I run the code on .Net 2.0 on Windows, it prints every 10% (rather than 5%). If I run the same code on Mono on an ARM machine it doesn't print any progress out at all.
What is causing Mono to not give any output?
Why is it printing only in increments of 10% rather than 5%?
Thanks
Here's the code:
public Map(int NumberOfRows, int NumberOfColumns)
{
Rows = NumberOfRows;
Columns = NumberOfColumns;
TileGrid = new Tile[NumberOfRows][];
for (int x = 0; x < TileGrid.Length; x++)
{
TileGrid[x] = new Tile[NumberOfColumns];
for (int y = 0; y < TileGrid[x].Length; y++)
{
TileGrid[x][y] = new Tile();
}
if (((double)x / Rows) * 100 % 5 == 0)
{
Console.WriteLine("{0}%", ((double)x / Rows) * 100);
}
}
}
The problem is basically that you're performing an equality check on a floating point number, which is pretty much never a good idea.
This is better... but still not good:
int percentage = (x * 100) / Rows;
if (percentage % 5 == 0)
{
Console.WriteLine("{0}%", percentage);
}
That's still not going to print the percentage unless you end up exactly at multiples of 5%. So if there are 12 items, it's not going to work. Try this instead:
// Before the loop
int lastPrintedPercentage = -5; // So that we always print on the first loop
// Within the loop
int percentage = (x * 100) / Rows;
if (percentage >= lastPrintedPercentage + 5)
{
Console.WriteLine("{0}%", percentage);
lastPrintedPercentage = percentage;
}
floating point operations must be compared against the machine epsilon because of the floating point rounding errors
http://en.wikipedia.org/wiki/Machine_epsilon
This expression can be never null according to the floating point rounding error
if (((double)x / Rows) * 100 % 5 == 0)
must be
if (Math.Abs(((double)x / Rows) * 100 % 5) < MACHINE_EPSILON)
But there is no definition in the .NET Framework for the machine epsilon. So don't use floating point operations for this at all or use a delta technique like
var step = (double)x / Rows) * 5;
var current = step ;
...
if((double)x / Rows) >= current)
{
current += step;
// Your code here
}
...

C# Triangle numbers optimization

The task is to find a triangle number which has at least 500 divisors.
For example 28 has 6 divisors: 1,2,4,7,14,28
My code works for up to 200 divisors, but for 500 it runs forever...
Is there any way to optimize the code. For instance I thought of dynamic optimization and memoization, but couldn't find a way to do it?
int sum = 0;
int counter = 0;
int count = 1;
bool isTrue = true;
while (isTrue)
{
counter = 0;
sum += count;
for (int j = 1; j <= sum; j++)
{
if (sum % j == 0)
{
counter++;
if (counter == 500)
{
isTrue = false;
Console.WriteLine("Triangle number: {0}", sum);
break;
}
}
}
count++;
}
Console.WriteLine("Number of divisors: {0}", counter);
Ignore the fact that the number is a triangle number. If you can solve this problem quickly:
given any number n, determine the number of divisors it has
then obviously you can solve Euler #12 quickly. Just list the triangle numbers, which are easy to calculate, determine the number of divisors of each, and stop when you get a result 500 or larger.
So how do you determine the number of divisors quickly? As you've discovered, when the numbers get big, it's a lot of work.
Here's a hint. Suppose you already have the prime factorization. Let's pick a number, say, 196. Factorize that into prime numbers:
196 = 2 x 2 x 7 x 7
I can tell you just by glancing at the factorization that 196 has nine divisors. How?
Because any divisor of 196 is of the form:
(1, 2 or 2x2) x (1, 7 or 7x7)
So obviously there are nine possible combinations:
1 x 1
1 x 7
1 x 7 x 7
2 x 1
2 x 7
2 x 7 x 7
2 x 2 x 1
2 x 2 x 7
2 x 2 x 7 x 7
Pick another number. 200, lets say. Thats 2 x 2 x 2 x 5 x 5. So there are twelve possibilities:
1 x 1
1 x 5
1 x 5 x 5
2 x 1
2 x 5
...
2 x 2 x 2 x 5 x 5
See the pattern? You take the prime factorization, group them by prime, and count how many are in each group. Then you add one to each of those numbers and multiply them together. Again, in 200 there are three twos and two fives in the prime factorization. Add one to each: four and three. Multiply them together: twelve. That's how many divisors there are.
So you can find the number of divisors very quickly if you know the prime factorization. We have reduced the divisor problem to a much easier problem: Can you figure out how to produce a prime factorization quickly?
here are some optimizations I'll just throw out there for you.
the easiest thing is to change
for (int j = 1; j <= sum; j++)
{
if (sum % j == 0)
{
counter++;
if (counter == 500)
{
isTrue = false;
Console.WriteLine("Triangle number: {0}", sum);
break;
}
}
}
if you've found 1 divisor, you've found 2 divisors, so change it to
for (int j = 1; j <= sum; j++)
{
if (sum % j == 0)
{
if(sum/j < j)
break;
else if(sum/j == j)
counter++;
else
counter +=2;
if (counter == 500)
{
isTrue = false;
Console.WriteLine("Triangle number: {0}", sum);
break;
}
}
}
this will reduce the runtime a lot, but it will still take a long time.
another optimization you can do is to not start checking form sum but calculate the smallest number that has 500 divisors.
and then you can find the largest triangle number after that, and start from there.
If you can figure something else special about the nature of this problem, than it is possible for you to reduce the runtime by a whole lot.
The number of divisors of a number is the product of the powers of the prime factors plus one. For example: 28 = 2^2*7^1, so the # of divisors is (2+1)*(1+1) = 6.
This means that, if you want many divisors compared to the size of the number, you don't want any one prime to occur too often. Put another way: it is likely that the smallest triangular number with at least 500 divisors is the product of small powers of small primes.
So, instead of checking every number to see if it divides the triangular number, go through a list of the smallest primes, and see how often each one occurs in the prime factorization. Then use the formula above to compute the number of divisors.
Take these steps:
1.) Calculate the first log(2, 499) prime numbers (not 500, as 1 is counted as a divisor if I am nit mistaken despite the fact that it is not prime, as it has only one divisor). There are many solutions out there, but you catch my drift.
2.) A triangle number is of the form of n * (n + 1) / 2, because
1 + 2 + ... + 100 = (1 + 100) + (2 + 99) + ... + (50 + 51) = 101 * 50 = 101 * 100 / 2 = 5050 (as Cauchy solved it when he was an eight-year boy and the teacher punished him with this task).
1 + ... + n = (1 + n) + (2 + n - 1) + ... = n * (n + 1) / 2.
3.) S = prod(first log(2, 499) prime numbers)
4.) Solve the equation of n * (n + 1) / 2 = S and calculate its ceiling. You will have an integer, let's call it m.
5.)
while (not(found))
found = isCorrect(m)
if (not(found)) then
m = m + 1
end if
end while
return m
and there you go. Let me know if I was able to help you.
As #EricLippert nad #LajosArpad mentioned, the key idea is to iterate over triangle numbers only. You can calculate them using the following formula:
T(n) = n * (n + 1) / 2
Here is JSFiddle which you may find helpful.
function generateTriangleNumber(n) {
return (n * (n + 1)) / 2;
}
function findTriangleNumberWithOver500Divisors() {
var nextTriangleNum;
var sqrt;
for (i = 2;; i++) {
var factors = [];
factors[0] = 1;
nextTriangleNum = generateTriangleNumber(i);
sqrt = Math.pow(nextTriangleNum, 0.5);
sqrt = Math.floor(sqrt);
var j;
for (j = 2; j <= sqrt; j++) {
if (nextTriangleNum % j == 0) {
var quotient = nextTriangleNum / j;
factors[factors.length] = j;
factors[factors.length] = quotient;
}
}
factors[factors.length] = nextTriangleNum;
if (factors.length > 500) {
break;
}
}
console.log(nextTriangleNum);
}
Incidentally, the first Google result for divisors of triangular number search query gives this :)
Project Euler 12: Triangle Number with 500 Divisors
See if it helps.
EDIT: Text from that article:
The first triangle number with over 500 digits is: 76576500 Solution
took 1 ms

Categories