Monotonic Functions in Java of Comparables - java

I am trying to implement an algorithm that checks if an array of comparable elements is increasing or decreasing. So far I have written this method:
class Solution {
public boolean isMonotonic(int[] A) {
int store = 0;
for (int i = 0; i < A.length - 1; ++i) {
int c = Integer.compare(A[i], A[i+1]);
if (c != 0) {
if (c != store && store != 0)
return false;
store = c;
}
}
return true;
}
}
I changed the method signature, by passing a generic method of comparables, but I'm struggling to implement the compareTo method. I am probably using the bounded generics wrong, but I'm not too sure?
My attempt:
public boolean Test(T[] n)
{
if (n.length < 3)
return true;
int direction = n[0].compareTo(n[1]);
for (int i = 1; i < n.length-1; i++){
int step = n[i].compareTo(n[i+1]);
if (step == 0)
continue;
if (direction == 0)
direction = step;
else if ( sdtep < 0 && direction > 0
|| step > 0 && direction < 0)
return false;
}
return true;
}

In order to make your method take a generic argument, change its header:
public static <T extends Comparable<? super T>> boolean isMonotonic(T[] A)
You can then compare items of the array using the Comparable::compareTo method:
int c = A[i].compareTo(A[i+1]);

Monotone function:
public static boolean isMonotone(int[] a) {
boolean monotone = true;
int i=0;
while(a[i]==a[i+1]) {
i++;
}
if(a[i]>a[i+1]) {
for(int j=0;j<(a.length-1);j++) {
if(!(a[j]>=a[j+1])){
monotone=false;
}
}
}
if(a[i]<a[i+1]) {
for(int j=0;j<(a.length-1);j++) {
if(!(a[j]<=a[j+1])){
monotone=false;
}
}
}
return monotone;
}

Strictly monotone function:
public static boolean isMonotone(int[] a) {
boolean monotone = true;
if(a[0]>a[1]) {
for(int i=0;i<(a.length-1);i++) {
if(!(a[i]>a[i+1])){
monotone=false;
}
}
}
if(a[0]<a[1]) {
for(int i=0;i<(a.length-1);i++) {
if(!(a[i]<a[i+1])){
monotone=false;
}
}
}
if(a[0]==a[1]) return false;
return monotone;
}

Related

How to make this method only have 1 return statement instead of 2

My professor has a rule that "there should be no more than one return statement in any method". Now I've written a pretty simple method in my first project. How would I make this have only return statement without ruining functionality?
public static int find(int correctNumber, int numArray[], int lastNum) {
for (int i = 0; i < lastNum; i++) {
if (numArray[i] == correctNumber) {
return i;
}
}
return -1;
Use another variable to assign the value and then apply a break within the if clause to exit the loop.
public static int find(int correctNumber, int numArray[], int lastNum) {
int returnValue = -1;
for (int i = 0; i < lastNum; i++) {
if (numArray[i] == correctNumber) {
returnValue = i;
break;
}
}
return returnValue;
}
And you will find that many professional programmers with lots of experience find it perfectly acceptable to use multiple return statements.
For example: This is the equals override from the JDK HashMap source. That code was written by four internationally recognized computer scientists, three of which have their PhD's.
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
like this?
public static int find(int correctNumber, int numArray[], int lastNum) {
int correctIndex = -1;
for (int i = 0; i < lastNum; i++) {
if (numArray[i] == correctNumber) {
correctIndex = i;
}
}
return correctIndex;
you can try this:
public static int find(int correctNumber, int numArray[], int lastNum) {
int temNum = -1;
for (int i = 0; i < lastNum; i++) {
if (numArray[i] == correctNumber) {
temNum = i;
break;
}
}
return temNum;
}
public static int find(int correctNumber, int numArray[], int lastNum) {
int i = lastNum - 1;
while (i >= 0 && numArray[i] != correctNumber) {
i--;
}
return i;
}
This differs slightly from your code in that, if the 'correctNumber' occurs twice, it will find the higher-index instance.
It could be expressed with a for-loop but I find I prefer the while-loop.
public static int find(int correctNumber, int numArray[], int lastNum) {
int i;
for (i = lastNum-1; i >= 0 && numArray[i] != correctNumber; i--) {
}
return i;
}

Im receiving a String index out of range question for a java program i wrote for my assignment

I would like to apologise in advance if im doing something wrong with the code formatting because this is my second time posting here
I have a java assignment due in a couple of days in which the user enters a string and only the integers are collected from it and placed in the array intArray
Now i think i got the logic right in the code below but when i run it in the main, it asks for the string and the boolean, when i enter both it gives me the error
"Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 115"
This is what i entered for example
"Enter a string and true if you want to skip errors or false if you want to skip errors
sdak23
false"
this is my main:
import java.util.Scanner;
public class MainStringToIntArray {
public static void main(String[] args) {
Scanner intut = new Scanner(System.in);
Scanner input = new Scanner(System.in);
StringToIntArray s1 = new StringToIntArray();
System.out.println("Enter a string and true if you want to skip errors or false if you want to skip errors");
s1.scanStringToIntArray(intut.next(), input.nextBoolean());
}
}
import java.util.Arrays;
import java.util.Scanner;
public class StringToIntArray {
private int[] intArray = new int[10];
public StringToIntArray() {
Arrays.fill(intArray, Integer.MIN_VALUE);
}
public int indexOf(int intToFind) {
int b = 0;
for (int a = 0; a < intArray.length; a++) {
if (intArray[a] == intToFind) {
b = intArray[a];
}
else {
b = -1;
}
}
return b;
}
public int indexOf(String intToFind) {
int b = 0;
for (int a = 0; a < intArray.length; a++) {
if (intArray[a] == Integer.parseInt(intToFind)) {
b = intArray[a];
}
else {
b = -1;
}
}
return b;
}
public boolean contains(int intToFind) {
int a = indexOf(intToFind);
if (a > 0) {
return true;
}
else {
return false;
}
}
public boolean contains(String intToFind) {
int a = indexOf(intToFind);
if (a > 0) {
return true;
}
else {
return false;
}
}
public int get(int index) {
if(index < 0 && index > 10) {
return Integer.MIN_VALUE;
}
else {
return intArray[index];
}
}
public boolean scanStringToIntArray(String s, Boolean skipErrors) {
Boolean result = null;
Scanner input = new Scanner(s);
int l = s.length();
if ((skipErrors)) {
String discard = null;
for (int a = 0; a < l; a++) {
for (int z = 0; z < l; z++) {
if (input.hasNextInt(s.charAt(z))) {
intArray[a] = s.charAt(z);
System.out.println(a);
result = true;
}
else {
discard = discard + s.charAt(z);
}
}
}
}
else {
for (int v = 0; v < l; v++) {
for (int p = 0; p < l; p++) {
if ((input.hasNextInt(s.charAt(p)))) {
intArray[v] = s.charAt(p);
System.out.println(v);
}
else {
System.out.println(v);
result = false;
}
}
}
}
return result;
}
}
The issue is in the get method. It is logically impossible for the index to be both less than 0 and greater than 10; you probably want to use the logical or operator (||). Also, the maximum index of the array is actually 9, as arrays are zero indexed.
public int get(int index) {
if(index < 0 || index > 9) {
return Integer.MIN_VALUE;
}
else {
return intArray[index];
}
}
There are other logical errors in your code as well. All your indexOf methods should be returning the index where the element was first found instead of the element itself and your else branch is always resetting it to -1 each time it is not found.

Implement a Set class using an array

My Java assignment is to implement a set class by using an array.
The assignment won't allow me import the set class from the library, so I have to make it on my own. When I tried to print out the array, it prints out numbers in repeats, not unique numbers. I don't know where the problem is, so if you guys can find any errors in my code, it would be great. I tried to add numbers 2, 3, and 4 to the set, so the result should be 2 3 4, but the code shows me 2 3 2 3 2.
I think the source of the problem is from the add method from the set class, but I don't know what the problem is exactly.
import java.util.Arrays;
public final class Set implements SetInterface
{
private int[] set;
private int size;
private int capacity;
public Set(int c)
{
capacity = c;
set = new int[capacity];
size = 0;
}
public boolean contains(int x)
{
boolean contains = false;
for(int i = 0; i<capacity; i++)
{
if(x == set[i])
contains = true;
else
contains = false;
}
return contains;
}
public void add(int x)
{
for(int i = 0; i<capacity; i++)
{
if(!contains(x))
{
if(size == capacity)
{
set = Arrays.copyOf(set,size*2);
}
if(set[i]==0)
{
set[i++] = x;
}
}
}
size++;
}
public boolean remove(int x)
{
boolean remove = false;
for(int i = 0; i < capacity; i++)
{
if(x == set[i])
{
set[i] = set[size -1];
size--;
remove = true;
}
if(isEmpty())
{
remove = false;
}
}
return remove;
}
public void clear()
{
set = null;
size = 0;
}
public int size()
{
return size;
}
public boolean isEmpty()
{
if(size == 0)
return true;
else
return false;
}
public int[] toArray()
{
return Arrays.copyOf(set, capacity);
}
}
This is the driver class that I test my class.
import java.util.Arrays;
public class SetDriver
{
public static void main(String[] args)
{
SetDriver driver = new SetDriver();
Set s1 = new Set(5);
s1.add(2);
s1.add(3);
s1.add(4);
driver.print(s1);
System.out.println("Size: "+s1.size());
}
public static void print(Set s)
{
for(int i = 0; i<s.toArray().length; i++)
{
System.out.print(s.toArray()[i]+" ");
}
System.out.println("");
}
}
The outputs are here:
2 3 2 3 2
Size: 3
There's a likely problem with your contains method. Suppose that you did find a duplicate. What happens is that you assign your variable to true and you continue to iterate. This stomps over the logic entirely; you could have a duplicate but never act on it because your boolean code precludes you from doing so.
Ideally, when you find a match, you must stop iterating and return immediately.
public boolean contains(int value) {
for(int setItem : set) {
if(setItem == value) {
return true;
}
}
return false;
}
You should change add method like this.
public void add(int x) {
if (contains(x))
return;
if (size >= capacity) {
capacity *= 2;
set = Arrays.copyOf(set, capacity);
}
set[size++] = x;
}

Java Treemap comparator ignoring get when key is different instances

The issue I'm having is that the get method throws NPE when the key is a different instance than the one in the TreeMap.
public class ConjuntDocuments {
private TreeMap<Capcalera, Document> almacen;
private ArrayList<Pair_plantilla> plantilla;
ConjuntDocuments() {
almacen = new TreeMap<Capcalera, Document>(new CustomComparator());
plantilla = new ArrayList<Pair_plantilla>();
}
private static class CustomComparator implements Comparator<Capcalera> {
#Override
public int compare(Capcalera c1, Capcalera c2) {
int ax = c1.get_tit().get_nom().compareFrase(c2.get_tit().get_nom());
if (ax < 0) return -1;
else if (ax > 0) return 1;
//titols iguals
else {
ax = c1.get_au().get_nom().compareFrase(c2.get_au().get_nom());
if (ax < 0) return -1;
else if (ax > 0) return 1;
}
//titols i autors iguals
return 0;
}
}
compareFrase compares ArrayLists(Paraula) -> Frase, Paraula is like a string, get_chars returns a String.
public int compareFrase(Frase f) {
for(int i=0; i<min(this.get_size(), f.get_size()); ++i){
int aux = this.get_paraula(i).get_chars().compareTo(f.get_paraula(i).get_chars());
if(aux < 0) return -1;
else if(aux > 0) return 1;
}
if(this.get_size() < f.get_size()) return -1;
else if(this.get_size() > f.get_size()) return 1;
return 0;
}
Titol and autor are Frases -> ArrayList(Paraula)
public class Capcalera {
private Titol tit;
private Autor au;
So after trying to figure this out, I've realised that the get method only works if the key referenced is the same instance than the one mapped, right after putting an entry (almacen.put(capcalera,document) , if I try to call almacen.get(Capcalera) it will return the value correctly, but if I create a new Capcalera, it will throw NPE. I'm assuming there is an issue with the comparator but since the entries are sorted correctly I can't figure out what is wrong.
EDIT:
I've implemented .equals and .hashcode from Capcalera, but I might be doing something wrong because .get from the Treemap still throws NPE.
#Override
public int hashCode() {
int hashTitol = tit != null ? tit.hashCode() : 0;
int hashAutor = au != null ? au.hashCode() : 0;
return (hashTitol + hashAutor) * hashAutor + hashTitol;
}
#Override
public boolean equals(Object other) {
if (other instanceof Capcalera) {
Capcalera otherCapcalera = (Capcalera) other;
return
(( this.get_tit().get_nom().equalsFrase(otherCapcalera.get_tit().get_nom()) ||
( this.get_tit() != null && otherCapcalera.get_tit() != null &&
this.get_tit().get_nom().equalsFrase(otherCapcalera.get_tit().get_nom()) )) &&
( this.get_au().get_nom().equalsFrase(otherCapcalera.get_au().get_nom()) ||
( this.get_au() != null && otherCapcalera.get_au() != null &&
this.get_au().get_nom().equalsFrase(otherCapcalera.get_au().get_nom()))) );
}
return false;
}
equalsFrase returns true if Titol/Autor are equals
public boolean equalsFrase(Frase f) {
for(int i=0; i<min(this.get_size(), f.get_size()); ++i){
int aux = this.get_paraula(i).get_chars().compareTo(f.get_paraula(i).get_chars());
if(aux < 0) return false;
else if(aux > 0) return false;
}
if(this.get_size() < f.get_size()) return false;
else if(this.get_size() > f.get_size()) return false;
return true;
}

Java var from statement doesn't save

I can't save var stop so it can stop for cycle. I just need when tryOpen is true to exit that method and stop doing recursion.
public void moznosti(char [] arr, String pr, int a, int b) {
boolean stop = false;
if (b == 0) {
char [] heslo = pr.toCharArray();
for (int i = 0; i < heslo.length; i++) {
System.out.print(heslo[i]);
}
System.out.println();
if (tryOpen(heslo)) {
stop = true;
System.out.println("END");
}
return;
}
if (stop == false) {
for (int i = 0; i < a; i++) {
String tmp = pr+arr[i];
moznosti(arr, tmp, a, b-1);
}
}
}
Stop is a local variable here. If you make it a static global variable it will work, but note that you will have to set it to false before every time you call moznosti.
The above will work, but it isn't that good of a practice.
The best method would be to make your function return true when it succeeds. Then you can check success before making any more recursive calls:
if (b == 0) {
char[] heslo = pr.toCharArray();
for (int i = 0; i < heslo.length; i++) {
System.out.print(heslo[i]);
}
System.out.println();
if (tryOpen(heslo)) {
System.out.println("END");
} else {
for (int i = 0; i < a; i++) {
String tmp = pr + arr[i];
if (moz(arr, tmp, a, b - 1)) {
return true;
}
}
}
}
Thanks for help, this is what I did now it's working but it is slow...
public boolean moznosti(char [] arr, String pr, int a, int b) {
if (b == 0) {
char [] heslo = pr.toCharArray();
if(tryOpen(heslo)) {
return false;
}
return true;
}
for (int i = 0; i < a; i++) {
String tmp = pr+arr[i];
if (moznosti(arr, tmp, a, b-1) == false) {
return false;
}
moznosti(arr, tmp, a, b-1);
}
return true;
}
}

Categories