Java permutations - java

I am trying to run my code so it prints cyclic permutations, though I can only get it to do the first one at the moment. It runs correctly up to the point which I have marked but I can't see what is going wrong. I think it has no break in the while loop, but I'm not sure. Really could do with some help here.
package permutation;
public class Permutation {
static int DEFAULT = 100;
public static void main(String[] args) {
int n = DEFAULT;
if (args.length > 0)
n = Integer.parseInt(args[0]);
int[] OA = new int[n];
for (int i = 0; i < n; i++)
OA[i] = i + 1;
System.out.println("The original array is:");
for (int i = 0; i < OA.length; i++)
System.out.print(OA[i] + " ");
System.out.println();
System.out.println("A permutation of the original array is:");
OA = generateRandomPermutation(n);
printArray(OA);
printPemutation(OA);
}
static int[] generateRandomPermutation(int n)// (a)
{
int[] A = new int[n];
for (int i = 0; i < n; i++)
A[i] = i + 1;
for (int i = 0; i < n; i++) {
int r = (int) (Math.random() * (n));
int swap = A[r];
A[r] = A[i];
A[i] = swap;
}
return A;
}
static void printArray(int A[]) {
for (int i = 0; i < A.length; i++)
System.out.print(A[i] + " ");
System.out.println();
}
static void printPemutation(int p[])// (b)
{
System.out
.println("The permutation is represented by the cyclic notation:");
int[] B = new int[p.length];
int m = 0;
while (m < p.length)// this is the point at which my code screws up
{
if (!check(B, m)) {
B = parenthesis(p, m);
printParenthesis(B);
m++;
} else
m++;
}// if not there are then repeat
}
static int[] parenthesis(int p[], int i) {
int[] B = new int[p.length];
for (int a = p[i], j = 0; a != B[0]; a = p[a - 1], j++) {
B[j] = a;
}
return B;
}
static void printParenthesis(int B[]) {
System.out.print("( ");
for (int i = 0; i < B.length && B[i] != 0; i++)
System.out.print(B[i] + " ");
System.out.print(")");
}
static boolean check(int B[], int m) {
int i = 0;
boolean a = false;
while (i < B.length || !a) {
if ((ispresent(m, B, i))){
a = true;
break;
}
else
i++;
}
return a;
}
static boolean ispresent(int m, int B[], int i) {
return m == B[i] && m < B.length;
}
}

Among others you should check p[m] in check(B, p[m]) instead of m:
in static void printPemutation(int p[]):
while (m < p.length){
if (!check(B, p[m])) {
B = parenthesis(p, m);
printParenthesis(B);
}
m++;
}
then
static boolean check(int B[], int m) {
int i = 0;
while (i < B.length) {
if (m == B[i]) {
return true;
}
i++;
}
return false;
}
this does somehow more what you want, but not always i fear...

Related

java.lang.StackOverflowError on factorial function being called by another recursive function

I have a factorial function on my program that works fine until i try to execute the function deleteRepeated(), the console is telling me that the error is in the return of the factorial function, maybe it's being called by a single function too many times in a short period of time? I've been stuck for hours.
import java.util.Scanner;
public class ex9 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
int[] newArr = new int[n - repeated(arr)];
int[] finalArr = deleteRepeated(arr, newArr);
for (int a : finalArr) {
System.out.println(a);
}
}
public static long factorial(int n) {
if (n == 0)
return 1;
return (n * factorial(n - 1));
}
public static int repeated(int arr[]) {
int n = arr.length;
int mix = (int) (factorial(n) / (2 * factorial(n - 2)));
int i = 0;
int k = 0;
int rep = 0;
int a = -100;
while (i < mix) {
for (int j = k + 1; j < n; j++) {
if (arr[k] == arr[j] && a != j) {
a = j;
rep += 1;
}
i++;
}
k++;
}
return rep;
}
public static int[] deleteRepeated(int arr[], int newArr[]) {
int n = arr.length;
int rep = repeated(arr);
int i = 0;
int k = 0;
int a = -100;
while (i < newArr.length) {
for (int j = k + 1; j < n; j++) {
if (arr[k] == arr[j] && a != arr[k]) {
a = arr[j];
newArr[k] = arr[k];
}
i++;
}
k++;
}
rep = repeated(newArr);
if (rep > 0) {
int[] newArr2 = new int[newArr.length - rep];
deleteRepeated(newArr, newArr2);
}
return newArr;
}
}
Only thing i could do to avoid the error was stopping the function from executing :/, maybe it has to do with how i'm re-calling it at the end of each execution...? is what i did allowed?
So, deleteRepeated is all messed up. The issue is deleteRepeated does not actually remove duplicate elements, so the check for the base case of recursion always fails. I'm not sure why you're using recursion here anyway; if the while loop worked properly, it could remove all duplicates without need for recursion.
It appears that you copy-pasted the implementation of repeated into deleteRepeated, and you replaced the logic for handling repeated elements with logic that handles non-repeated elements.
Here is how I would implement the method:
public static int deleteRepeated(int arr[], int newArr[]) {
int n = 0;
for(int i = 0; i < arr.length; i++) {
boolean unique = true;
for(int j = 0; j < n; j++)
unique = unique && newArr[j] != arr[i];
if(unique)
newArr[n++] = arr[i];
if(n >= newArr.length) break;
}
return n;
}

Java Heap Sort and Counting Sort returns false

I have an assignment where I have to implement heap sort, quick sort, and counting sort into my program. Currently I have no errors but my output is returning as false for my heap and counting sort. What mistakes am I making? How can they be fixed? Please help any feedback will be appreciated.
package sorting;
import java.util.*;
public class Sort2
{
public static int left (int i)
{
return 2 * i + 1;
}
public static int right (int i)
{
return 2 * i + 2;
}
public static int parent (int i)
{
return ((i-1)/2);
}
public static void max_heapify (int[] array, int heap_size, int i)
{
int largest = i;
int l = left(i);
int r = right(i);
if (l < heap_size && array[l] > array[i])
{
largest = l;
}
else
{
largest = i;
}
if (r < heap_size && array[r] > array[largest])
{
largest = r;
}
if (largest != i)
{
int exchange = array[i];
array[i] = array[largest];
array[largest] = exchange;
max_heapify(array, array.length, largest);
}
}
public static int[] build_heap (int[] array)
{
int heap_size = array.length;
for (int i = array.length/2; i >= 1;i--)
{
max_heapify(array, heap_size, i);
}
return array;
}
public static int[] heap_sort (int[] array)
{
build_heap(array);
int heap_size = array.length;
for (int i = array.length;i >= 2;i--)
{
heap_size--;
int exchange = array[0];
array[0] = array[heap_size];
array[heap_size] = exchange;
max_heapify(array, array.length, 1);
}
return array;
}
public static void quick_sort (int[] array, int p, int r)
{
if (p < r)
{
int q = partition(array, p, r);
quick_sort(array, p,q-1);
quick_sort(array, q + 1,r);
}
}
public static int partition (int[] array, int p, int r)
{
int x = array[r];
int i = p - 1;
for (int j = p;j< r;j++)
{
if (array[j] <= x)
{
i++;
int exchange = array[i];
array[i] = array[j];
array[j] = exchange;
}
}
int exchange = array[i+1];
array[i+1] = array[r];
array[r] = exchange;
return i + 1;
}
public static int[] counting_sort (int[] A, int k)
{
int [] C = new int[k+1];
int [] B = new int [A.length];
for(int i = 0;i <= k; i++)
{
C[i] = 0;
}
for(int j = 0; j < A.length; j++)
{
C[A[j]] = C[A[j]] + 1;
}
for (int i = 1; i <= k; i++)
{
C[i] = C[i]+C[i-1];
}
for (int j = A.length - 1;j > 1; j--)
{
B[C[A[j]]- 1]=A[j];
C[A[j]]=C[A[j]] - 1;
}
return B;
}
public static int[] generate_random_array (int n, int k) {
List<Integer> list;
int[] array;
Random rnd;
rnd = new Random(System.currentTimeMillis());
list = new ArrayList<Integer> ();
for (int i = 1; i <= n; i++)
list.add(new Integer(rnd.nextInt(k+1)));
Collections.shuffle(list, rnd);
array = new int[n];
for (int i = 0; i < n; i++)
array[i] = list.get(i).intValue();
return array;
}
public static int[] generate_random_array (int n) {
List<Integer> list;
int[] array;
list = new ArrayList<Integer> ();
for (int i = 1; i <= n; i++)
list.add(new Integer(i));
Collections.shuffle(list, new Random(System.currentTimeMillis()));
array = new int[n];
for (int i = 0; i < n; i++)
array[i] = list.get(i).intValue();
return array;
}
/*
* Input: an integer array
* Output: true if the array is acsendingly sorted, otherwise return false
*/
public static boolean check_sorted (int[] array) {
for (int i = 1; i < array.length; i++) {
if (array[i-1] > array[i])
return false;
}
return true;
}
public static void print_array (int[] array) {
for (int i = 0; i < array.length; i++)
System.out.print(array[i] + ", ");
System.out.println();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int k = 10000;
System.out.println("Heap sort starts ------------------");
for (int n = 100000; n <= 1000000; n=n+100000) {
int[] array = Sort2.generate_random_array(n);
long t1 = System.currentTimeMillis();
array = Sort2.heap_sort(array);
long t2 = System.currentTimeMillis();
long t = t2 - t1;
boolean flag = Sort2.check_sorted(array);
System.out.println(n + "," + t + "," + flag);
}
System.out.println("Heap sort ends ------------------");
//Currently works
System.out.println("Quick sort starts ------------------");
for (int n = 100000; n <= 1000000; n=n+100000)
{
int[] array = Sort2.generate_random_array(n);
long t1 = System.currentTimeMillis();
Sort2.quick_sort(array, 0, n-1);
long t2 = System.currentTimeMillis();
long t = t2 - t1;
boolean flag = Sort2.check_sorted(array);
System.out.println(n + "," + t + "," + flag);
}
System.out.println("Quick sort ends ------------------");
int[] array2 = Sort2.generate_random_array(10, 10);
array2 = Sort2.counting_sort(array2,10);
boolean flag = Sort2.check_sorted(array2);
System.out.println(flag);
System.out.println("Counting sort starts ------------------");
for (int n = 100000; n <= 1000000; n=n+100000) {
int[] array = Sort2.generate_random_array(n, k);
long t1 = System.currentTimeMillis();
array = Sort2.counting_sort(array, n);
long t2 = System.currentTimeMillis();
long t = t2 - t1;
flag = Sort2.check_sorted(array);
System.out.println(n + "," + t + "," + flag);
}
System.out.println("Counting sort ends ------------------");
}
}
EDIT I modified your check method to print out the offending array elements:
public static boolean check_sorted( int[] array ) {
for( int i = 1; i < array.length; i++ ) {
if( array[i-1] > array[i] ) {
System.err.println( "Reversed array elements: " + (i-1) + "="
+ array[i-1] + ", " + i + "=" + array[i] );
return false;
}
return true;
}
It looks like the heap sort does not sort the first element of the array:
Heap sort starts ------------------
100000,5,false
Reversed array elements: 0=100000, 1=99999
And ten more like that.
For this homework assignment I would have suggested doing a google search on the specific sorts you were told to complete.
https://www.geeksforgeeks.org/counting-sort/
This will show you the code you just need to modify it for your variables. One thing I noticed right away is you are not building the count array correctly and that is affecting the build of the output array.
https://www.geeksforgeeks.org/heap-sort/
Here is the same instruction and explanation for your heap sort. I did not really look deeply into this as I do not have the time right now. Please use these resources to modify your code and hopefully complete the project.

How can I modify the boyer moore algorithm so that it runs in 0(n+m) time?

So I'm using the Boyer-Moore function and trying to integrate the failure function from the KMP and I don't know how to do that per se. I added the calling method to the failure function but I don't know how to make use of it. The two methods are given below.
public static int findBoyerMoore(char[] text, char[] pattern) {
int n = text.length;
int m = pattern.length;
int[] fail = computeFailKMP(pattern); ---> I did this but how can I use fail?
if(m == 0){
return 0;
}
Map<Character, Integer> last = new HashMap<>();
for(int i = 0; i< n; i++) {
last.put(text[i], -1);
}
for(int k = 0; k < m; k++) {
last.put(pattern[k], k);
}
int i = m - 1;
int k = m - 1;
while(i < n) {
if(text[i] == pattern[k]) {
if(k == 0) {
return i;
}
i--;
k--;
} else {
i+= m - Math.min(k, 1+ last.get(text[i]));
k = m-1;
}
}
return -1;
}
public static int[] computeFailKMP(char[] pattern) {
int m = pattern.length;
int[] fail = new int[m];
int j = 0;
int k = 0;
while(j < m) {
if(pattern[j] == pattern[k]) {
fail[j] = k + 1;
j++;
k++;
}
else if(k > 0) {
k = fail[k - 1];
}
else {
j++;
}
}
return fail;
}

Searching for a sum in an array

I have a method which counts how many sums of 3 elements,which are equal to 0, does the array contains. I need help finding the way to stop counting the same triplets in the loop. For instance, 1 + 3 - 4 = 0, but also 3 - 4 +1 = 0.Here is the method:
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
if(binarySearch(A,sum))
{
count++;
}
}
}
return count;
edit: I have to use the Binary Search (the array is sorted).
Here is the binarySearch code:
private static boolean binarySearch(int A[],int y)
{
y=-y;
int max = A.length-1;
int min = 0;
int mid;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
return true;
}
if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
return false;
You can avoid counting different triplets by making one assumption that we need to look for the triplets (x,y,z) with x < y < z and A[x] + A[y] + A[z] == 0.
So what you need to do is to modify the binarySearch function to return the number of index that greater than y and has A[z] == -(A[x] + A[y])
private static int binarySearch(int A[],int y, int index)
{
y=-y;
int max = A.length-1;
int min = index + 1;
int mid;
int start = A.length;
int end = 0;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
start = Math.min(start, mid);
max = mid - 1;
} else
if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
int max = A.length - 1;
int min = index + 1;
while (max>=min)
{
mid = (max+min)/2;
if (y==A[mid])
{
end = Math.max(end, mid);
min= mid + 1;
} else if (y<A[mid])
{
max=mid-1;
}
else
{
min=mid+1;
}
}
if(start <= end)
return end - start + 1;
return 0;
}
So the new function binarySearch will return the total number of index that greater than index and has value equals to y.
So the rest of the job is to count the answer
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
count += binarySearch(A,sum, j);
}
}
return count;
}
Notice how I used two binary search to find the starting and the ending index of all values greater than y!
private static int counter(int A[]) {
int e = A.length;
int count = 0;
for (int i = 0; i < e; i++) {
for (int j = 1; (j < e - 1) && (i != j); j++) {
for (int k = 2; (k < e - 2) && (j != k); k++) {
if (A[i] + A[j] + A[k] == 0) {
count++;
}
}
}
}
return count;
}
private static int counter(int ints[]) {
int count = 0;
for (int i = 0; i < ints.length; i++) {
for (int j = 0; j < ints.length; j++) {
if (i == j) {
// cannot sum with itself.
continue;
}
for (int k = 0; k < ints.length; k++) {
if (k == j) {
// cannot sum with itself.
continue;
}
if ((ints[i] + ints[j] + ints[k]) == 0) {
count++;
}
}
}
}
return count;
}
To solve problem with binary search
Your code was almost correct. all you needed to do was just to replace
if (sum == binarySearch(A,sum)) {
with this
if (binarySearch(A,sum)) {
I am assuming that your binarySearch(A, sum) method will return true if it will found sum in A array else false
private static int counter(int A[]) {
int sum;
int e = A.length;
int count = 0;
for (int i=0; i<e; i++) {
for (int j=i+1; j<e; j++) {
sum=A[i]+A[j];
if (binarySearch(A,sum)) {
count++;
}
}
}
return count;
}
Here is my solution assuming the array is sorted and there are no repeated elements, I used the binary search function you provided. Could the input array contain repeated elements? Could you provide some test cases?
In order to not counting the same triplets in the loop, we should have a way of inspecting repeated elements, the main idea that I used here is to have a list of int[] arrays saving the sorted integers of {A[i],A[j],-sum}.Then in each iteration I compare new A[i] and A[j] to the records in the list, thus eliminating repeated ones.
private static int counter(int A[]){
int sum;
int e = A.length;
int count = 0;
List<int[]> elements = new ArrayList<>();
boolean mark = false;
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
if (-sum == binarySearch(A,sum)){
int[] sort = {A[i],A[j],-sum};
if(-sum == A[i] || -sum == A[j]){
continue;
}else{
Arrays.sort(sort);
//System.out.println("sort" + sort[0] + " " + sort[1]+ " " + sort[2]);
for (int[] element : elements) {
if((element[0] == sort[0] && element[1] == sort[1]) && element[2] == sort[2])
mark = true;
}
if(mark){
mark = false;
continue;
}else{
count++;
elements.add(sort);
//System.out.println("Else sort" + sort[0] + " " + sort[1]);
}
}
}
}
}
return count;
}
you can use a assisted Array,stored the flag that indicate if the element is used;
Here is the code:
private static int counter(int A[])
{
int sum;
int e = A.length;
int count = 0;
// assisted flag array
List<Boolean> flagList = new ArrayList<Boolean>(e);
for (int k = 0; k < e; k++) {
flagList.add(k, false);// initialization
}
for (int i=0; i<e; i++)
{
for (int j=i+1; j<e; j++)
{
sum=A[i]+A[j];
// if element used, no count
if(binarySearch(A,sum)&& !flagList.get(i)&& !flagList.get(j))
{
count++;
flagList.set(i, true);
flagList.set(j, true);
}
}
}
return count;

Polynomial Class in Java problems

I'm having trouble with this polynomial class, specifically the checkZero and differentiate methods. The checkZero class is supposed to see if there are any leading coefficients in the polynomial, and if so, it should resize the coefficient array. The differentiate method should find the derivative of a polynomial, but I keep getting ArrayIndexOutOfBounds errors.
public class Polynomial {
private float[] coefficients;
public static void main (String[] args){
float[] fa = {3, 2, 4};
Polynomial test = new Polynomial(fa);
}
public Polynomial() {
coefficients = new float[1];
coefficients[0] = 0;
}
public Polynomial(int degree) {
coefficients = new float[degree+1];
for (int i = 0; i <= degree; i++)
coefficients[i] = 0;
}
public Polynomial(float[] a) {
coefficients = new float[a.length];
for (int i = 0; i < a.length; i++)
coefficients[i] = a[i];
}
public int getDegree() {
return coefficients.length-1;
}
public float getCoefficient(int i) {
return coefficients[i];
}
public void setCoefficient(int i, float value) {
coefficients[i] = value;
}
public Polynomial add(Polynomial p) {
int n = getDegree();
int m = p.getDegree();
Polynomial result = new Polynomial(Polynomial.max(n, m));
int i;
for (i = 0; i <= Polynomial.min(n, m); i++)
result.setCoefficient(i, coefficients[i] + p.getCoefficient(i));
if (i <= n) {
//we have to copy the remaining coefficients from this object
for ( ; i <= n; i++)
result.setCoefficient(i, coefficients[i]);
} else {
// we have to copy the remaining coefficients from p
for ( ; i <= m; i++)
result.setCoefficient(i, p.getCoefficient(i));
}
return result;
}
public void displayPolynomial () {
for (int i=0; i < coefficients.length; i++)
System.out.print(" "+coefficients[i]);
System.out.println();
}
private static int max (int n, int m) {
if (n > m)
return n;
return m;
}
private static int min (int n, int m) {
if (n > m)
return m;
return n;
}
public Polynomial multiplyCon (double c){
int n = getDegree();
Polynomial results = new Polynomial(n);
for (int i =0; i <= n; i++){ // can work when multiplying only 1 coefficient
results.setCoefficient(i, (float)(coefficients[i] * c)); // errors ArrayIndexOutOfBounds for setCoefficient
}
return results;
}
public Polynomial multiplyPoly (Polynomial p){
int n = getDegree();
int m = p.getDegree();
Polynomial result = null;
for (int i = 0; i <= n; i++){
Polynomial tmpResult = p.multiByConstantWithDegree(coefficients[i], i); //Calls new method
if (result == null){
result = tmpResult;
} else {
result = result.add(tmpResult);
}
}
return result;
}
public void checkZero(){
int newDegree = getDegree();
int length = coefficients.length;
float testArray[] = coefficients;
for (int i = coefficients.length-1; i>0; i--){
if (coefficients[i] != 0){
testArray[i] = coefficients[i];
}
}
for (int j = 0; j < testArray.length; j++){
coefficients[j] = testArray[j];
}
}
public Polynomial differentiate(){
int n = getDegree();
int newPolyDegree = n - 1;
Polynomial newResult = new Polynomial();
if (n == 0){
newResult.setCoefficient(0, 0);
}
for (int i =0; i<= n; i++){
newResult.setCoefficient(i, coefficients[i+1] * (i+1));
}
return newResult;
}
}
There might be more problems, but one is a problem with your differentiate method:
int n = getDegree();
...
Polynomial newResult = new Polynomial();
...
for (int i = 0; i <= n; i++)
{
newResult.setCoefficient(i, coefficients[i + 1] * (i + 1)); //This line
}
Your paramaterless constructor initializes an array with length 1, so "newResult" will only have 1 index, and you try to put something into place i, which goes above 1 if the Polynomial you are in have an array of greater length than 1.
First, a few code notes:
New arrays are automatically initialized to 0 in Java. This is not needed.
coefficients = new float[degree+1];
for (int i = 0; i <= degree; i++)
coefficients[i] = 0;
I also see many lines which might become more readable and compact if you use the trinary operator, for example:
int i;
for (i = 0; i <= Polynomial.min(n, m); i++)
result.setCoefficient(i, coefficients[i] + p.getCoefficient(i));
if (i <= n) {
//we have to copy the remaining coefficients from this object
for ( ; i <= n; i++)
result.setCoefficient(i, coefficients[i]);
} else {
// we have to copy the remaining coefficients from p
for ( ; i <= m; i++)
result.setCoefficient(i, p.getCoefficient(i));
}
Could become something like
for (int i = 0; i <= result.getDegree(); i++)
result.setCoefficient(i,
i>n?0:coefficients[i] +
i>m?0:p.getCoefficient(i));
The one bug I did spot was here:
int n = getDegree();
....
for (int i =0; i<= n; i++){
newResult.setCoefficient(i, coefficients[i+1] * (i+1));
}
This will always call coefficients[coefficients.length] on the last iteration, which will always fail.
The stack trace of the exception when you ran this program should tell you exactly where the error is, by the way.

Categories

Resources