Related
`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!
I want is to display all consecutive sequences from a given array of ints.
Finally I want to display the longest one with text.
What I tried
I sorted the array and found all sequences.
I stored the found sequences into a new ArrayList.
Below is only a small piece of code, because I know the rest doesn't work:
int[] myArray = {202,203,204,205,206, 100, 1, 3, 200, 2, 4, 201, 5};
ArrayList<Integer> secuence = new ArrayList<>();
Arrays.sort(myArray);
for (int i = 0; i < myArray.length - 1; i++) {
if ((myArray[i] + 1) == myArray[i + 1] || (myArray[i] - 1) == myArray[i - 1]) {
secuence.add(myArray[i]);
}
}
I tried many different ways, but can't figure out.
A couple remarks, suggestions:
As sort() sorts the array in increasing order, actually you do not have to check for decreasing elements
For finding the "anything"est thing, you need to store the "anything"est thing found so far, and a current candidate. This applies to finding largest element or longest sequence of consecutive elements too
For dealing with subparts of an array, it is not necessary to make an actual copy of the elements, it is enough to store beginning index and ending index or length.
Putting them together:
var myArray = [202,203,204,205,206, 100, 1, 3, 200, 2, 4, 201, 5];
myArray.sort((a,b)=>a-b);
console.log("Sorted array:",...myArray);
var longstart=0;
var longlength=0;
var currstart=0;
while(currstart<myArray.length){
var currlength=0;
while(currstart+currlength<myArray.length
&& myArray[currstart]+currlength==myArray[currstart+currlength])
currlength++;
if(currlength>longlength){
longlength=currlength;
longstart=currstart;
}
console.log("Sequence:",...myArray.slice(currstart,currstart+currlength));
currstart+=currlength;
}
console.log("Longest:",...myArray.slice(longstart,longstart+longlength));
This code is JavaScript so it can be run here, a Java variant (just with less printing) would look very similar:
int[] myArray = {202,203,204,205,206, 100, 1, 3, 200, 2, 4, 201, 5};
Arrays.sort(myArray);
int longstart=0;
int longlength=0;
int currstart=0;
while(currstart<myArray.length){
int currlength=0;
while(currstart+currlength<myArray.length
&& myArray[currstart]+currlength==myArray[currstart+currlength])
currlength++;
if(currlength>longlength){
longlength=currlength;
longstart=currstart;
}
currstart+=currlength;
}
for(int i=0;i<longlength;i++)
System.out.print((i==0?"Longest: ":", ")+myArray[longstart+i]);
The key thing is to have the check work with a growing distance, so the fixed [i]+1==[i+1] check in your initial code became [i]+distance==[i+distance].
I approached the solution as follows:
Data structures
a consecutive sequence (what we want to find) is a List of at least 2 consecutive Integers (pair)
to return all foundSequences you need one result List containing 0 or more Lists
to check for consecutive-ness you need the current and previous element
Algorithm
Logic applied (if):
Consecutive-ness is found if current == previous + 1, otherwise an existing consecutive sequence is broken
If a sequence has at least 2 elements, i.e. sequence.size() > 1, then it should be added to the result list (i.e. foundSequences)
Before the first element and after each broken sequence, the previous == null
After the last element there could be an open sequence with sequence.size() > 1. If so, then this sequence is not broken, but completed and should be added to the result list (i.e. foundSequences)
Iterating over elements (loop):
Use a for-each loop to process all elements of the (sorted!) array
The for-loop automatically fills the current element (iterating variable)
You must keep track of the previous element (thus initialized null before the loop). It must archive the current element of each loop, so we can compare the next element against it.
Unless the current element is not consecutive anymore (a break happened), then the previous will become null to start a fresh collection.
In case of a break the currently found sequence may be added to the result. Then the sequence needs to be reset to null to start a fresh collection.
After the last element was checked and the loop ended, there could be still a sequence (that was not yet broken). This needs to be added to the result.
8.
Source
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class ConsecutiveSequenceFinder {
private int[] unsortedNumbers;
public ConsecutiveSequenceFinder(int[] numbers) {
this.unsortedNumbers = numbers;
}
public int[] sorted() {
int[] sortedNumbers = Arrays.copyOf(this.unsortedNumbers, this.unsortedNumbers.length);
Arrays.sort(sortedNumbers);
return sortedNumbers;
}
public List<List<Integer>> findSequences() {
// one sequence is List of integers; thus list of sequences is list of list of integers
List<List<Integer>> foundSequences = new ArrayList<>();
// first we sort the array
int[] ascending = this.sorted();
// this working variable will hold the currently found sequence
List<Integer> sequence = new ArrayList<Integer>();
Integer previous = null;
System.out.println("Finding sequences ..");
for (int current : ascending) {
// check if current value is first or one more than (consecutive to) previous
if (previous == null || current == previous + 1) {
sequence.add(current);
previous = current;
} else {
System.out.printf("\tsequence of %d consecutive is broken at: %d\n", sequence.size(), current);
// if sequence found (at least a pair) then add
if (sequence.size() > 1) {
foundSequences.add(sequence);
}
// and finally prepare a new sequence, to collect fresh again
sequence = new ArrayList<>();
previous = null;
}
}
// if sequence left, then add
if (sequence.size() > 1) {
System.out.printf("\tsequence of %d consecutive was completed with last array element\n", sequence.size());
foundSequences.add(sequence);
}
return foundSequences;
}
public static void main (String[] args) throws java.lang.Exception {
// demo numbers
int[] values = {202,203,204,205,206, 100, 1, 3, 200, 2, 4, 201, 5};
// starting demo
System.out.println("Input: " + Arrays.toString(values));
ConsecutiveSequenceFinder finder = new ConsecutiveSequenceFinder(values);
System.out.println("Sorted: " + Arrays.toString(finder.sorted()));
List<List<Integer>> foundSequences = finder.findSequences();
System.out.println("Found sequences: " + foundSequences.size());
// print for each sequence the size and its elements
for (List<Integer> sequence : foundSequences) {
System.out.printf("\t %d elements: %s\n",sequence.size(), sequence.toString());
}
// check for each sequence if it is the longest
List<Integer> longestSequence = new ArrayList<>();
for (List<Integer> sequence : foundSequences) {
if (sequence.size() > longestSequence.size()) {
longestSequence = sequence;
}
}
System.out.printf("Longest sequence has %d elements: %s\n",longestSequence.size(), longestSequence.toString());
}
}
Actual Output
Input: [202, 203, 204, 205, 206, 100, 1, 3, 200, 2, 4, 201, 5]
Sorted: [1, 2, 3, 4, 5, 100, 200, 201, 202, 203, 204, 205, 206]
Finding sequences ..
sequence of 5 consecutive is broken at: 100
sequence of 7 consecutive was completed with last array element
Found sequences: 2
5 elements: [1, 2, 3, 4, 5]
7 elements: [200, 201, 202, 203, 204, 205, 206]
Longest sequence has 7 elements: [200, 201, 202, 203, 204, 205, 206]
Process finished with exit code 0
I see a lot of posts with the same topic (mostly with Strings) but haven't found the answer to my question. How would I remove duplicate integers from an ArrayList?
import java.util.*;
public class ArrayList2 {
public static ArrayList<Integer> removeAllDuplicates(ArrayList<Integer> list) {
Collections.sort(list);
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == list.get(i + 1)) {
list.remove(i);
}
}
return list;
}
}
This is the start of my code, the only problem that has arised is that if there are 3 integers with the same value, it only removes one of them. If I put in 4, it removes two of them. PLEASE NO HASHING!!!
The ArrayList and the output when I run it:
List: [-13, -13, -6, -3, 0, 1, 1, 1, 5, 7, 9]
Duplicates Removed: [-13, -6, -3, 0, 1, 1, 5, 7, 9]
This is my first time using this website, so please let me know if I'm doing something wrong with formatting/if there's already an answer to my question that I missed.
The specific reason why your removeAllDuplicates function doesn't work is that you are still iterating after a successful comparison. If you iterate only when list.get(i) != list.get(i + 1), you will get rid of all the duplicates.
public static ArrayList<Integer> removeAllDuplicates(ArrayList<Integer> list) {
Collections.sort(list);
int i = 0;
while(i < list.size() - 1) {
if (list.get(i) == list.get(i + 1)) {
list.remove(i);
} else {
i++;
}
}
return list;
}
It's worth noting that the above function is not as fast as it could be. Though the iteration runs quickly enough, the most significant step will be the sort operation (O(n log n)).
To avoid this extra time complexity, consider using a HashSet instead of an ArrayList (if it still fits within the constraints of your problem).
Other people have "answered" the basic issue, of the if statement skipping over elements because the for-loop is incrementing the index position, while the size of the array is shrinking.
This is just "another" possible solution. Personally, I don't like mutating Lists in loops and prefer to use iterators, something like...
Collections.sort(list);
Iterator<Integer> it = list.iterator();
Integer last = null;
while (it.hasNext()) {
Integer next = it.next();
if (next == last) {
it.remove();
}
last = next;
}
Still, I think some kind of Set would be a simpler and easier solution (and since you'd not have to sort the list, more efficient ;))
This assumes that you cannot use a set ("Please No hashing!!!") for a reason such as homework.
Look what happens when you remove a duplicate. Let's say that the dupe you're removing is the 1st of 3 consecutive equal numbers.
v
-13, -6, -3, 0, 1, 1, 1, 5, 7, 9
Here i is 4 to refer to the first of the 3 1 values. When you remove it, all subsequent elements get shifted down, so that the second 1 value now takes the place of the first 1 value at index i = 4. Then the current iteration ends, another one begins, and i is now 5.
v
-13, -6, -3, 0, 1, 1, 5, 7, 9
But now i is referring to the second of the two 1 values left, and the next element 5 isn't equal, so no dupe is found.
Every time you find a duplicate, you must decrease i by 1 so that you can stay on the first element that is a duplicate, to catch 3 or more duplicates in a row.
v
-13, -6, -3, 0, 1, 1, 5, 7, 9
Now consecutive elements still match, and another 1 value will get removed.
You'd want to have a double for loop as you dont want to check the only the next index but all indexes. As well as remember when you remove a value you want to check that removed value again as it could of been replaced with another duplicate value.
I'm working on a project where I need to use recursion, and arraylists/vectors to solve a 3-satisfiability instance. The task is to select a sub-set of integers, such that each set denoted below contains one or more elements of the sub-set. The constraint being that a number, i & its opposite, -i, cannot both be in the sub-set.
Vector<Vector<Integer>> matrix = new Vector<Vector<Integer>>();
for(int i=0;i<4;i++)
{
matrix.add(new Vector<Integer>());
}
the 2-dimensional vector/arraylist is then filled with numbers, for example:
1, -2, 3
-1, 2, 4
2, -3, 4
-1, -2, -3
if(startRec(matrix)
{
//solution is found
}
else
{
//no solution is possible
}
private boolean startRec(Vector<Vector<Integer>> matrix)
{ // I'm using trial and error to find a solution to the above problem. So in the below, matrix.get(0).get(i) is selected as part of a possibly correct set.
boolean success=false;
if(stagen(matrix.get(0).get(0), matrix))
{
success=true;
}
else if(stagen(matrix.get(0).get(1),matrix))
{
success=true;
}
else if(stagen(matrix.get(0).get(2),matrix))
{
success=true;
}
return success;
}
private boolean stagen(int input, Vector<Vector<Integer>> matrix)
{
removei(input, matrix) // this removes all Vector<Integer> that contain i. Those sets are considered satisfied, and no longer need to be addressed.
removenegative(input,matrix) // this removes all integers that are -input. Since i and -i cannot both be selected, I'm removing the -input.
//So if a set contained three ints, one of which was -input, it now contains 2.
boolean success=false;
if(stagen(matrix.get(0).get(0), matrix)) // since the original matrix.get(0) contained input, it was removed in removei(input,matrix), thus this is a one below the one called previously.
{
success=true;
}
else if(stagen(matrix.get(0).get(1),matrix))
{
success=true;
}
else if(stagen(matrix.get(0).get(2),matrix))
{
success=true;
}
return success;
}
I've removed the out of range checks, to make it more readable. But the process I'm confident is going on is this:
1, -2, 3 //1 is selected in the second line of startRec
-1, 2, 4
2, -3, 4
-1, -2, -3
//1, -2, 3 line is removed from consideration by method removei() as 1 has been selected
2, 4 // -1 has been removed as both 1,-1 cannot be selected.
2, -3, 4
-2, -3 // -1 removed.
2, 4 now 2 is the first number, so 2 is selected.
-2, 3, 4
-2, -3
//2, 4 removed via removei method.
3, 4 //-2 is removed, because 2 has been selected.
-3 //-2removed.
3, 4 //Now 3 is selected.
-3
//3, 4 line removed as it has been satisfied.
_____ //There's now an empty set here as -3 was deleted
//false is returned by stagen.
The program returns to the stagen which selected 3, and it now ideally now select 4 as the next letter. But I deleted that whole row.
Is there a way to do this without creating an unknown number of vectors?
2ndly, is there a significant difference between arraylists & vectors? I've been using arraylists, exclusively, but the project suggests vectors.
The first part of your question is incoherent. However I'll elaborate on the differences between Vector and Arraylist:
If multiple threads access an ArrayList concurrently then you need to externally synchronize the block of code which modifies the list.
Internally, both of them use an array to maintain the data structure. If running out of space, ArrayList increases its size by 50% while Vector doubles its size.
Refer this thread for a detailed explanation.
I am trying to compute pascal's triangle given a row number. I am using recursion.
My code is below:
public static List<Integer> getRow(int rowIndex) {
if (rowIndex == 1){
List <Integer> list = new ArrayList(rowIndex+1);
list.add(1);
return list;
}
else{
List<Integer> oldList = getRow(rowIndex -1);
List <Integer> list = new ArrayList(rowIndex+1);
int temp = 0;
list.add(0,1);
list.add(list.size()-1,1);
System.out.println("rowIndex "+rowIndex);
for (int i = 1; i < list.size()-1; i ++){
temp = oldList.get(i) + oldList.get(i-1);
list.add(i,temp);
}
return list;
}
}
It always returns [1,1] regardless of what row I am trying to get. I tried inserting print statements. I noticed the size of list is always 2 regardless of what rowIndex is.
List <Integer> list = new ArrayList(rowIndex+1);
Is the line above not the correct way to create an ArrayList? Seems like my arraylist always has size = 2;
you misunderstand how ArrayLists do work and you really should read the Javadoc.
In short, the constructor's parameter defines the initial size of the ArrayList in memory, not the max size. If you instantiate a new ArrayList<Integer>(2)it only means that the jvm allocates upfront enough space for two Integers, and that when you add a third element then the jvm will grow the size of the ArrayList in order to allow you to add more elements.
Further, you can access an ArrayList position with get() only if an element has been added at this position.
Finally, keep in mind that add at a specific position shifts right all elements. Thus if you add(10,1) then add(2,4), your first add will be shifted right.
Back to your question, if you absolutely want to use an ArrayList and not an array, you have to initialize your ArrayList with the right size, then set values at the right positions.
Here is a working solution :
// the method with your algorithm which has been slightly modified
public static List<Integer> getRow(final int rowIndex) {
// notice that I call a helper method which initialises correctly the ArrayList
final List<Integer> list = init(rowIndex);
if (rowIndex == 1) {
// notice that I set the value at a given position
// I can only do it because I initialised all values to 0 first
list.set(0, 1);
} else {
final List<Integer> previousRowList = getRow(rowIndex - 1);
// again, I set values...
list.set(0, 1);
list.set(rowIndex - 1, 1);
for (int i = 1; i < (list.size() - 1); i++) {
// set again...
list.set(i, previousRowList.get(i - 1) + previousRowList.get(i));
}
}
// lets print out the row
System.err.println(list);
// then return it
return list;
}
public static List<Integer> init(final int size) {
// passing the size is overkill, but well...
final List<Integer> list = new ArrayList<Integer>(size);
// fill the ArrayList with zeros
for (int i = 0; i < size; i++) {
list.add(i, 0);
}
// then return it
return list;
}
public static void main(final String[] args) {
getRow(Integer.parseInt(args[0]));
}
If you run it you'll get a (not so nice, but working) Pascal's triangle. Here follows the result if you want 11 rows :
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1]
Hope it helps !
I think you're miss-interpreting the data structures.
And array list is a LIST implemented on top of an array. Setting the size of the array in the constructor is a way to give control to the developer for the initial size of the array (This is rarely necessary as the class manages the array size itself--so just leave out this argument). So the size of an array list is actually the size of the list, which is the number of elements, not the number of buckets in the underlying array which is specified in the constructor.
If you know the size of the array you want, and you want to get and add at specific locations, use a standard array, not an array list.
However, I think your code will work if you move
list.add(list.size()-1,1);
to after your for-loop (I'm actually surprised it doesn't throw an index out of bounds exception). And since you're going left to right, none of your adds need an index specified, since it'll just add it to the end of the existing list.