Nested For loop eternally running? - c#

I'm having a little trouble figuring out a nested for loop here. Here's the problem:
The population of Ireland is 4.8 million and growing at a rate of 7% per year. Write a program to determine and display the population
in 10 years time. Your program should also display a count of the
number of years that the population is predicted to exceed 5 million.
And here's what I've coded so far:
double pop = 4.8;
int years = 0;
for (int i = 0; i < 10; i++)
{
pop += (pop / 100) * 7;
for (int j = 0; pop >5; j++)
{
years += j;
}
}
Console.WriteLine("Pop in year 2030 is " + Math.Round(pop, 2) + " million and the population will be over 5 million for " + years + " years.");
}
Now to be clear, I need the sum of the years in which population exceeds 5(million) (the answer is 10) and I must only use for loops to solve this problem. I'm thinking the answer is a nested for loop, but have tried and tried with no success.
Can anyone help me on where I've screwed this up?

Look at your inner loop.
for (int j = 0; pop >5; j++)
{
years += j;
}
Your condition being pop > 5, you need pop to shrink if you ever want to exit the loop. But the body of the loop never alters pop, so if it's greater than 5, you'll loop forever.
The problem definition suggests that you don't need an inner loop at all. Just check pop, and if it's greater than 5, increment years.
if (pop > 5)
{
++years;
}
If you're really under such an insane restriction that you can't use if, you could do something boneheaded like create a for loop that only runs once if your other condition is right.
for (int j = 0; j < 1 && pop > 5; ++j)
{
++years;
}
but no sane person does this.

First, you need to clearer variable names in my opinion. Of course, don't go to far with that, but IMO population will be better than just pop.
Furhter, you could use Dictionary to store years alongside with preidcted population.
Also, write comments to better see what's going on :)
With this suggestions, I would code this like below:
double population = 4.8;
int currentYear = 2020;
Dictionary<int, double> predictions = new Dictionary<int, double>();
// Adding current state
predictions.Add(currentYear, population);
// I changed bounds of a loop to handle years in more comfortable way :)
for (int i = 1; i <= 10; i++)
{
population *= 1.07;
predictions.Add(currentYear + i, population);
}
Now you have data in Dictionary that looks like this:
2020 4.8
2021 ...
2022 ...
... ...
Now you can get all years, where population was over 5 million easily with predictions.Where(kvp => kvp.Value > 5).

If I well understand your question.
Technically if you add 7% each year your program should look like this
bool passed = true;
double pop = 4.8;
int year = 0;
for (int i=0; i<10; i++)
{
pop *= 1.07;
if (pop > 5 && passed)
{
year = i;
passed = false;
}
}

Related

Grouping results from for-loop C#

First time asking a question on Stackoverflow, fingers crossed! I'm new to programming and I'm struggeling to solve an issue. I got this foor loop:
for (int i = 0; i < antal.Count(); i++)
{
tbxResultat.AppendText(namnLista.ElementAt(i) + " \t");
tbxResultat.AppendText(personnummerLista.ElementAt(i).ToString() + " \t");
tbxResultat.AppendText(distriktLista.ElementAt(i) + " \t");
tbxResultat.AppendText(antal.ElementAt(i).ToString() + newLine);
}
I want to group the results from the loop into 4 sections: first values 0-49, second 50-99, third 100-199 and fourth 199. I'm interested in seeing how many is in each section and having it printed right each section, like:
23
37
---------------------------------
Total count of 2 in first section.
I've tried putting the for-loop in if statments but with no success. The sortment of the list is done with bubble sort which i modified to take a List instead of array. Any tips in the right direction would be much appriciated!
/Drone
This code should be what you asked for. Note the while in there. It's not if because there may be groups with zero elements, so you have to handle those as well.
int groupLimit = 50;
int elementsInGroup = 0;
for (int i = 0; i < antal.Count(); i++, elementsInGroup++)
{
while (antal[i] >= groupLimit)
{
// Write summary here. Use elementsInGroup..
groupLimit += 50;
elementsInGroup = 0;
}
// Write one row here. I suggest building the string and calling only one AppendText..
}

In C#, how do I store the amount of times random numbers equal certain sums in an array?

I'm writing a program that rolls _ amounts of _ sided dice _ times as specified by the user. This is a project with set requirements such as the class structure and the fact I have to use an array to show my results. The results are supposed to display each total I could possibly get and the amount of times I got each total after rolling for the specified amount of times.
I've written my attempt at this and fully expected it to work, but of course it did not.
Rolling 1,000 times and rolling 2 dice with 6 sides, here are my results:
4) 4
6) 4
8) 4
10) 4
12) 4
I'd expect something like:
2) 85
3) 83
4) 84
5) 82
... until 12
The sum doesn't start at 2 it starts at 4, it rolls 20 times instead of 1,000, and all the values are the same. Any idea what could be wrong?
Here's my code:
private int[] myTotals;
private int possibleTotal = 2;
private int arrayLocation = 0;
private int myNumberOfDice;
private string results = "";
private static Random diceGenerator = new Random();
public DiceFactory()
{
}
public void rollDice(int numberOfRolls, int numberOfSides, int numberOfDice)
{
myNumberOfDice = numberOfDice;
myTotals = new int[numberOfRolls];
arrayLocation = possibleTotal - 2;
for (int i = 0; i < numberOfRolls; i++) {
myTotals[arrayLocation] = diceGenerator.Next(1, numberOfSides + 1);
myTotals[arrayLocation]++;
}
while (possibleTotal <= numberOfSides * myNumberOfDice)
{
results += (possibleTotal) + ") " + myTotals[arrayLocation] + "\r\n";
possibleTotal++;
}
}
public string getResults()
{
return results;
}
}
arrayLocation gets set to 4 (6 - 2) at the beginning of your method, and doesn't change as you go through either your rolling loop or your result-building loop. That explains why you're seeing the value 4 for all your outputs.
I'd suggest sticking with a simple for loop for your result-building loop:
for (int i = 2; i <= numberOfSides * myNumberOfDice; i++)
{
results += (i) + ") " + myTotals[i] + "\r\n";
}
That isn't your only problem. You'll need to figure out how to add up the results from rolling multiple dice. (Your code doesn't currently use myNumberOfDice in the rolling loop.) Definitely learn to use your debugger and understand what you think should be in each variable at each step of the way, and compare it with what actually shows up each step of the way. Breaking complex things down into small, verifiable steps is the essence of software development.

Quickly returning all numbers less than or divisible by Seven

So i had an interview question: Write a function that takes a number and returns all numbers less than or divisible by 7
private List<int> GetLessThanOrDivisbleBySeven(int num)
{
List<int> ReturnList = new List<int>();
for(int i = 0; i <= num; i++)
{
if(i <7 || i % 7 == 0)
{
ReturnList.Add(i);
}
}
return ReturnList;
}
So far so good. The follow up question was: Let's say that call was being made 10s of thousands of times an hour. How could you speed it up?
I said if you knew what your queue was you could break up your queue and thread it. That got me some points i feel. However, he wanted to know if there was anything in the function i could do.
I came up with the idea to test if the num was greater than 7. if so initialize the list with 1 - 7 and start the loop int i = 8 which i think was ok but is there another way i am missing?
If you want to speed it up without caching, you can just increment i by 7 to get all numbers divisible by 7, it will be something like this:
static private List<int> GetLessThanOrDivisbleBySeven(int num) {
List<int> ReturnList;
int i;
if (num <= 7) {
ReturnList = new List<int>();
for (i = 0; i <= num; i++) {
ReturnList.Add(i);
}
return ReturnList;
}
ReturnList = new List<int> { 0, 1, 2, 3, 4, 5, 6 };
i = 7;
while (i <= num) {
ReturnList.Add(i);
i += 7;
}
return ReturnList;
}
You can cache the results. Each time your function is being called, check what numbers are in the cache, and calculate the rest.
If the current number is smaller, return the appropriate cached results.
use the previous results when calculating new list
int oldMax = 0;
List<int> ReturnList = new List<int>();
private List<int> GetLessThanOrDivisbleBySeven(int num)
{
if (num > oldMax )
{
oldMax = num;
for(int i = oldMax ; i <= num; i++)
{
if(i <7 || i % 7 == 0)
{
ReturnList.Add(i);
}
}
return ReturnList;
}
else
{
// create a copy of ReturnList and Remove from the copy numbers bigger than num
}
}
Interview questions are usually more about how you approach problems in general and not so much the technical implementation. In your case you could do a lot of small things, like caching the list outside. Caching different versions of the list in a dictionary, if space was not a problem. Maybe somebody can come up with some smarter math, to save on calculations, but usually it's more about asking the right questions and considering the right options. Say, if you ask "does this program run on a web server? maybe I can store all data in a table and use it as a quick lookup instead of recalculating every time." There might not even be a correct or best answer, they probably just want to hear, that you can think of special situations.
You can find all the numbers that are divisible by 7 and smaller than num by calculating res = num/7 and then create a loop from 1 to res and multiply each number by 7.
private List<int> GetLessThanOrDivisbleBySeven(int num)
{
List<int> ReturnList = new List<int>();
// Add all the numbers that are less than 7 first
int i = 0;
for(i = 0; i < 7; i++)
ReturnList.Add(i);
int res = num / 7;// num = res*7+rem
for(i = 1; i <= res; i++)
{
ReturnList.Add(i*7);
}
return ReturnList;
}
Think about memory management and how the List class works.
Unless you tell it the capacity it will need, it allocates a new array whenever it runs out of space, however it is easy to work out the size it will need to be.
Returning an array would save one object allocation compared to using a List, so discuss the tradeoff between the two.
What about using "yeild return" to advoid allocating memory, or does it have other costs to consider?
Is the same number requested often, if so consider cacheing.
Would LINQ, maybe using Enumerable.Range help?
An experienced C# programmer would be expected to know at least a little about all the above and that memory management is often an hidden issue.

C# Trial division - first n primes. Error in logic?

In a course a problem was to list the first n primes. Apparently we should implement trial division while saving primes in an array to reduce the number of divisions required. Initially I misunderstood, but got a working if slower solution using a separate function to test for primality but I would like to implement it the way I should have done.
Below is my attempt, with irrelevant code removed, such as the input test.
using System;
namespace PrimeNumbers
{
class MainClass
{
public static void Main (string[] args)
{
Console.Write("How many primes?\n");
string s = Console.ReadLine();
uint N;
UInt32.TryParse(s, out N)
uint[] PrimeTable = new uint[N];
PrimeTable[0] = 2;
for (uint i=1; i < N; i++)//loop n spaces in array, [0] set already so i starts from 1
{
uint j = PrimeTable[i -1] + 1;//sets j bigger than biggest prime so far
bool isPrime = false;// Just a condition to allow the loop to break???(Is that right?)
while (!isPrime)//so loop continues until a break is hit
{
isPrime = true;//to ensure that the loop executes
for(uint k=0; k < i; k++)//want to divide by first i primes
{
if (PrimeTable[k] == 0) break;//try to avoid divide by zero - unnecessary
if (j % PrimeTable[k] == 0)//zero remainder means not prime so break and increment j
{
isPrime = false;
break;
}
}
j++;//j increment mentioned above
}
PrimeTable[i] = j; //not different if this is enclosed in brace above
}
for (uint i = 0; i < N; i++)
Console.Write(PrimeTable[i] + " ");
Console.ReadLine();
}
}
}
My comments are my attempt to describe what I think the code is doing, I have tried very many small changes, often they would lead to divide by zero errors when running so I added in a test, but I don't think it should be necessary. (I also got several out of range errors when trying to change the loop conditions.)
I have looked at several questions on stack exchange, in particular:
Program to find prime numbers
The first answer uses a different method, the second is close to what I want, but the exact thing is in this comment from Nick Larsson:
You could make this faster by keeping track of the primes and only
trying to divide by those.
C# is not shown on here: http://rosettacode.org/wiki/Sequence_of_primes_by_Trial_Division#Python
I have seen plenty of other methods and algorithms, such as Eratosthenes sieve and GNF, but really only want to implement it this way, as I think my problem is with the program logic and I don't understand why it doesn't work. Thanks
The following should solve your problem:
for (uint i = 1; i < numberOfPrimes; i++)//loop n spaces in array, [0] set already so i starts from 1
{
uint j = PrimeTable[i - 1] + 1;//sets j bigger than biggest prime so far
bool isPrime = false;// Just a condition to allow the loop to break???(Is that right?)
while (!isPrime)//so loop continues until a break is hit
{
isPrime = true;//to ensure that the loop executes
for (uint k = 0; k < i; k++)//want to divide by first i primes
{
if (PrimeTable[k] == 0) break;//try to avoid divide by zero - unnecessary
if (j % PrimeTable[k] == 0)//zero remainder means not prime so break and increment j
{
isPrime = false;
j++;
break;
}
}
}
PrimeTable[i] = j;
}
The major change that I did was move the incrementation of the variable j to inside the conditional prime check. This is because, the current value is not prime, so we want to check the next prime number and must move to the next candidate before breaking in the loop.
Your code was incrementing after the check was made. Which means that when you found a prime candidate, you would increment to the next candidate and assign that as your prime. For example, when j = 3, it would pass the condition, isPrime would still = true, but then j++ would increment it to 4 and that would add it to the PrimeTable.
Make sense?
This might not be a very good answer to your question, but you might want to look at this implementation and see if you can spot where yours differs.
int primesCount = 10;
List<uint> primes = new List<uint>() { 2u };
for (uint n = 3u;; n += 2u)
{
if (primes.TakeWhile(u => u * u <= n).All(u => n % u != 0))
{
primes.Add(n);
}
if (primes.Count() >= primesCount)
{
break;
}
}
This correctly and efficiently computes the first primesCount primes.

Enter a code branch every ten percent till 100 percent

I can think of some very convoluted methods with loops and nested loops to solve this problem but I'm trying to be more professional than that.
My scenario is that I need to enter a section of code every ten percent but it isn't quite working as expected. It is entering the code about every percent which is due to my code but I lack the knowledge to know how to change it.
int currentPercent = Math.Truncate((current * 100M) / total);
//avoid divide by zero error
if (currentPercent > 0)
{
if (IsDivisible(100, currentPercent))
{
....my code that works fine other than coming in too many times
}
}
Helper referenced above where the trouble is:
private bool IsDivisible(int x, int y)
{
return (x % y) == 0;
}
So obviously it works as it should. Mod eliminates currentPercent of 3 but 1 & 2 pass when really I don't want a true value until currentPercent = 10 and then not again till 20...etc.
Thank you and my apologies for the elementary question
Mod will only catch exact occurrences of your interval. Try keeping track of your next milestone, you'll be less likely to miss them.
const int cycles = 100;
const int interval = 10;
int nextPercent = interval;
for (int index = 0; index <= cycles; index++)
{
int currentPercent = (index * 100) / cycles;
if (currentPercent >= nextPercent)
{
nextPercent = currentPercent - (currentPercent % interval) + interval;
}
}
I might misunderstand you, but it seems like you're trying to do something extremely simple more complex than it needs to be. What about this?
for (int i = 1; i <= 100; i++)
{
if (i % 10 == 0)
{
// Here, you can do what you want - this will happen
// every ten iterations ("percent")
}
}
Or, if your entire code enters from somewhere else (so no loop in this scope), the important part is the i % 10 == 0.
if (IsDivisible(100, currentPercent))
{
....my code that works fine other than coming in too many times
}
try changing that 100 to a 10. And I think your x and y are also backwards.
You can try a few sample operations using google calculator.
(20 mod 10) = 0
Not sure if I fully understand, but I think this is what you want? You also reversed the order of modulo in your code (100 mod percent, rather than the other way around):
int currentPercent = current * 100 / total;
if (currentPercent % 10 == 0)
{
// your code here, every 10%, starting at 0%
}
Note that code this way only works properly if you are guaranteed to hit every percentage-mark. If you could, say, skip from 19% to 21% then you'll need to keep track of which percentage the previous time was to see if you went over a 10% mark.
try this:
for (int percent = 1; percent <= 100; percent++)
{
if (percent % 10 == 0)
{
//code goes here
}
}
Depending on how you increment your % value, this may or may not work % 10 == 0. For example jumping from 89 to 91 % would effectively skip the code execution. You should store last executed value, 80 in this case. Then check if interval is >= 10, so 90 would work, as well as 91.

Categories