Calculate the number of points with integer coordinates inside the ellipse - c#

Calculate the number of points with integer coordinates inside the ellipse1. Hint: check those values for x and y for which
< 1.
Can
and this be fulfilled? And what about y?

There is no point inside the ellipse whose |x| is greater than 13.
If you want to count the number of points with integer coordinates inside the ellipse I would do something like this:
int Points = 0;
for(int x = -13; x <= 13; x++)
{
for(int y = -16; y <= 16; y++)
{
if((Math.Pow(x, 2)/169) + (Math.Pow(y, 2)/256) <= 1)
{
Points++;
}
}
Clarify the question if you want a more detailed answer because it is hard to understand what you are asking.

You can query all the points within
x = {-13 .. 13}
y = {-16 .. 16}
square (follow the hint provided: you should analyze points such that |x| < 13 and |y| < 16). Let's do it with a help of Linq:
int a = 13;
int b = 16;
int result = Enumerable
.Range(-a, a * 2 + 1)
.SelectMany(x => Enumerable
.Range(-b, 2 * b + 1)
.Select(y => (x: x, y: y)))
.Count(p => (double) p.x * p.x / a / a + (double) p.y * p.y / b / b < 1);
Console.Write(result);
Outcome:
647
If you want to include points which on the ellipse (e.g. {13, 0}), just change < 1 into <= 1. In this case you'll have 651 points (points {-13, 0}, {13, 0}, {0, -16}, {0, 16} are added).

Related

Generate vectors given degree of polynomial and list of coeficients

I'm using Unity, and I'm making a generator in which the user inputs a degree of a polynomial plus all of its coefficients. For example, I can have degree 3 and [1,2,3,4], which should be 1x^3 + 2x^2 + 3x^1 + 4x^0.
Here's what I have:
int[] coef = TitleToGame.coeficients;
for (int x = -10; x <= 10; x++)
{
float y = 0;
for (int i = 0; i < TitleToGame.degree - 1; i++)
{
if (i == 0)
{
y = coef[TitleToGame.degree] * Mathf.Pow(x, i);
}
else
{
y += coef[TitleToGame.degree - i] * Mathf.Pow(x, i);
}
Instantiate(block, new Vector3(x, y, 5), Quaternion.identity);
}
}
I'm trying to generate blocks from domain -10 to 10. However, the result looks a bit funky.
Degree 3 with [1,1,1,1] shows a parabola with an extra linear line:
Degree 2 shows a linear line (with an extra unwanted flat line), 1 doesn't show anything, and 4 also shows a parabola. What am I doing wrong?
You're calling Instantiate in the inner for loop, when I persume you want to call it in the outer loop (from -10 to 10).
Also, you probably don't need that if-else statement. Both lines do the same thing.
for (int i = 0; i < TitleToGame.degree - 1; i++)
{
y += coef[TitleToGame.degree - i] * Mathf.Pow(x, i);
}
Instantiate(block, new Vector3(x, y, 5), Quaternion.identity);

Drawing square/game board c#

I want to create a simple square on C# which will be used as a game board.
I am trying to do it using nested loops and have looked into how people make squares this way however I am having difficulty understanding how its done.
This is my code so far for the board:
for (int x = 0; x < 8; x = x + 1)
for (int y = 0; y < 8; y = y + 1)
if (board[x, y] == SquareState.gotCheese)
Console.Write("C");
else
Console.Write("*");
It does print out a * if there is no cheese and a C is there is cheese on the board, however its all in a line and doesn't look like a board. Like this:
*****************C*******
This is the structure for the board if its any help
static SquareState[,] board = new SquareState[8, 8];
The fact that it is writing all in line is because you are now telling the console to create a new line. Console.write() just append strings inline with the precedent.
You for cycle should also be an y-first cycle, so you will cycle each horizontal value (x) and then pass to a new vertical one.
for (int y = 0; y < 8; y++){
for (int x = 0; x < 8; x++){
if (board[x, y] == SquareState.gotCheese)
Console.Write("C");
else
Console.Write("*");
}
Console.WriteLine();
}
If you don't swap the cycles your result will be wrong, for example in a 3 by 3 square where x goes from 0 to 2, from left to right and y goes from 0 to 2 from top to bottom, you will have:
External FOR entering x = 0
Internal FOR entering y = 0
writing the 'cell' (0, 0)
Internal FOR entering y = 1
writing the 'cell' (0, 1)
Internal FOR entering y = 2
writing the 'cell' (0, 2)
writing a new line
External FOR entering x = 1
...
The result of this will be:
(0,0)(0,1)(0,2)
(1,0)(1,1)(1,2)
(2,0)(2,1)(2,2)
That is wrong, it should be:
--------------------> x
(0,0)(1,0)(2,0) |
(0,1)(1,1)(2,1) |
(0,2)(1,2)(2,2) |
V y
You need to print a newline after the inner loop but inside the outer loop.
Console.WriteLine("");
for (int x = 0; x < 8; x = x + 1){
for (int y = 0; y < 8; y = y + 1){
if (board[x, y] == SquareState.gotCheese)
Console.Write("C");
else
Console.Write("*");
Console.WriteLine("");
}
}

Random number with fixed average

I want to generate 100 random numbers between 1 and 10. But the average of those 100 random numbers should be 7. How can I do that? I am doing as follows:
//generating random number
Random random = new Random();
int value = random.Next(1,10);
And storing each value in an array. If the average of 100 items in the array is not 7 then I need to get another 100 random numbers. Can anyone suggest a better way of doing this?
public int RandomNumberThatAveragesToSeven()
{
//Chosen by fair dice roll
//Guaranteed to be random
return 7;
}
Without additional parameters, this above algorithm satisfies each and every requirement.
Return must be between 1 and 10
Average of multiple calls must tend to 7 as n tends to inf.
EDIT Since there was so much controversy on this answer...I added this answer...which is definitely random.
public List<int> ProduceRandom100NumbersWithAverageOfSeven()
{
var rand = new Random();
var seed = rand.Next();
if(seed > 0.5)
{
return new List(Enumerable.Concat(
Enumerable.Repeat(6, 50),
Enumerable.Repeat(8, 50)));
}
else
{
return new List(Enumerable.Concat(
Enumerable.Repeat(8, 50),
Enumerable.Repeat(6, 50)));
}
}
Initialize A[0], ..., A[99] to 1.
Initialize I = {0, 1, ..., 99}.
Repeat steps 4-6 600 times.
Pick random i uniformly from I.
Increment A[i].
If A[i] == 10, then remove i from I.
This will guarantee sum(A) is 700 and thus avg(A) is 7.
Note however that this does not give a uniform distribution over all such arrays of 100 integers in {1, ..., 10} such that they sum to 700. To devise an algorithm for uniformly sampling would be a much more challenging exercise.
Something like this might do it:
public static void Main(string[] args)
{
var randomList = new List<int>();
var random = new Random();
var avg = 0;
while (avg != 7)
{
randomList = new List<int>();
GenerateList(randomList, random);
avg = (int) randomList.Average();
}
for (var i = 0; i < randomList.Count; i++)
{
Console.WriteLine(string.Format("Index: {0}, Number: {1}", i, randomList.ElementAt(i)));
}
}
private static void GenerateList(List<int> refList, Random random)
{
for (var i = 0; i < 100; i++)
{
refList.Add(random.Next(1, 10));
}
}
My 2 cents
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Stopwatch watch = Stopwatch.StartNew();
int count = 100;
Double min = 0;
Double max = 10;
Double target = 7;
Double tolerance = 0.00000001;
Double minAverage = target - tolerance;
Double maxAverage = target + tolerance;
Random r = new Random();
List<Double> numbers = new List<double>();
Double sum = 0;
for (int i = 0; i < count; i++)
{
Double d = RangedDouble(min, max, r);
numbers.Add(d);
sum += d;
}
int Adjustments = 0;
while((sum / count < minAverage || (sum / count) > maxAverage))
{
while ((sum / count) < minAverage)
{
Double oldDbl = numbers.First(d => d < minAverage);
Double newDbl = oldDbl + RangedDouble(minAverage - oldDbl, 10 - oldDbl, r);
numbers.Remove(oldDbl);
sum -= oldDbl;
numbers.Add(newDbl);
sum += newDbl;
Adjustments++;
}
while ((sum / count) > maxAverage)
{
Double oldDbl = numbers.First(d => d > maxAverage);
Double newDbl = oldDbl - RangedDouble(oldDbl - maxAverage, oldDbl, r);
numbers.Remove(oldDbl);
sum -= oldDbl;
numbers.Add(newDbl);
sum += newDbl;
Adjustments++;
}
}
watch.Stop();
int x = 0;
while (x < count)
{
Console.WriteLine("{0:F7} {1:F7} {2:F7} {3:F7}", numbers.Skip(x).Take(1).First(), numbers.Skip(x + 1).Take(1).First(), numbers.Skip(x + 2).Take(1).First(), numbers.Skip(x + 3).Take(1).First());
x += 4;
}
Console.WriteLine();
Console.WriteLine(watch.ElapsedMilliseconds);
Console.WriteLine(numbers.Average());
Console.WriteLine(Adjustments);
Console.ReadKey(true);
}
private static double RangedDouble(Double min, Double max, Random r)
{
return (r.NextDouble() * (max - min) + min);
}
}
}
And the output:
8.1510368 7.2103030 7.9909210 9.6693311
8.2275382 7.2839244 8.8634567 7.9751014
7.8643791 7.2262462 9.8914455 9.6875690
8.4396683 8.4308401 7.5380218 8.6147181
8.2760663 7.7399011 7.4312152 9.2115622
9.7850111 9.1061378 9.8672965 9.5610411
7.0415607 8.8446195 9.3562218 8.5279759
7.5227340 9.3572417 9.8927997 9.5880645
9.0908564 7.0918394 9.6213258 8.6528169
9.3803283 9.6869223 1.4006790 3.3310691
7.0719214 2.6370854 9.7558776 8.9180391
3.0486700 5.0082988 8.8624504 5.0497899
0.9692377 7.7140550 9.8495115 6.4933865
4.4939760 9.3187625 5.4353003 6.5405668
9.5693118 5.0339998 6.9644440 4.6902072
0.5241568 9.7748420 0.1406617 8.4731427
9.8064604 6.3113773 0.8628048 9.2417028
8.9148867 9.3111336 3.2424080 9.6710544
4.3794982 5.1687718 9.8207783 0.3283217
9.8321869 2.8093698 7.4377070 4.1130959
5.9840738 9.2560763 3.6691865 2.5498863
7.3242246 7.0179332 5.8906831 9.3340545
0.3735044 7.2442886 0.4409532 9.0749754
9.6716409 8.4097246 2.8069123 7.2970794
2.4964238 8.2826350 9.1115787 3.7373927
1
6.99992266645471
729
edit: changing the code to always result in an average of exactly 7.
This is basically an optimized version of what you were doing already. Instead of generating another 100 numbers, it generates only 10 before doing the check.
using System.Collections.Generic;
using System.Linq;
var r = new Random();
var numbers = new List<int>();
while (numbers.Count < 100)
{
var stack = new Stack<int>();
for (int i = 0; i < 10; i++)
{
stack.Push(r.Next(10));
}
if (stack.Sum() == 70)
{
numbers.AddRange(stack);
}
}
Console.WriteLine(numbers.Average());
OK, it could be tricky to do something like that.
If you need to obtain 100 different numbers and you need that they average will be 7, you'll need them to sum 700.
You'll need to keep track of each number and their total sum. While 700 minus the sum of your obtained so far values is lesser than 10 * the amount of numbers you haven't obtained yet, you can continue obtaining pure random values.
When the moment comes that your obtained values sum is lesser than the values you need to obtain, then you change that last number by a 10, put a 10 in the rest of numbers you need to the end of your list and, on the last number, you get the difference between 700 and the sum of your 99 previous pseudo-random values.
Shuffle your array et voilá, you have a 100 pseudo-random array with numbers from 1 to 10 whose average is 7. Surely it will have more 10s than it'll be desired, but sure you'll be able to fine tune this "algorithm" to make it a bit less 10 prone.
Mmmm, wait a moment, what if you get random values that have an average above 7? You'll need to track also that the sum of your current values is lesser than the numbers you have yet to obtain. If you surpass this value in any moment you'll need to convert your last number to a 1, put a 1 on the rest of your needed values and obtain again your last number as the difference between 700 and your 99 earlier values.
Like the other answers have posted, since we know the length we can get the average by just focusing on the total sum.
I'd solve it recursively. In the base case, we need to generate a list of length 1 which sums to some number s. That's easy: the list just contains s:
rand 1 s = [s]
Now we can solve the recursive case rand n s where n is the desired list length and s is the desired sum. To do this, we'll generate two lists x and y and concatenate them together, subject to the given constraints:
length x + length y = n
sum x + sum y = s
1 * length x <= sum x -- Minimum value is 1
10 * length x >= sum x -- Maximum value is 10
1 * length y <= sum y
10 * length y >= sum y
These equations/inequalities can't be solved yet, so the first thing we do is choose the length of the lists. To keep down the level of recursion we can choose lx = round (n / 2) then set the following:
length x = lx
length y = n - lx = ly
Hence:
sum x + sum y = s
1 * lx <= sum x
10 * lx >= sum x
1 * ly <= sum y
10 * ly >= sum y
We use the first equation to rewrite the inequalities:
1 * lx <= sum x
10 * lx >= sum x
1 * ly <= s - sum x
10 * ly >= s - sum x
We can rearrange the bottom two to make sum x the subject:
sum x + 1 * ly <= s
sum x + 10 * ly >= s
sum x <= s - 1 * ly
sum x >= s - 10 * ly
We know ly and s so these give us definite bounds for sum x, which we combine by taking the largest lower bound and the smallest upper bound:
max (1 * lx) (s - 10 * ly) <= sum x
min (10 * lx) (s - 1 * ly) >= sum x
These bounds make sense: they take into account the cases where every element in x is 1 or 10 and they ensure that the remainder can be handled by sum y. Now we just generate a random number B between these bounds, then set:
sum x = B
sum y = s - B
From that, we can perform our recursion (assuming some random number function randInt):
rand n s = let lx = round (n / 2)
ly = n - lx
lower = max (1 * lx) (s - 10 * ly)
upper = min (10 * lx) (s - 1 * ly)
b = randInt lower upper
in rand lx b ++ rand ly (s - b)
Now your list can be generated by calling:
myList = rand 100 700
I've written this in Haskell for brevity, but it's just arithmetic so should translate to C# easily. Here's a Python version if it helps:
def rand(n, s):
if n == 1:
return [s]
lx = int(n / 2)
ly = n - lx
lower = max(1 * lx, s - 10 * ly)
upper = min(10 * lx, s - 1 * ly)
b = randint(lower, upper)
result = rand(lx, b)
result.extend(rand(ly, s - b))
return result
Please point out any mistakes I've made!
Edit: Although I doubt it's the case for C#, in some languages we could make this simpler and more efficient by using tail-recursion. First we switch to generating one element at a time:
-- Generate one number then recurse
rand 1 s = [s]
rand n s = let ly = n - 1
lower = max 1 (s - 10 * ly)
upper = min 10 (s - 1 * ly)
x = randInt lower upper
in x : rand (n - 1) s
Then we accumulate the result rather than building up unfinished continuations:
rand' xs 1 s = s:xs
rand' xs n s = let ly = n - 1
lower = max 1 (s - 10 * ly)
upper = min 10 (s - 1 * ly)
x = randInt lower upper
in rand' (x:xs) (n-1) s
rand = rand' []
this function is for get fixed average between n Records randomly.
that here in my answer "n" is declared as "count".
https://github.com/amingolmahalle/RandomGenerateDataBetweenTwoNumber
public void ProccessGenerateData(WorkBook workBookData, out List<double> nomreList, out int adjustmentsVal)
{
try
{
nomreList = new List<double>();
adjustmentsVal = 0;
int count = workBookData.NumberStudents;
double min = workBookData.Min;
double max = workBookData.Max;
double target = workBookData.FixedAvg;
double tolerance = workBookData.Tolerance;
double minAverage = Math.Round(target - tolerance, 2);
double maxAverage = Math.Round(target + tolerance, 2);
Random r = new Random(DateTime.Now.Millisecond);
List<double> listNomre = new List<double>();
double sum = 0;
for (int i = 0; i < count; i++)
{
double d = Math.Round(RangedDouble(min, max, r), 2);
listNomre.Add(d);
sum += d;
sum = Math.Round(sum, 2);
}
int adjustments = 0;
while (Math.Round((sum / count), 2) < minAverage || Math.Round((sum / count), 2) > maxAverage)
{
if (Math.Round((sum / count), 2) < minAverage)
{
double oldDbl1 = listNomre.First(d => d < minAverage);
//min<a1+x1<max --> a1 is oldDbl1 , x1 --> Unknown
double newDbl1 = Math.Round(oldDbl1 + RangedDouble(min-oldDbl1, max - oldDbl1, r), 2);
listNomre.Remove(oldDbl1);
sum -= oldDbl1;
sum = Math.Round(sum, 2);
listNomre.Add(newDbl1);
sum += newDbl1;
sum = Math.Round(sum, 2);
adjustments++;
continue;
}
double oldDbl = listNomre.First(d => d > maxAverage);
//min<a1-x1<max --> a1 is oldDbl , x1 --> Unknown
double newDbl = Math.Round(oldDbl - RangedDouble(oldDbl-max, oldDbl - min, r), 2);
listNomre.Remove(oldDbl);
sum -= oldDbl;
sum = Math.Round(sum, 2);
listNomre.Add(newDbl);
sum += newDbl;
sum = Math.Round(sum, 2);
adjustments++;
}
nomreList = listNomre;
adjustmentsVal = adjustments;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
throw;
}
}
private static double RangedDouble(double min, double max, Random r)
{
//Function RangedDouble => Random Number Between 2 Double Numbers
//Random.NextDouble => returns a double between 0 and 1
return Math.Round( r.NextDouble() * (max - min) + min,2);
}
class Program
{
static void Main(string[] args)
{
var rnd = new Random();
var min = 1;
var max = 20;
var avg = 15;
var count = 5000;
var numbers = new List<int>();
for (var i = 0; i < count; i++)
{
var random1 = rnd.Next(min, avg + 1);
var random2 = rnd.Next(avg + 2, max + 1);
var randoms = new List<int>();
randoms.AddRange(Enumerable.Repeat<int>(random2, avg - min));
randoms.AddRange(Enumerable.Repeat<int>(random1, max - avg));
var generatedNumber = randoms[rnd.Next(randoms.Count)];
numbers.Add(generatedNumber);
}
numbers = numbers.OrderBy(x => x).ToList();
var groups = numbers.GroupBy(x => x).OrderByDescending(x => x.Count()).ToList();
groups.ForEach(x => Console.WriteLine($"{x.Key}: {x.Count()}"));
Console.WriteLine($"Average: {numbers.Average(x => x)}");
Console.WriteLine($"Count of numbers: {groups.Count}");
}
}
This method generates a random number sequence then keeps adding/subtracting until we get the correct total (700), so long as the number we are altering is still in the range of 1-10
List<int> randomNumbers = new List<int>();
for (int i = 0; i < 100; i++) {
numbers.Add(r.Next(1, 10));
}
int total = randomNumbers.Sum();
// Now fiddle until we get the correct total (700)
if (total < 700) {
while (total < 700) {
for (int i = 0; i < 100; i++) {
if (numbers[i] < 10) {
numbers[i]++;
total = randomNumbers.Sum();
if (total == 700) break;
}
}
}
}
else if (total > 700) {
while (total > 700) {
for (int i = 99; i >= 0; i--) {
if (numbers[i] > 0) {
numbers[i]--;
total = randomNumbers.Sum();
if (total == 700) break;
}
}
}
}

How does this coordinate conversion achieve the desired result?

The following code snippet, with width=2,height=2
int maxI = width + height;
for (int i = 1; i <= maxI; i++) {
int startJ = Math.Max(0, i - width);
int maxJ = Math.Min(i, height);
for (int j = startJ; j <= maxJ; j++) {
int x = i - j;
int y = j;
DoSomething(x,y);}}
Will call DoSomething with the following x,y pairs:
1: X=1,Y=0
2: X=0,Y=1 (Diagram: 0,0
3: X=2,Y=0 at bottom left)
4: X=1,Y=1 5 7 8
5: X=0,Y=2 2 4 6
6: X=2,Y=1 # 1 3
7: X=1,Y=2
8: X=2,Y=2
This is the desired result; to iterate a rectangle starting from 0,0 but expanding diagonally rather than (the much more popular) [y*width+x]. However, I'm baffled by the maxI=width+height and x=i-j calculations. How does this conversion work?
The thing to realize here is that x + y is a constant for each cell in a particular diagonal. For example, cells 3, 4, and 5 have coordinates {2, 0}; {1, 1}; {0, 2}. Notice that each of those add up to 2.
So maxI is really the maximum value of one of these sums. Since {width, height} is the top right, the sum for that diagonal is width + height. So that's where that comes from.
The i - j part comes about because it's basically solving the above equation. Each value of i is the sum of the coordinates. j is chosen to be the y-coordinate of a cell within that diagonal. Since we know x + y = i and that y = j, we get that x + j = i or x = i - j.
This can be also explained by geometric transformations:
1) Translation, so the rectangle's center is in origin:
x' = x - width/2
bounds: [-width/2,width/2)
y' = y - height/2
bounds: [-height/2,height/2)
2) Rotation by 45 degrees:
x'' = x'cos(45) - y'sin(45) = (sqrt(2)/2)x' - (sqrt(2)/2)y'
y'' = x'sin(45) + y'cos(45) = (sqrt(2)/2)x' + (sqrt(2)/2)y'
3) Scaling by sqrt(2)/2:
x''' = x' - y' = x - width/2 - y + height/2
bounds: [-width/2-height/2,width/2+height/2)
y''' = x' + y' = x - width/2 + y - height/2
bounds: [-width/2-height/2,width/2+height/2)
4) Translating back only on x axis:
x'''' = x''' + width/2 = x - y + height/2
bounds: [-height/2,width/2+height/2)
y'''' = y'''
bounds: [-width/2-height/2,width/2+height/2)
5) Introducing parametric variables:
i = y'''' + width/2 + height/2
bounds: [0,width+height)
j = x'''' + y'''' - width/2 - height/2
bounds: [-width-3*height/2,width/2+height/2)
For this transformation you get that:
x = i - j
y = j
And it will iterate point by point through diagonals going from bottom-right to top-left corner of the screen. Max and Min in the code you presented bound the result to a subset of these diagonals, representing a rectangle.

Need working C# code to find neighbors of an element in a 2-dimentional array

say array with 12 rows and 10 columns
int[,] array = new int[12,10];
and I select 0,0 it must return all neighbors of 0,0
which will be
0,1
1,1
1,0
say I want neighbors of 2,3 it must return an array of neighbors
1,2
1,3
1,4
2,2
2,4
3,1
3,2
3,3
element [x, y]
neighbor1 = x + 1, y;
neighbor2 = x - 1, y;
neighbor3 = x, y + 1;
neighbor4 = x, y - 1;
neighbor5 = x + 1, y + 1;
neighbor6 = x + 1, y - 1;
neighbor7 = x - 1, y + 1;
neighbor8 = x - 1, y - 1;
Obviously you need to check if those elements coordinates exists just in case the element is in a "border" of the matrix. Hard? I say no.
Braindead and non-performing but illustrative and quick:
int[,] array = new int[12,10];
int refx=0, refy=10;
var neighbours = from x in Enumerable.Range(0,array.GetLength(0)).Where(x => Math.Abs(x - refx)<=1)
from y in Enumerable.Range(0,array.GetLength(1)).Where(y => Math.Abs(y - refy)<=1)
select new {x,y};
neighbours.ToList().ForEach(Console.WriteLine);
alternatively
neighbours = from x in Enumerable.Range(refx-1, 3)
from y in Enumerable.Range(refy-1, 3)
where x>=0 && y>=0 && x<array.GetLength(0) && y<array.GetLength(1)
select new {x,y};
neighbours.ToList().ForEach(Console.WriteLine);

Categories