I've got a task for printing the highest sum of numbers, lowest sum of numbers and the average of numbers which were printed. i managed to get the higest sum of numbers but with the lowest somehow didn't work for me at all.
for example:
7 3 -2 6 -10 8 -5 3 -2 1
their Interim amount:
7 10 8 14 4 12 7 10 8 9
the output will be:
Higest Interim amount: 14
Lowest Interim amount: 4
Avg of numbers: 0.9
my code:
static void Main(string[] args)
{
int num = 0, i, sum = 0, c = 0, max, min;
max = min = num;
for (i = 0; i <= 10; i++)
{
Console.WriteLine("Enter a number:");
num = int.Parse(Console.ReadLine());
sum = sum + num;
if (sum >= max)
max = sum;
else if (sum <= min)
min = sum;
c++;
Console.WriteLine("sum:{0}", sum);
}
Console.WriteLine("count={0} avg={1}", c, sum / (float)c);
Console.WriteLine("Max:{0} Min:{1}", max, min);
}
You make both min and max start at 0, so the min will only update if you get a negative value for the cumulative sum (which does not happen in your example). (Would be the same for the max value if all your sums remained negative).
You need to start with the numeric equivalent of min = +Infinity and max = -Infinity.
i.e.
static void Main(string[] args)
{
int num = 0, i, sum = 0, c = 0;
int max = int.MinValue;
int min = int.MaxValue;
(Thanks #Caius Jard for the syntax, I know nothing about C#)
It's because you set the initial min to 0, and then only set the minimum to the sum if it drops below that. If you set initial minimum and maximum to the first number input you won't have this problem:
static void Main(string[] args)
{
int num = 0, i, sum = 0, c = 0, max, min;
for (i = 0; i <= 9; i++)
{
Console.WriteLine("Enter a number:");
num = int.Parse(Console.ReadLine());
if(i == 0)
{
min = num;
max = num;
}
sum = sum + num;
if (sum >= max)
max = sum;
else if (sum <= min)
min = sum;
c++;
Console.WriteLine("sum:{0}", sum);
}
Console.WriteLine("count={0} avg={1}", c, sum / (float)c);
Console.WriteLine("Max:{0} Min:{1}", max, min);
}
Related
I am facing a problem while solving this task.
I should write a program which find the count of prime numbers which can be created using digits of given number, but without repetition unless digit itself repeated in given number.
For example, program should give 5 as output for number = 123. Because
{1, 2, 3, 12, 13, 21, 23, 123, 132, 213, 231, 312, 321}
has 5 prime numbers.
But if given number = 133 then program should count prime number from this list :
{1, 3, 13, 31, 33, 133, 313, 331}
Is there any way to write this program without using array? I have searched every source, but still cannot find a solution. If you have any idea, please help.
I am trying to write something like that. But it is still not working. It is not creating number as I want. One-digit numbers is a little bit closer than 3-digit when I enter 123 . Output is like that:
enter image description here
System.Console.WriteLine("Enter the number: ");
int number = Convert.ToInt32(Console.ReadLine());
int enteredNumber = number;
int length = 0;
while (number != 0)
{
length++;
number /= 10;
}
System.Console.WriteLine($"{length} length");
number = enteredNumber;
int nDigit = 1;
int count = 0;
int temp = number;
while (nDigit <= length)
{
int n = nDigit;
while (number != 0)
{
int digit = number % 10;
if (nDigit == 1 && isPrime(digit))
{
System.Console.WriteLine("1-digit prime number : " + digit);
count++;
}
else
{
int tempNewNumber = digit * Convert.ToInt32(Math.Pow(10, Convert.ToDouble(nDigit - 1)));
int newNumber = tempNewNumber;
while (temp != 0)
{
if (nDigit - 2 >= 0)
{
newNumber += (temp % 10) * Convert.ToInt32(Math.Pow(10, Convert.ToDouble(nDigit - 2)));
nDigit--;
}
if (nDigit == 1)
{
System.Console.WriteLine("in while : " + newNumber);
if (isPrime(newNumber))
{
System.Console.WriteLine("prime number : " + newNumber);
count++;
}
newNumber = tempNewNumber;
nDigit = n;
}
temp /= 10;
}
nDigit = n;
temp = enteredNumber;
}
number /= 10;
}
number = enteredNumber;
nDigit++;
}
System.Console.WriteLine("Count : " + count);
}
static bool isPrime(int num)
{
if (num <= 1) return false;
int i = 2;
while (i <= num / 2)
{
if (num % i == 0)
return false;
i++;
}
return true;
}`
You can do what you want without arrays: Identify a number by the product of the nth prime number for each digit n.
If two numbers have the same id, they are digit-wise permutations of each other.
If the id of one number p is evenly divisibly by the id of another number q, then q has fewer digits than p, but all digits of q can also found in p.
You can now test all numbers in the possible range, for example all numbers with 3 or fewer digits, whether they can be made from the given digit. This is probably not very efficient, especially for large numbers, but hey! – no arrays. (And permutations of large sets have their own performance issues.)
The example code below finds the 16 permutations of 123, but it doesn't check whether the numbers are primes.
public class Permutor
{
static uint[] prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
static uint code(uint n)
{
uint res = 1;
while (n > 0) {
res *= prime[n % 10];
n /= 10;
}
return res;
}
static uint ceiling(uint n)
{
uint c = 1;
while (n > 0) {
c *= 10;
n /= 10;
}
return c;
}
static void Main(string[] args)
{
uint num = 123;
uint id = code(num);
uint max = ceiling(num);
for (uint i = 1; i < max; i++) {
if (id % code(i) == 0) {
Console.WriteLine(i);
}
}
}
}
There's room for improvement. For example, the actual ceiling for 123 is, of course, 321, so you could try to find that from the code instead of overestimating the ciling to 1000.
When you look for primes, you don't need to visit every number. Except 2 and 3, all prime numbers are either 2*k - 1 or 2*k + 1.
The task is to allow the user to enter values between 0 and 100. If the user enters -99 the program should stop. Once the program has exited, the average must be computed. However, the average should include all the entered values, except the lowest value entered (minimum) and the greatest value entered (maximum). I have written a fairly good-looking code, but it throws an IndexOutOfRangeException.
Here is that code:
class Program
{
static void Main(string[] args)
{
DisplayApp();
Calculate();
}
static void DisplayApp()
{
Console.WriteLine("Grade Calculator: ");
Console.WriteLine();
}
static double Calculate()
{
Console.WriteLine("Enter grades (-99 to exit): ");
string input = Console.ReadLine();
int[] array1 = new int[] { };
int iInput = int.Parse(input);
int min = 100;
int max = 0;
int i = 0;
int sum = 0;
double average = 0;
while(iInput != 99)
{
if(iInput < min)
{
array1[i] = min;
}
else if(iInput > max)
{
array1[i] = max;
}
sum += iInput - (min + max);
i++;
}
average = (double)sum / i;
return average;
}
}
What do you think could be improved in order for the program to work?
As I mentioned in the comments, you create an array of size zero. I don't see why you need an array at all, since you are only summing the values:
static double Calculate()
{
Console.WriteLine("Enter grades (-99 to exit): ");
int min = Int32.MaxValue;
int max = Int32.MinValue;
int sum = 0;
int i = 0;
while (true)
{
// TODO: Change to TryParse and handle input errors.
int iInput = int.Parse(Console.ReadLine());
if (iInput == -99) break;
if (iInput > 0 && iInput < 100) {
if (iInput < min)
{
min = iInput;
}
if (iInput > max)
{
max = iInput;
}
sum += iInput;
i += 1;
}
}
// TODO: Ensure no division by zero
return (double)(sum - max - min) / (i - 2);
}
I want to input 10 numbers and get the total sum of them if you take out the highest and lowest number that was input. So basically it'll be 8 numbers that i get the sum of when i take out the highest and lowest number that was input out of the 10. So far i can only count the total sum out of the 10 numbers, but not sure how to take out the highest and lowest. What approach could i take?
static void Main(string[] args)
{
int number, sum = 0, n;
for (number = 1; number < 11; number++)
{
Console.WriteLine("Enter a number");
n = Convert.ToInt32(Console.ReadLine());
sum += n;
}
Points(sum);
Console.ReadLine();
}
static void Points(int sum)
{
Console.WriteLine("Totalpoint is " + sum);
}
Addition is additive, so you can simply remove them on the end:
int sum = 0;
int min = int.MaxValue;
int max = int.MinValue;
for (int i = 0; i < 10; ++i)
{
Console.WriteLine("Enter a number");
int n = Convert.ToInt32(Console.ReadLine());
sum += n;
min = Math.Min(min, n);
max = Math.Max(max, n);
}
sum -= min;
sum -= max;
Points(sum);
Console.ReadLine();
An easy implementation to explain my thought process, could be the following:
static void Main(string[] args)
{
int number, sum = 0, n;
List<int> inputNumbers = new List<int>();
for(number = 0; number < 10; number++)
{
inputNumbers.Add(Convert.ToInt32(Console.ReadLine()));
}
// Obtain maximum and minimum values
var maximum = inputNumbers.Max();
var mimimum = inputNumbers.Min();
foreach (var item in inputNumbers)
{
if(item == maximum)
{
inputNumbers.Remove(item);
break;
}
}
foreach(var item in inputNumbers)
{
if(item == mimimum)
{
inputNumbers.Remove(item);
break;
}
}
Console.WriteLine("Sum: "+inputNumbers.Sum());
Console.ReadKey();
}
The solution is rather simple, since after populating the List with the specified 10 values, you query it to obtain the minimum and maximum values.
When you know them, you can simply loop through the list and remove both the maximum and minimum (break is completely necessary after those operations).
Downside? In this simple implementation, you would be iterating through the List two times, which should definitely be optimized, even if for clean code sake.
But it might the best first step to you!
Just have two more variables to track max and min values as you read them:
min = Math.Min(min, n);
max = Math.Max(max, n);
Then, as you exit the loop, you can simply subtract those from the total sum before printing.
sum -= min + max;
You can try this:
List<int> testNum = new List<int>();
int num = 0;
int sum = 0;
try
{
// This will loop until you have 10 inputs
while(testNum.Count < 10)
{
Console.WriteLine("Enter a number:");
num = Convert.ToInt32(Console.ReadLine()); // Need to have the Try/Catch in case user doesn't input a number
testNum.Add(num);
}
// Get the min and max values (you will need System.Linq for this)
int minVal = testNum.Min();
int maxVal = testNum.Max();
// Remove the min and max values from the List
testNum.Remove(testNum.IndexOf(minVal));
testNum.Remove(testNum.IndexOf(maxVal));
// Sum the remaining values up
foreach(int n in testNum)
{
sum = sum + n;
}
return sum;
}
catch
{
throw;
}
Add the input numbers in the List and sum their values excluding min and max values
public static void Main(string[] args)
{
var list = new List<int>();
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Enter number " + i);
int num = Convert.ToInt32(Console.ReadLine());
list.Add(num); //adding the input number in list
}
Sum(list);
}
private static void Sum(List<int> list)
{
int max = list.Max();
int min = list.Min();
int sum = list.Where(x => x != max && x != min).Sum(); //taking the sum of all values exlcuding min and max
Console.WriteLine("Sum is " + sum);
}
I have 5 fields, I want them all to have a generated number between 0 and 100. But, the sum of the 5 fields should be 100.
When I want to give a random number for one field I would do the following:
Random rnd = new Random();
int x= rnd.Next(1, 10);
But how should I do that for multiple fields that needs to have a sum of 100 together?
You can use the following approach:
generate 4 random integers in [0, 100]
sort them, let's denote the sorted values as 0 ≤ x1 ≤ x2 ≤ x3 ≤ x4 ≤ 100
use the following 5 values as the random numbers with sum 100:
N1 = x1
N2 = x2 - x1
N3 = x3 - x2
N4 = x4 - x3
N5 = 100 - x4
It basically corresponds to randomly choosing 4 sectioning points on the [0, 100] interval, and using the lengths of the 5 resulting intervals as the random numbers:
const int k = 5;
const int sum = 100;
Random rnd = new Random();
int[] x = new int[k + 1];
// the endpoints of the interval
x[0] = 0;
x[k] = sum;
// generate the k - 1 random sectioning points
for (int i = 1; i < k; i++) {
x[i] = rnd.Next(0, sum + 1);
}
// sort the sectioning points
Array.Sort(x);
// obtain the k numbers with sum s
int[] N = new int[k];
for (int i = 0; i < k; i++) {
N[i] = x[i + 1] - x[i];
}
In order to make your distribution uniform, you could try the following aproach:
Generate some random numbers.
Normalize them.
Correct the last field to get exactly the expected sum, if needed.
The code:
const int ExpectedSum = 100;
Random rnd = new Random();
int[] fields = new int[5];
// Generate 4 random values and get their sum
int sum = 0;
for (int i = 0; i < fields.Length - 1; i++)
{
fields[i] = rnd.Next(ExpectedSum);
sum += fields[i];
}
// Adjust the sum as if there were 5 random values
int actualSum = sum * fields.Length / (fields.Length - 1);
// Normalize 4 random values and get their sum
sum = 0;
for (int i = 0; i < fields.Length - 1; i++)
{
fields[i] = fields[i] * ExpectedSum / actualSum;
sum += fields[i];
}
// Set the last value
fields[fields.Length - 1] = ExpectedSum - sum;
Live example: https://dotnetfiddle.net/5yXwOP
To achieve a truly random distribution, with every element having the chance to be 100 with a total sum of 100, you can use the following solution:
public static int[] GetRandomDistribution(int sum, int amountOfNumbers)
{
int[] numbers = new int[amountOfNumbers];
var random = new Random();
for (int i = 0; i < sum; i++)
{
numbers[random.Next(0, amountOfNumbers)]++;
}
return numbers;
}
static void Main(string[] args)
{
var result = GetRandomDistribution(100, 5);
}
It increases a random number by one until the sum is reached. This should fulfill all your criterias.
After thinking about it, I prefer the following solution, because it's less likely to generate an equal distribution:
public static int[] GetRandomDistribution2(int sum, int amountOfNumbers)
{
int[] numbers = new int[amountOfNumbers];
var random = new Random();
for (int i = 0; i < amountOfNumbers; i++)
{
numbers[i] = random.Next(sum);
}
var compeleteSum = numbers.Sum();
// Scale the numbers down to 0 -> sum
for (int i = 0; i < amountOfNumbers; i++)
{
numbers[i] = (int)(((double)numbers[i] / compeleteSum) * sum);
}
// Due to rounding the number will most likely be below sum
var resultSum = numbers.Sum();
// Add +1 until we reach "sum"
for (int i = 0; i < sum - resultSum; i++)
{
numbers[random.Next(0, amountOfNumbers)]++;
}
return numbers;
}
For Example.
int sum=100;
int i = 5;
Random rnd = new Random();
while (true)
{
int cur;
--i;
if (i == 0) {
Console.WriteLine(sum + " ");
break;
} else
cur=rnd.Next(1, sum);
sum -= cur;
Console.WriteLine(cur + " ");
}
Live Example: https://dotnetfiddle.net/ltIK40
or
Random rnd = new Random();
int x= rnd.Next(1, 10);
int y= rnd.Next(x,x+10);
int y2=rnd.Next(y,y+10);
int y3=rnd.Next(y2,y2+10);
int y4=100-(x+y+y2+y3);
My approach is this:
var rnd = new Random();
var numbers = Enumerable.Range(0, 5).Select(x => rnd.Next(0, 101)).ToArray().OrderBy(x => x).ToArray();
numbers = numbers.Zip(numbers.Skip(1), (n0, n1) => n1 - n0).ToArray();
numbers = numbers.Concat(new[] { 100 - numbers.Sum() }).ToArray();
This is as uniform as I think is possible.
Create your first random number. After that you take the difference between the value of num1 and 100 as the max def of rnd. But to guarantee that their sum is 100, you have to check at the last num if the sum of all nums is 100. If not the value of your last num is the difference that their sum and 100.
And to simply your code and get a clean strcuture, put that code in a loop and instead of single numbers work with an int[5] array.
private int[] CreateRandomNumbersWithSum()
{
int[] nums = new int[5];
int difference = 100;
Random rnd = new Random();
for (int i = 0; i < nums.Length; i++)
{
nums[i] = rnd.Next(0, difference);
difference -= nums[i];
}
int sum = 0;
foreach (var num in nums)
sum += num;
if (sum != 100)
{
nums[4] = 100 - sum;
}
return nums;
}
I think this is a very simple solution:
public void GenerateRandNr(int total)
{
var rnd = new Random();
var nr1 = rnd.Next(0, total);
var nr2 = rnd.Next(0, total - nr1);
var nr3 = rnd.Next(0, total - nr1 - nr2);
var nr4 = rnd.Next(0, total - nr1 - nr2 - nr3);
var nr5 = total - nr1 - nr2 - nr3 - nr4;
}
EDIT:
Just tested it, works fine for me:
The solution is that it's not the numbers that need to be random so much as the distribution needs to be random. The randomness of the numbers will be a side effect of their random distribution.
So you would start with five random numbers in a given range. The exact range doesn't matter as long as the range is the same for all five, although a broader range allows for more variation. I'd use Random.NextDouble() which returns random numbers between 0 and 1.
Each of those individual numbers divided by the sum of those numbers represents a distribution.
For example, say your random numbers are .4, .7, .2, .5, .2. (Using fewer digits for simplicity.)
The total of those numbers is 2. So now the distributions are each of those numbers divided by the total.
.4 / 2 = .20
.7 / 2 = .35
.2 / 2 = .10
.5 / 2 = .25
.2 / 2 = .10
You'll notice that those distributions will equal 100% or really close to it if there are a lot more decimal places.
The output is going to be each of those distributions times the target number, in this case, 100. In other words, each of those numbers represents a piece of 100.
So multiplying each of those distributions times the target, we get 20, 35, 10, 25, and 100, which add up to 100.
The trouble is that because of rounding your numbers won't always perfectly add up to 100. To fix that you might add one to the smallest number if the sum is less than 100, or subtract one from the largest number of the the sum is greater than 100. Or you could choose to add or subtract on one of the numbers at random.
Here's a class to create the distributions. (I'm just playing around so I haven't exactly optimized this to death.)
public class RandomlyDistributesNumbersTotallingTarget
{
public IEnumerable<int> GetTheNumbers(int howManyNumbers, int targetTotal)
{
var random = new Random();
var distributions = new List<double>();
for (var addDistributions = 0; addDistributions < howManyNumbers; addDistributions++)
{
distributions.Add(random.NextDouble());
}
var sumOfDistributions = distributions.Sum();
var output = distributions.Select(
distribution =>
(int)Math.Round(distribution / sumOfDistributions * targetTotal, 0)).ToList();
RoundUpOutput(output, targetTotal);
return output;
}
private void RoundUpOutput(List<int> output, int targetTotal)
{
var difference = targetTotal - output.Sum();
if (difference !=0)
{
var indexToAdjust =
difference > 0 ? output.IndexOf(output.Min()) : output.IndexOf(output.Max());
output[indexToAdjust]+= difference;
}
}
}
And here's a not-perfectly-scientific unit test that tests it many times over and ensures that the results always total 100.
[TestMethod]
public void OutputTotalsTarget()
{
var subject = new RandomlyDistributesNumbersTotallingTarget();
for (var x = 0; x < 10000; x++)
{
var output = subject.GetTheNumbers(5, 100);
Assert.AreEqual(100, output.Sum());
}
}
Some sample outputs:
5, 30, 27, 7, 31
15, 7, 26, 27, 25
10, 11, 23, 2, 54
The numbers are always going to average to 20, so while 96, 1, 1, 1 is a hypothetical possibility they're going to tend to hover closer to 20.
Okay. Having been burned by my previous attempt at this seemingly trivial problem, I decided to have another go. Why not normalise all the numbers after generation? This guarantees randomness, and avoids O(n log n) performance from a sort. It also has the advantage that even with my basic maths, I can work out that the numbers are uniformly distributed.
public static int[] UniformNormalization(this Random r, int valueCount, int valueSum)
{
var ret = new int[valueCount];
long sum = 0;
for (int i = 0; i < valueCount; i++)
{
var next = r.Next(0, valueSum);
ret[i] = next;
sum += next;
}
var actualSum = 0;
for (int i = 0; i < valueCount; i++)
{
actualSum += ret[i] = (int)((ret[i] * valueSum) / sum);
}
//Fix integer rounding errors.
if (valueSum > actualSum)
{
for (int i = 0; i < valueSum - actualSum; i++)
{
ret[r.Next(0, valueCount)]++;
}
}
return ret;
}
This should also be one of the fastest solutions.
the question asks:
Write a program that reads from the screen two integer numbers min and max and outputs the sum of all squares of integers between min(including) and max(not including). If min is bigger than max, the program should output "min should be smaller than max!". Example:
>4
>9
190 (= 4² + 5² + 6² + 7² + 8²)
>14
>3
min should be smaller than max!
my code:
using System;
namespace ForLoops
{
class SumOfSquares
{
static void Main(string[] args)
{
int sum = 0;
int min = int.Parse(Console.ReadLine());
int max = int.Parse(Console.ReadLine());
for (int i = min; i < max; i = i++)
{
sum = i * i;
}
Console.WriteLine(sum);
}
}
}
I keep getting 68 when i should get 190.
So the answer is you make it to For Loop statement so you can have the 2 examples. Answers at the same time.
int min = int.Parse(Console.ReadLine());
int max = int.Parse(Console.ReadLine());
if(min > max)
{
Console.WriteLine("min should be smaller than max!");
}
else
{
int sum = 0;
for(int i = min; i < max; i++)
{
sum = sum + i*i;
}
Console.WriteLine(sum);
}
There are two flaws in your code:
The post-increment operator i++ increments i, but returns the previous value. So by i = i++ you never increase i because you always reassign the value as it was before the increment. This leads to an infinite loop.
You didn't sum up the products, but only assigned individual productes with sum = i * i;. You need to add them with sum += i*i;.
So your final loop could look like that:
int sum = 0;
for (int i = min; i < max; i++)
sum += i * i;
Linq is altertative to get rid of explicit loops (and let .net do the work for you):
using System.Linq;
...
int min = 4;
int max = 9;
int sum = Enumerable
.Range(min, max - min) // from min to max (not included)
.Sum(x => x * x); // sum up squares