Draw points in a graph - java

`I have an array that every row is a day and 1st column means month, 2nd: day, 3rd: hour, 4th: minute and 5th:second of the sunrise.
I manage to the draw the graph, but I can't draw the line of the values of the array. The x axis is for the days of the year and y axis is the times of sunrise.
The original array has 365 columns, but I thought gicing the example of 4 would be enough.
int[][] Info_Sun = {
{ 1 , 1 , 8 , 23 , 2 } ,
{ 1 , 2 , 8 , 23 , 9 } ,
{ 1 , 3 , 8 , 23 , 13 } ,
{ 1 , 4 , 8 , 23 , 15 } ,
{ 1 , 5 , 8 , 23 , 16 } ,
{ 1 , 6 , 8 , 23 , 14 } ,
{ 1 , 7 , 8 , 23 , 10 } ,
};
float positionX, positionY;
float sunset_pixel, sunrise_pixel, pixel_X, distance;
PFont f;
void setup(){
size(1500, 800);
background(255, 255, 211);
line(220,height/2+200,width-200,height/2+200);
line(width/4-155,55,width/4-155,600);
distance=-21.5;
for(int s=1; s<25; s++){
line(220,height/2+200+distance,width-200,height/2+200+distance);
f= createFont("Consolas", 16, true);
textFont (f,14);
fill(0);
text(s,200,height/2+200+distance);
text("Sortida i posta (hora)", 100, 50);
text("DIES DE L'ANY", 1200, 615);
distance-=21.5;
point(220, 220);
}
pixel_X=25;
for (int i=0; i<Info_Sun.length; i++){
sunrise_pixel=Info_Sun[i][2]*pixel_X+(Info_Sun[i][3]*pixel_X)/60+(Info_Sun[i][4]*pixel_X)/3600;
strokeWeight(3);
stroke(255,0,0);
point (Info_Sun[i][1]+220, sunrise_pixel);
}
}

I modified your code a bunch to simplify it for readability reasons; it may be that you need some of the changes I made for your own code so don't take it the wrong way, but making these modifications helped me to analyze your code.
I noticed that you used pixels instead of lines to link the 'points' of the graph. It makes sense in some contexts but here I choose to use line segments instead. Also, I coded it in a way that uses only the seconds instead of a real month-day-hour-minute-second line, because if I had you would have seen only a straight line. I wanted you to see the actual curve.
So you understand that my code here isn't a copy-and-paste solution to your issue, but instead a methodology that aims to let you understand the principle behind the graph lines.
Here what it'll look like:
To draw a line, you need 2 sets of coordinates: the 1st point and the 2nd point. That's pretty easy to get the basic informations needed by using the Info_Sun array. The only difficulty is to translate these into actual coordinates. It's way easier when you remember these points:
The (0,0) point of this graph's coordinates is actually the (220, 600) point.
The (0,0) point of the sketch is in the left-up corner of the sketch.
The X axis coordinates increases when you go right.
The Y axis coordinates increases when you go down.
So you need to know these 2 distances to be able to calculate a point's coordinates:
The distance between 2 points on the X axis.
The distance between 2 points on the Y axis.
Which are being stored here in the variables distanceX and distanceY. By now you probably have guessed where I'm going with that but I'll go on anyway: the coordinates of a point are as follow:
X == 220 + distanceX * (Index of the point + 1)
Y == 600 - distanceY * Index of the point
// '+ 1' because arrays starts at 0 so day 1 is at index 0
Of course, you have to be aware that you'll need to calculate these coordinates of 2 points every time you draw a line: for the point at the current index, and for the point at index+1. So you can link those 2 points.
This said, here's some code that reflects what I just said. You will notice my modifications in the first part of the code; they are not that important. The part that interests you is at the end.
int[][] Info_Sun = {
{ 1, 1, 8, 23, 2 },
{ 1, 2, 8, 23, 9 },
{ 1, 3, 8, 23, 13 },
{ 1, 4, 8, 23, 15 },
{ 1, 5, 8, 23, 16 },
{ 1, 6, 8, 23, 14 },
{ 1, 7, 8, 23, 10 },
};
float positionX, positionY;
float sunset_pixel, sunrise_pixel, pixel_X, distanceX, distanceY;
PFont f;
void setup() {
size(1500, 800);
background(255, 255, 211);
// drawing axis and titles
// modified for readability
line(220, 600, 1300, 600);
line(220, 600, 220, 55);
distanceY=21.5;
f= createFont("Consolas", 16, true);
textFont (f, 14);
fill(0);
// Hours
for (int i=0; i<24; i++) {
line(220, 600-(distanceY*i), 1300, 600-(distanceY*i));
text(i, 200, 600-(distanceY*i));
}
// Days
distanceX = (1300-220)/(Info_Sun.length+1);
for (int i=1; i<=Info_Sun.length; i++) {
line(220+distanceX*i, 600, 220+distanceX*i, 55);
text(i, 220+distanceX*i, 630);
}
text("Sortida i posta (hora)", 100, 50);
text("DIES DE L'ANY", 1200, 615);
//// drawing curves
strokeWeight(3);
stroke(255, 0, 0);
// THIS IS THE PART WHERE I DRAW THE CURVE
// Using only the seconds so you see a curve and not a straight line
for (int i=0; i<Info_Sun.length-1; i++) {
line(220+distanceX*(i+1), 600-distanceY*Info_Sun[i][4], 220+distanceX*(i+2), 600-distanceY*Info_Sun[i+1][4]);
// Here I calculate 2 points per loop, one for everyday
// so then I link every day by tracing a line between them, and as I start with the day 1 (which is at the index 0 in your table) I use index 0 and 1 for my first line
// that's why loop ends at 'i<Info_Sun.length-1': else I would go out of the bounds of the array
}
}
I'm sure you can adapt this principle to your own ends. I hope this helps!

Related

how to get Math.random() with a unit step

I am trying to create a snake game where i have 400x400 pane and the snake moves by 20 at X and Y axis. By doing this i have created a grid that has step of 20 at X and Y axis.
I want to randomly spawn a fruit at the pane but i want the width and height to be in grid so it should spawn at steps of 20 (0, 20, 40, 60 , 80, ... , 400).
I can use Math.random()*400 to get range but i cant give it unit step.
I found this question which is exactly what i asked but the solution is for lua based math.random():
math.random function with step option?
Here is how i translate the snakes position:
if (input.equals(KeyCode.W.toString()) || input.equals(KeyCode.UP.toString()))
if (snakes.get(0).getY() == 0)
movement.stop();
else
snakes.get(0).setY(snakes.get(0).getY() - 20);
*Snakes is an Arraylist of rectangles that expand as it eats food and i want only the head to eat the food
*Food is a circle that spawns at random location
And here is how i check if they come in contact:
if (food.getCenterX() == snakes.get(0).getX() && food.getCenterY() == snakes.get(0).getY())
score++;
setScore();
I move my snake over the food but the x and y position don't ever match unless i spawn food myself at the grid (say [20,40] or [60, 200]).
Is there another alternative or random with unit step or some other question that i couldn't find here at stackoverflow that can help me?
if you need integer values you can use Random.nextInt(int bound). This will produce coordinates inside your 20x20 matrix.
Random r = new Random();
int x = r.nextInt(20)*20; // values from 0 to 19 inclusively
int y = r.nextInt(20)*20;
If you want a random number out of 0, 20, 40, 60 , 80, ... , 400, then first realize that there are 21 values in that list.
Which means you want a random integer value 0, 1, 2, ..., 20, and then multiply that by 20, to get the step of 20 you want.
Don't use Math.random() for this. Sure it's convenient, but mostly is you want double values. Instead, use one of the following:
new Random() - Use in single-threaded code. Recommended.
You should generally only allocate one, then share it throughout your code.
new SplittableRandom() - Use for parallel computations.
ThreadLocalRandom.current() - Use in multi-threaded code, e.g. web servers.
All 3 have a nextInt(int bound) which returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive).
Example
Random rnd = new Random();
// in some loop generating fruits:
int fruitX = rnd.nextInt(21) * 20;
int fruitY = rnd.nextInt(21) * 20;

Dijkstra Algorithm multiple edges find minimum

i've been trying to find a way to get the minimum distance and path between vertexes in a Graph. I've found a solution in which i adapted to my necessities and it mostly works. Implementation i'm talking about: http://www.vogella.com/tutorials/JavaAlgorithmsDijkstra/article.html#shortestpath_problem
There's only one problem which is the one i'm asking about. As you can see there's only one edge linking two vertexes, and if that's the case i get the results i want.
However, in the test class if i just add another edge linking let's say Vertex 1 and Vertex 2 with a lower weight than the other one like this:
addLane("Edge_0", 0, 1, 85);
addLane("Edge_1", 0, 2, 217);
addLane("Edge_12", 0, 2, 210); //as you can see, added this one
addLane("Edge_2", 0, 4, 173);
addLane("Edge_3", 2, 6, 186);
addLane("Edge_4", 2, 7, 103);
addLane("Edge_5", 3, 7, 183);
addLane("Edge_6", 5, 8, 250);
addLane("Edge_7", 8, 9, 84);
addLane("Edge_8", 7, 9, 167);
addLane("Edge_9", 4, 9, 502);
addLane("Edge_10", 9, 10, 40);
addLane("Edge_11", 1, 10, 600);
In this case (lets say im trying to find the path/distance from Vertex 0 to 10) i still get the correct path (Vertex_0 -> Vertex_2 -> Vertex_7 -> Vertex_9 -> Vertex_10) but if i just do:
dijkstra.getShortestDistance(nodes.get(10)); //to get the distance from the source to the destination which in this case is the Vertex_10
It will give me the wrong distance (527) when it should be 520 because i added another edge from vertex_0 to vertex_2 with a lower weight so it should count that weight and not the previous one which is bigger.
I don't know if i made myself clear but if you have any ideas, i appreciate it.
Note: i didn't paste the rest here so this wouldn't get huge but check the link, it's all there
Because of the method getDistance. This method assumes that the node, target pair is connected by exactly one edge.
private int getDistance(Vertex node, Vertex target) {
for (Edge edge : edges) {
if (edge.getSource().equals(node) && edge.getDestination().equals(target)) {
return edge.getWeight();
}
}
throw new RuntimeException("Should not happen");
}
In this case it will find "Edge_1" with cost 217 before reaching "Edge_12" with cost 210.
A quick fix to this would be to first find the minimum of all edges connecting the two nodes:
private int getDistance(Vertex node, Vertex target) {
Integer weight = null;
for (Edge edge : edges) {
if (edge.getSource().equals(node) && edge.getDestination().equals(target)) {
if (weight == null || edge.getWeight() < weight) {
weight = edge.getWeight();
}
}
}
if (weight == null) {
throw new RuntimeException("Should not happen");
}
return weight;
}

Solve multivariable equation with constraints - Choco

I want to solve a nonlinear multivariable equation with discrete values like this one:
x*y + z + t - 10 = 0
with constraints:
10 < x < 100
etc..
I am trying to do it with Choco library, but I am a little lost.
I found this code:
// 1. Create a Solver
Solver solver = new Solver("my first problem");
// 2. Create variables through the variable factory
IntVar x = VariableFactory.bounded("X", 0, 5, solver);
IntVar y = VariableFactory.bounded("Y", 0, 5, solver);
// 3. Create and post constraints by using constraint factories
solver.post(IntConstraintFactory.arithm(x, "+", y, "<", 5));
// 4. Define the search strategy
solver.set(IntStrategyFactory.lexico_LB(x, y));
// 5. Launch the resolution process
solver.findSolution();
//6. Print search statistics
Chatterbox.printStatistics(solver);
but I don't understand where I place my equation.
I haven't used this library before, but maybe you should simply treat your equation as a constraint?
Yes, more precisely you should decompose your equations into several constraints:
10 < x < 100
becomes
solver.post(ICF.arithm(x,">",10));
solver.post(ICF.arithm(x,"<",100));
and
x*y + z + t - 10 = 0
becomes
// x*y = a
IntVar a = VF.bounded("x*y",-25,25,solver);
solver.post(ICF.times(x,y,a);
// a+z+t=10
IntVar cst = VF.fixed(10,solver);
solver.post(ICF.sum(new IntVar[]{a,z,t},cst));
Best,
Contact us for more support on Choco Solver : www.cosling.com

Check Adjacency in Triangle Array

For a school project i had to code the cracker barrel triangle peg game, http://www.joenord.com/puzzles/peggame/3_mid_game.jpg heres a link to what it is. I made a triangle symmetric matrix to represent the board
|\
|0\
|12\
|345\
|6789\....
public int get( int row, int col )
{
if (row >= col) // prevents array out of bounds
return matrix[row][col];
else
return matrix[col][row];
} //
and here is my get() function that's the form of the matrix. if i try to access get(Row, Column) and row>column i access get(column, row) its set that way in all my methods. This way its easier to prevent out of bounds stuff from happening. empty spots in the triangle are set to 0, all pegs are set to 1. There's unrelated reason why i didn't use a Boolean array. The project is a AI project and to develop a heuristic search algorithm i need access to the number of pegs adjacent to each other. I can easily prevent most duplicates by simply dividing by total/2 since it will count every adjacent in both directions. I don't know how to prevent duplicate checks when i cross that middle line. It only matters on the 0 2 5 and 9 positions. If i really wanted to i could write a separate set of rules for those positions, but that doesn't feel like good coding and is not functional for different sized triangles. any input is welcome and if you need more information feel free to ask.
0, 2, 5, 9 is not an arithmetic progression. The finite differences 2-0 = 2, 5-2 = 3, 9 - 5 = 4 are in arithmetic progression. So the sequence is 0, 0 + 2 = 2, 2 + 3 = 5, 5 + 4 = 9, 9 + 5 = 14, 14 + 6 = 20, etc. They are one less than the triangle numbers 1, 3, 6, 10, 15, 21, etc. The nth triangle number has a short-cut expression, n(n+1)/2 (where n starts at 1, not 0). So your numbers are n(n+1)/2 - 1 for n = 1, 2, 3, ...
Anyway, the situation you are experiencing should tell you that setting it up so get(row,col) == get(col,row) is a bad idea. What I would do instead is to set it up so that your puzzle starts at index 1,1 and increases from there; then put special values -1 in the matrix entries 0,y and x,0 and anything with col > row. You can check for out of bounds conditions just by checking for the value -1 in a cell. Then to count the number of pegs surrounding a position you always do the same thing: check all four adjacent cells for 1's.

How can I get a random value from 0~600 with an interval of 10?

I have an 600x600 screen that I wanted to divide it each 10 squares basically so I can do an snake game, so I need to generate the food into those divisions.
The code I thought of:
x.nextInt(10)*x.nextInt(6)*x.nextInt(10)
This doesn't work, and even if it worked there are multiple values that can achieve 20, lets say 1*2*10, 2*1*10...
So I also thought of this:
(int)(x.nextInt(600)/10)*10
But it doesn't make the interval of 10...
I also thought of this one:
Integer.parseInt(Double.toString(x.nextInt(600)/10))*10
but its pretty much stupid and it doesn't work (gives an error)
if you didn't understood what I want, here is results:
Random pairs (x and y):
10, 60
420, 170
550, 480
80, 600
Here is what I don't want:
14, 52
88, 19
551, 529
415, 550
How can I manage the logic to make the random with this interval?
You could try:
(int)(Math.random() * 60) * 10
Essentially this finds a random int between 0 and 59 then multiplies it by ten so that the numbers have a gap of 10...
Alternativly, you could take advantage of integer division and use
(int)(Math.random() * 600) / 10 * 10
which works on the same principle.
You can solve this by generating an integer between 0 and 60 (or I guess you really want 0 to 59 as a tile is 10 pixels wide and should be on the screen), and then multiplying that integer by 10.
You should use Math.random()
int random = (int )(Math.random() * 60 +1) * 10;
Description:
random() method returns a random number between 0.0 and 0.999. So, you multiply it by 60, so upper limit becomes 0.0 to 59.999, when you add 1, it becomes 1.0 to 60.999, now when you you truncate to int, you get 1 to 60. and then multiply it by 10 to get a multiple of 10 between 10 to 600.
note: If you want from 0 to 60 remove 1 and use
int random = (int )(Math.random() * 61) * 10;
Have a GridSquare class, with coordinates from 0 to 10 (randomly chosen), and then use a toScreenArea function that multiplies the coordinates by the number of pixels per square to find the appropriate spot on the screen to put the squares on.

Categories