Related
I need help to debug my code for the following challenge - https://www.hackerrank.com/challenges/maximizing-mission-points/problem
I've followed the lines of code from - https://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/.
My code is as below :
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
class SegmentTreeRMQ {
int st[][];
int minVal(int x, int y) {
return (x < y) ? x : y;
}
int getMid(int s, int e) {
return s + (e - s) / 2;
}
int RMQUtil(int sx1, int sy1, int sx2, int sy2, int x1, int y1, int x2, int y2, int index1, int index2)
{
// If segment of this node is a part of given range, then
// return the min of the segment
if (x1 <= sx1 && y1 <= sy1 && x2 >= sx2 && y2 >= sy2)
return st[index1][index2];
// If segment of this node is outside the given range
if ((sx1 < x1 && sy1 < y1) || (sx2 > x2 && sy2 > y2))
return Integer.MIN_VALUE;
// If a part of this segment overlaps with the given range
int midx = getMid(sx1, sx2);
int midy = getMid(sy1, sy2);
return minVal(RMQUtil(sx1, sy1, midx, midy, x1, y1, x2, y2, 2 * index1 + 1, 2 * index2 + 1),
RMQUtil(midx + 1, midy + 1, sx2, sy2, x1, y1, x2, y2, 2 * index1 + 2, 2 * index2 + 2));
}
int RMQ(int n, int m, int x1, int y1, int x2, int y2)
{
// Check for erroneous input values
/*if (x1< 0 || x2 > n - 1 || x1 > x2) {
System.out.println("Invalid Input "+x1+" "+x2);
return -1;
}
if (y1< 0 || y2 > m - 1 || y1 > y2) {
System.out.println("Invalid Input");
return -1;
}*/
return RMQUtil(0, 0, n - 1, m - 1, x1, y1, x2, y2, 0, 0);
}
int constructSTUtil(int arr[][], int x1, int y1, int x2, int y2, int si, int sj)
{
// If there is one element in array, store it in current
// node of segment tree and return
if (x1 == x2 && y1 == y2) {
st[si][sj] = arr[x1][y1];
return arr[x1][y1];
}
// If there are more than one elements, then recur for left and
// right subtrees and store the minimum of two values in this node
int midx = getMid(x1, x2);
int midy = getMid(y1, y2);
st[si][sj] = minVal(constructSTUtil(arr, x1, y1, midx, midy, si * 2 + 1, sj * 2 + 1),
constructSTUtil(arr, midx + 1, midy + 1, x2, y2, si * 2 + 2, sj * 2 + 2));
return st[si][sj];
}
void constructST(int arr[][], int n, int m)
{
// Allocate memory for segment tree
//Height of segment tree
int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));
int y = (int) (Math.ceil(Math.log(m) / Math.log(2)));
//Maximum size of segment tree
int max_size_x = 2 * (int) Math.pow(2, x) - 1;
int max_size_y = 2 * (int) Math.pow(2, y) - 1;
st = new int[max_size_x][max_size_y]; // allocate memory
// Fill the allocated memory st
constructSTUtil(arr, 0, 0, n - 1, m - 1, 0, 0);
}
}
class City implements Comparator<City> {
int latitude;
int longitude;
int height;
int points;
public City() {
}
public int compare(City c1, City c2){
return c1.height - c2.height;
}
}
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int d_lat = in.nextInt();
int d_long = in.nextInt();
ArrayList<City> cities = new ArrayList<City>();
for(int a0 = 0; a0 < n; a0++){
int latitude = in.nextInt();
int longitude = in.nextInt();
int height = in.nextInt();
int points = in.nextInt();
// Write Your Code Here
City city = new City();
city.latitude = latitude;
city.longitude = longitude;
city.height = height;
city.points = points;
cities.add(city);
}
Collections.sort(cities, new City());
int max_lat = Integer.MIN_VALUE;
int min_lat = Integer.MAX_VALUE;
int max_long = Integer.MIN_VALUE;
int min_long = Integer.MAX_VALUE;
for(City city : cities){
if(city.latitude > max_lat){
max_lat = city.latitude;
}
if(city.latitude < min_lat){
min_lat = city.latitude;
}
if(city.longitude > max_long){
max_long = city.longitude;
}
if(city.longitude < min_long){
min_long = city.longitude;
}
}
int lat_diff = max_lat-min_lat;
int long_diff = max_long-min_long;
int[][] arr = new int[lat_diff+1][long_diff+1];
for(City city : cities){
arr[city.latitude - min_lat ][city.longitude - min_long]=city.points;
}
SegmentTreeRMQ tree = new SegmentTreeRMQ();
tree.constructST(arr, lat_diff, long_diff);
int max_till_now = Integer.MIN_VALUE;
int max_till_city = 0;
for(City city : cities){
int x = city.latitude;
int y = city.longitude;
max_till_city = tree.RMQ(lat_diff+1,long_diff+1,x-d_lat,y-d_long,x+d_lat,y+d_long);
if(max_till_now < max_till_city){
max_till_now = max_till_city;
}
}
System.out.println(max_till_now);
in.close();
}
}
What I need to know is that do i require an update query as well? If yes please send me some pointers.
Thanks,
Apoorv Srivastava
I have a convex quadrilateral. I know the four points, and I have its four lines in the format mx + b (from the top going clockwise). Quadrilateral is a class shown below:
import java.awt.Point;
import java.awt.Polygon;
public final class Quadrilateral extends Polygon {
private static final long serialVersionUID = 794866732073166739L;
public final Point p1, p2, p3, p4;
public final Line l12, l23, l34, l41;
public Quadrilateral(Point p1, Point p2, Point p3, Point p4) {
super(new int[] { p1.x, p2.x, p3.x, p4.x }, new int[] { p1.y, p2.y,
p3.y, p4.y }, 4);
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
this.p4 = p4;
this.l12 = Quadrilateral.getLine(p1, p2);
this.l23 = Quadrilateral.getLine(p2, p3);
this.l34 = Quadrilateral.getLine(p3, p4);
this.l41 = Quadrilateral.getLine(p4, p1);
}
public static final Line getLine(Point p1, Point p2) {
if (p1.x > p2.x) {
return Quadrilateral.getLine(p2, p1);
} else {
int x1 = p1.x;
int x2 = p2.x;
int y1 = p1.y;
int y2 = p2.y;
int xdiff = x2 - x1;
int ydiff = y1 - y2;
double m = (double) ydiff / (double) xdiff;
double b = y1 - m * x1;
return new Line(m, b);
}
}
public Quadrilateral[][] grid(int x, int y) {...?...}
}
What I want to do is to divide an instance of Quadrilateral into an x by y grid of Quadrilaterals, sorted in a Quadrilateral[][]. How would I do this efficiently?
You have to interpolate to create the points in between. Do this for each component like so:
p1.x * (1-t) + p2.x * t
Where t goes from 0 to 1.
Create a grid of x+1 by y+1 points this way. Interpolate between two pairs of points of the outline that are neighbours (not connected via diagonals). Then interpolate again between the two points you receive as a result. Set t on each interpolation according to the values of x and y and what iteration step you are currently calculating.
From this grid of points you can build the grid of quadriliterals by iterating over the the points in steps of size 2.
I've finally found out the answer! It's quite lengthy. I've included the whole Quadrilateral.java file below:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public final class Quadrilateral extends Polygon {
private static final long serialVersionUID = 794866732073166739L;
public final Point p1, p2, p3, p4;
public final Line l12, l23, l34, l41;
public Quadrilateral(Point p1, Point p2, Point p3, Point p4) {
super(new int[] { p1.x, p2.x, p3.x, p4.x }, new int[] { p1.y, p2.y,
p3.y, p4.y }, 4);
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
this.p4 = p4;
this.l12 = Quadrilateral.getLine(p1, p2);
this.l23 = Quadrilateral.getLine(p2, p3);
this.l34 = Quadrilateral.getLine(p3, p4);
this.l41 = Quadrilateral.getLine(p4, p1);
}
public static Quadrilateral formatted(Quadrilateral quadrilateral, int w,
int h) {
return new Quadrilateral(Format.format(quadrilateral.p1, w, h),
Format.format(quadrilateral.p2, w, h), Format.format(
quadrilateral.p3, w, h), Format.format(
quadrilateral.p4, w, h));
}
public Quadrilateral[][] grid(int x, int y) {
Point[][] points = new Point[x + 1][y + 1];
for (int ix = 0; ix <= x; ix++) {
for (int iy = 0; iy <= y; iy++) {
points[ix][iy] = this.getPointAt(x, y, ix, iy);
}
}
Quadrilateral[][] qs = new Quadrilateral[x][y];
for (int ix = 0; ix < x; ix++) {
for (int iy = 0; iy < y; iy++) {
qs[ix][iy] = new Quadrilateral(points[ix][iy],
points[ix + 1][iy], points[ix + 1][iy + 1],
points[ix][iy + 1]);
}
}
return qs;
}
public ArrayList<ArrayList<Quadrilateral>> gridList(int x, int y) {
Point[][] points = new Point[x + 1][y + 1];
for (int ix = 0; ix <= x; ix++) {
for (int iy = 0; iy <= y; iy++) {
points[ix][iy] = this.getPointAt(x, y, ix, iy);
}
}
ArrayList<ArrayList<Quadrilateral>> qs = new ArrayList<>(0);
for (int ix = 0; ix < x; ix++) {
qs.add(new ArrayList<>(y));
for (int iy = 0; iy < y; iy++) {
qs.get(ix).add(
new Quadrilateral(points[ix][iy], points[ix + 1][iy],
points[ix + 1][iy + 1], points[ix][iy + 1]));
}
}
return qs;
}
public Point getPointAt(int xdiv, int ydiv, int xiter, int yiter) {
Point n1 = this.getTopPointAt(xdiv, xiter);
Point n2 = this.getRightPointAt(ydiv, yiter);
Point n3 = this.getBottomPointAt(xdiv, xiter);
Point n4 = this.getLeftPointAt(ydiv, yiter);
Line h = Quadrilateral.getLine(n4, n2);
Line v = Quadrilateral.getLine(n1, n3);
return h.intersect(v, n2.x, n1.x);
}
public Point getTopPointAt(int div, int iter) {
Point start = this.p1;
Point end = this.p2;
int xdiff = end.x - start.x;
int ydiff = end.y - start.y;
int xadd = (int) ((double) xdiff / (double) div) * iter;
int yadd = (int) ((double) ydiff / (double) div) * iter;
int x = start.x + xadd;
int y = start.y + yadd;
return new Point(x, y);
}
public Point getBottomPointAt(int div, int iter) {
Point start = this.p4;
Point end = this.p3;
int xdiff = end.x - start.x;
int ydiff = end.y - start.y;
int xadd = (int) ((double) xdiff / (double) div) * iter;
int yadd = (int) ((double) ydiff / (double) div) * iter;
int x = start.x + xadd;
int y = start.y + yadd;
return new Point(x, y);
}
public Point getLeftPointAt(int div, int iter) {
Point start = this.p4;
Point end = this.p1;
int xdiff = end.x - start.x;
int ydiff = end.y - start.y;
int xadd = (int) ((double) xdiff / (double) div) * iter;
int yadd = (int) ((double) ydiff / (double) div) * iter;
int x = start.x + xadd;
int y = start.y + yadd;
return new Point(x, y);
}
public Point getRightPointAt(int div, int iter) {
Point start = this.p3;
Point end = this.p2;
int xdiff = end.x - start.x;
int ydiff = end.y - start.y;
int xadd = (int) ((double) xdiff / (double) div) * iter;
int yadd = (int) ((double) ydiff / (double) div) * iter;
int x = start.x + xadd;
int y = start.y + yadd;
return new Point(x, y);
}
public static final Line getLine(Point p1, Point p2) {
if (p1.x < p2.x) {
return Quadrilateral.getLine(p2, p1);
} else {
int x1 = p1.x;
int x2 = p2.x;
int y1 = p1.y;
int y2 = p2.y;
int xdiff = x2 - x1;
int ydiff = y2 - y1;
double m = (double) ydiff / (double) xdiff;
double b = y1 - m * x1;
return new Line(m, b);
}
}
public void paint(Graphics g, BufferedImage image) {
int w = image.getWidth();
int h = image.getHeight();
Quadrilateral[][] grid = this.grid(w, h);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
g.setColor(new Color(image.getRGB(x, y), true));
g.fillPolygon(grid[x][y]);
}
}
}
}
I have to implement a scanline algorithm from our professor but I don't really understand how I get the intersection points from the scanline with a polygon.
Here is the algorithm:
I implemented my own polygon(with methods like paint(), contains() and so on) already and I have all edges from the polygon saved in an array like this:
int[] pointsX;
int[] pointsY;
and I have the min and max values for x and y saved in
int ymin, ymax, xmin, xmax;
So my first thought is that I have to create a scanline starting from 0,ymin and check in a loop if the next point is inside the polygon. I implemented this method like this:
public boolean contains(Point test) {
boolean result = false;
java.awt.Polygon polygon = new java.awt.Polygon(pointsX, pointsY, pointsX.length);
if (polygon.contains(test)) {
result = true;
}
return result;
}
So when the next point is inside the polygon, I have a intersection point and so on. For this i have this loop:
ArrayList<Point> intersectionPoints = new ArrayList<>();
wasInside = false;
for (int yTemp = ymin; yTemp <= ymax; yTemp++) {
for (int xTemp = xmin; xTemp <= xmax; xTemp++) {
if (wasInside != this.contains(new Point(xTemp, yTemp))) {
intersectionPoints.add(new Point(xTemp, yTemp));
wasInside = !wasInside;
}
}
}
But I got a hint that this is no proper solution from my stackoverflow question.
Can someone give me a hint, how I can start implementing the algorithm from my professor? Where do I get the x1,y1,x2,y2,c points? I know that these are the edges but how do I know which edges do I have to take?
EDIT:
OK, now I have all Edges sorted by their y values. Can I calculate the intersection points with the given formula Sx=x1+(x2-x1)/...?
My first try looks like this:
for (int c = ymin; c <= ymax; c++) {
for (int xTemp = xmin; xTemp <= xmax; xTemp++) {
for (int currentEdge = 0; currentEdge < edges.size() - 1; currentEdge++) {
int x1 = edges.get(currentEdge).x;
int x2 = edges.get(currentEdge + 1).x;
int y1 = edges.get(currentEdge).y;
int y2 = edges.get(currentEdge + 1).y;
if ((y1 <= c && y2 > c) || (y2 <= c && y1 > c)) {
intersectionPoints.add(new Point((x1 + (x2 - x1) / (y2 - y1) * (c - y1)),c));
}
}
}
}
But this seems to be wrong, because I get a lot of wrong Points in intersectionPoints.
The problem was that I calculated with int numbers and an int divided by another int results in inaccuracies. So just doing this with double numbers solved it.
This is how I calculate the intersection points:
edges is a ArrayList<Point> containing the edge points.
ymin is the lowest y value and `ymax`` the highest one.
for (int yTemp = ymin; yTemp <= ymax; yTemp++) {
ArrayList<Point> intersectionPoints = new ArrayList<>();
for (int p = 0; p < edges.size() - 1; p++) {
int x1, x2, y1, y2;
double deltax, deltay, x;
x1 = edges.get(p).x;
y1 = edges.get(p).y;
x2 = edges.get(p + 1).x;
y2 = edges.get(p + 1).y;
deltax = x2 - x1;
deltay = y2 - y1;
int roundedX;
x = x1 + deltax / deltay * (yTemp - y1);
roundedX = (int) Math.round(x);
if ((y1 <= yTemp && y2 > yTemp) || (y2 <= yTemp && y1 > yTemp)) {
intersectionPoints.add(new Point(roundedX, yTemp));
}
}
//for the last interval
int x1, x2, y1, y2;
x1 = edges.get(edges.size() - 1).x;
y1 = edges.get(edges.size() - 1).y;
x2 = edges.get(0).x;
y2 = edges.get(0).y;
if ((y1 <= yTemp && y2 > yTemp) || (y2 <= yTemp && y1 > yTemp)) {
intersectionPoints.add(new Point(x1 + (x2 - x1) / (y2 - y1) * yTemp - y1, yTemp));
}
//you have to sort the intersection points of every scanline from the lowest x value to thr highest
Collections.sort(intersectionPoints, new SortXPoints());
pointsOfScanline.add(intersectionPoints);
This will give you an ArrayList containing ArrayLists of scanline points for every Scanline. So you just have to draw them with drawLine(x1, y2, x2, y2).
I need to make perlin noise like in AS3.0:
bitmapData.perlinNoise(baseX, baseY, numOctaves,
randomSeed, stitch, fractalNoise, grayScale, offsets);
It's seamless noise:
I found a lot of material about it, but I can't make it like in my as3.0 image. Java code:
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Noise extends JPanel{
public static int octaves = 4;
public static int size = 128;
public static float[][][] noise = new float[size][size][octaves];
public static float[][] perlinnoise = new float[size][size];
public static float p = (float) 1/4;
public static Random gen = new Random();
public static float GenerateNoise() {
return gen.nextFloat();
}
public static float SmoothNoise(int x, int y, int z) {
try{
float corners = (noise[x - 1][y - 1][z] + noise[x + 1][y - 1][z] + noise[x - 1][y + 1][z] + noise[x + 1][y + 1][z]) / 16;
float sides = (noise[x - 1][y][z] + noise[x + 1][y][z] + noise[x][y - 1][z] + noise[x][y + 1][z]) / 8;
float center = noise[x][y][z] / 4;
return corners + sides + center;
}catch(Exception e) {
return 0;
}
}
public static float InterpolatedNoise(float x, float y, int pX, int pY, int pZ) {
int intX = (int) x;
int intY = (int) y;
float fracX = x - intX;
float fracY = y - intY;
float v1 = SmoothNoise(pX, pY, pZ);
float v2 = SmoothNoise(pX + 1, pY, pZ);
float v3 = SmoothNoise(pX, pY + 1, pZ);
float v4 = SmoothNoise(pX + 1, pY + 1, pZ);
float i1 = Interpolate(v1, v2, fracX);
float i2 = Interpolate(v3, v4, fracX);
return Interpolate(i1, i2, fracY);
}
public static float Interpolate(float a, float b, float x) {
float ft = (float) (x * 3.1415927);
float f = (float) ((1 - Math.cos(ft)) * 0.5);
return (float) (a * (1 - f) + b * f);
}
public static float Perlin2D(float x, float y, int posX, int posY, int posZ) {
float total = 0;
for(int i = 0; i < octaves; i++) {
double f = Math.pow(2, i);
double a = Math.pow(p, i);
total = (float) (total + InterpolatedNoise((float)(x * f), (float)(y * f), posX, posY, posZ) * a);
}
return total;
}
public static void main(String [] args) {
for(int z = 0; z < octaves; z++) {
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
noise[x][y][z] = GenerateNoise();
}
}
}
for(int z = 0; z < octaves; z++) {
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
perlinnoise[x][y] = Perlin2D(x / (size - 1), y / (size - 1), x, y, z) / octaves;
}
}
}
JFrame f = new JFrame("Perlin Noise");
f.setSize(400, 400);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Noise());
f.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
g.setColor(new Color(perlinnoise[x][y], perlinnoise[x][y], perlinnoise[x][y]));
g.fillRect(x * 2, y * 2, 2, 2);
}
}
repaint();
}
}
Help please!
The trick is, the Perlin noise does not use pseudo-random generator, it uses a function that takes an argument and returns predefined value for that argument, but when argument shifts by 1, the value jumps almost randomly. Check the sources for the permutation formulae, the init() method makes a permutation that then is used to make the entire noise.
Hey stackoverflow community! I have been reading about perlin noise for the past 2 weeks and tried implementing it on my own in the most basic way. Even so, my program does not work. It outputs near similar looking results all the time and the persistence does not seem to change anything. Here is my code:
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Noise extends JPanel{
public static int octaves = 4;
public static int size = 128;
public static float[][][] noise = new float[size][size][octaves];
public static float[][] perlinnoise = new float[size][size];
public static float p = (float) 1/4;
public static Random gen = new Random();
public static float GenerateNoise() {
return gen.nextFloat();
}
public static float SmoothNoise(int x, int y, int z) {
try{
float corners = (noise[x - 1][y - 1][z] + noise[x + 1][y - 1][z] + noise[x - 1][y + 1][z] + noise[x + 1][y + 1][z]) / 16;
float sides = (noise[x - 1][y][z] + noise[x + 1][y][z] + noise[x][y - 1][z] + noise[x][y + 1][z]) / 8;
float center = noise[x][y][z] / 4;
return corners + sides + center;
}catch(Exception e) {
return 0;
}
}
public static float InterpolatedNoise(float x, float y, int pX, int pY, int pZ) {
int intX = (int) x;
int intY = (int) y;
float fracX = x - intX;
float fracY = y - intY;
float v1 = SmoothNoise(pX, pY, pZ);
float v2 = SmoothNoise(pX + 1, pY, pZ);
float v3 = SmoothNoise(pX, pY + 1, pZ);
float v4 = SmoothNoise(pX + 1, pY + 1, pZ);
float i1 = Interpolate(v1, v2, fracX);
float i2 = Interpolate(v3, v4, fracX);
return Interpolate(i1, i2, fracY);
}
public static float Interpolate(float a, float b, float x) {
float ft = (float) (x * 3.1415927);
float f = (float) ((1 - Math.cos(ft)) * 0.5);
return (float) (a * (1 - f) + b * f);
}
public static float Perlin2D(float x, float y, int posX, int posY, int posZ) {
float total = 0;
for(int i = 0; i < octaves; i++) {
double f = Math.pow(2, i);
double a = Math.pow(p, i);
total = (float) (total + InterpolatedNoise((float)(x * f), (float)(y * f), posX, posY, posZ) * a);
}
return total;
}
public static void main(String [] args) {
for(int z = 0; z < octaves; z++) {
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
noise[x][y][z] = GenerateNoise();
}
}
}
for(int z = 0; z < octaves; z++) {
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
perlinnoise[x][y] = Perlin2D(x / (size - 1), y / (size - 1), x, y, z) / octaves;
}
}
}
JFrame f = new JFrame("Perlin Noise");
f.setSize(400, 400);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Noise());
f.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for(int y = 0; y < size; y++) {
for(int x = 0; x < size; x++) {
g.setColor(new Color(perlinnoise[x][y], perlinnoise[x][y], perlinnoise[x][y]));
g.fillRect(x * 2, y * 2, 2, 2);
}
}
repaint();
}
}
I do not understand why it is not working because it is exactly as the pseudo code in this article said to do it. Can anyone assist me in figuring this out? Thanks.
EDIT: Ok please can someone just explain the process required to do this PLEASE I am going crazy trying to figure this out. I have been trying to figure it out for the past 2 weeks and no one is giving me any help with it. Please if you know how to do this, please just explain it to me I would greatly appreciate it. Thanks.