Finding maximum length difference between strings of two arrays - java

So I've tried to used a nested loop and add the lengths to a int array and then go through the int array and find the highest number but it doesn't pass the test case and I'm starting to think that maybe I'm overcomplicating this problem and that there's a much simpler approach. Here is what I've tried.
public static int mxdiflg(String[] a1, String[] a2) {
int maxDiff=0;
int[] lengths=new int[a1.length*a2.length];
for(int i=0;i<a1.length;i++){
for(int j=0;j<a2.length;j++){
lengths[j]=Math.abs(a1[j].length()-a2[i].length());
}
}
for(int i=0;i<lengths.length;i++){
if(lengths[i]>maxDiff){
maxDiff=lengths[i];
}
}
return maxDiff;
}

You can do it like so with two independent loops.
String[] a1 = { "ab", "cdefghik", "lsls" };
String[] a2 = { "a", "cdefghik", "lsls", "abcdefghijkl" };
int max = mxdiflg(a1, a2);
System.out.println(max);
prints
11
initialize the minvals to largest int value and the maxvals to 0.
each loop finds the min and max of the strings using Math.min and Math.max.
once done, find the maximum of the two max values and the minimum of the two min values.
the subtract the minimum from the maximum and you have the result.
public static int mxdiflg(String[] a1, String[] a2) {
int maxa1 = 0, mina1 = Integer.MAX_VALUE, maxa2 = 0,
mina2 = Integer.MAX_VALUE;
// find max and
for (String s : a1) {
int len = s.length();
maxa1 = Math.max(maxa1, len);
mina1 = Math.min(mina1, len);
}
for (String s : a2) {
int len = s.length();
maxa2 = Math.max(maxa2, len);
mina2 = Math.min(mina2, len);
}
return Math.max(maxa1, maxa2) - Math.min(mina1, mina2);
}
Note: Due to the peculiarities of various character encodings, String.length does accurately count the characters. As stated in the documentation.
Returns the length of this string. The length is equal to the number of Unicode code units in the string.
As some characters use encoding schemes of more than 8 bits, their reported length would greater than 1.
If this is important, the s.length could be replaced with (int)s.codePoints().count() to handle these encodings.

Assuming Java 8+ and a reasonable number of strings in each array, I'd suggest using the following to avoid the nested loop:
int a1max = Arrays.stream(a1).mapToInt(String::length).max().orElse(0);
int a1min = Arrays.stream(a1).mapToInt(String::length).min().orElse(0);
int a2max = Arrays.stream(a2).mapToInt(String::length).max().orElse(0);
int a2min = Arrays.stream(a2).mapToInt(String::length).min().orElse(0);
int maxDiff = Math.max(Math.abs(a2max-a1min), Math.abs(a1max-a2min));

Related

Remove trailing zeros in the output of an integer array in java

In my code, I get an output of an array but it displays some unwanted zeros after getting the array, Can you explain a way to avoid getting these unwanted zeros.
static int[] cutTheSticks(int[] arr) {
int min,i,j,count=0;
int []arr2=Arrays.copyOf(arr,arr.length);
int []temp =Arrays.copyOf(arr,arr.length);
for(i=0;i<arr.length;i++){
Arrays.sort(arr2);
min= arr2[0];
for(j=0;j<arr.length;j++){
if(temp[j]>0){
count++;
}
temp[j]=temp[j]-min;
}
int []res = new int [arr.length];
while(count!=0) {
res[i] = count;
count = 0;
}
return res;
}
You can figure the "size" of res without its trailing zeros with:
int rlen = res.length;
while (res[rlen-1] == 0) {
--rlen;
}
If you wish, you can then use the calculated "effective length" rlen to reallocate the res array at the correct size:
res = Arrays.copyOf(res, rlen);
Or just use rlen instead of res.length when you need to know the "correct" size of res.

java how do i read a negative int as a positive one

The question at hand is:
The method should compute for each row the sum of the absolute values
of the elements of that row. The method should return the maximum of
these sums. For example, if applied to the test array, the method
should return the value max (3+1+4+0,5+9+2+6, 5+3+7+8) = max (8,22,23)
= 23.
The test array:
3 -1 4 0
5 9 -2 6
5 3 7 -8
so far i have made a method that gets the value of all the rows and returns to me the sum in a list; however, i want it to turn negative integers into positive ones.
here's my code so far:
public static int[] rowSums(int[][]array) {
int[] a = new int[array.length];
for (int i = 0;i<array.length;i++){
int sum = IntStream.of(array[i]).sum();
a[i]=sum;
} return a;}
Output:
[6,18,7]
You can use Math#abs(standing for absolute value) which converts any negative number into a positive number:
int sum = IntStream.of(array[i]).map(Math::abs).sum();
If you'd like to lose those for-loops, you can even just stick with streams:
public static int[] rowSums(int[][] array) {
return Arrays.stream(array)
.mapToInt(i -> Arrays.stream(i).map(Math::abs).sum())
.toArray();
}
Here you can use the Map. So The code will be like this.
public static int[] rowSums(int[][]array) {
int[] a = new int[array.length];
for (int i = 0;i<array.length;i++){
int sum = IntStream.of(array[i]).map(n->{
if(n<0) {
return n*-1;
}
else {
return n;
}
}).sum();
a[i]=sum;
} return a;}
Here I just make all the negative Integers into Positive.
Update this line
int sum = IntStream.of(array[i]).sum();
to
int sum = IntStream.of(array[i]).map(Math::abs).sum();
And solution for whole matrix (this snippet will return 23):
Optional<Integer> maxVal = Arrays.stream(matrix)
.map(array -> Arrays.stream(array).map(Math::abs).sum())
.reduce(Integer::max);
And without Optional
int maxVal = Arrays.stream(matrix)
.map(array -> Arrays.stream(array).map(Math::abs).sum())
.reduce(Integer::max).get();
Use Math.abs() It'll take any number and return it as a positive number. You need it on this line:
int sum = IntStream.of(array[i]).sum();
to take array[i] and make it absolute. So
IntStream.of(Math.abs(array[i]).sum();
Just use:
Math.abs(var)
This will turn var to a positive if it is negative.
Therefore the full answer is as follows:
public static int[] rowSums(int[][]array) {
int[] a = new int[array.length];
for (int i = 0;i<array.length;i++){
int sum = IntStream.of(array[i]).map(Math::abs).sum();
a[i]=sum;
} return a;}
Change all numbers to positive numbers. This can be done using Math.abs(int).Check the link.

How to copy only certain elements of one Array to another in Java

I am struggling to create an array with the correct size according to my parameters I have set up. Long story short this program is dealing with a set number of elements in the first array. Those elements are as follows
int [] myWeights = {258, 58, 209, 91, 79, 182, 172, 27, 7, 29, 128, 198};
Now those elements are in ounces. I get the program to run everything correctly, now my professor wants us to separate the ones that are over 8 pounds into a new array. Those elements in the new array in this case are 258, 209, 182, 172, and 198. The problem is that the program, at the beginning, can create a randomly sized array with varying sized elements between the numbers 1-320. Is there a way to have some sort of loop instantiate the proper amount of "boxes" needed. Or am I just supposed to instantiate some arbitrary number and hope that is what I will need? My current code for this is
public static int [] overGivenPounds(int x, int [] array){
int pounds = 0;
int arrayLength = 0;
int arrayOverEightPounds[];
int k = 0;
for(int i = 0; i < array.length; i++){
pounds = array[i] / 16;
if(x < pounds){
arrayOverEightPounds[k] = array[i];
k++;
}
}
return arrayOverEightPounds;
If any of this seems unclear please ask, there is no need to be rude. I am very new to Java.
Use a loop to determine the size of the target array
Create the target array of the needed size
Use a second loop to put values in the target array
Without that first step, you cannot know the right size of the array. If you create an array that's even one element too small or one element two big, that will be a waste,
because you will be forced to create a 3rd array to return an array of the right size.
So your solution should look something like:
public static int[] overGivenPounds(int x, int[] array) {
int size = 0;
for (int value : array) {
if (satisfies(x, value)) {
size++;
}
}
int[] result = new int[size];
// ??? -> for you to complete this
for (int value : array) {
if (satisfies(x, value)) {
// ??? -> for you to complete this
}
}
return result;
}
public static int[] overGivenPounds(int x, int[] array){
Arrays.sort(array);
boolean foundSomething = false;
int startIndex = 0;
for (int i = 0; i < array.length; i++) {
if(array[i]/16>=x){
startIndex = i;
foundSomething = true;
break;
}
}
if(foundSomething)
return Arrays.copyOfRange(array, startIndex, array.length);
return null;
}
Are you allowed to use Java streams? If so, the solution would be:
return Arrays.stream(myWeights).filter(n -> n/16 > x).toArray();
If not then you could use Arrays.copyOfto create an array of the correct length:
int[] heavyWeights = int[myWeights.length];
int size = 0;
for (int weight: myWeights)
if (weight / 16 > x)
heavyWeights[size++] = weight;
return Arrays.copyOf(heavyWeights, size);
Are you allowed to use other classes? If so, you could just use an ArrayList and then use
//int arrayOverEightPounds[];
List<Integer> listOverEightPounds = new ArrayList<>();
//...
//arrayOverEightPounds[k] = array[i];
listOverEightPounds.add(array[i]);
//....
return listOverEightPounds.toArray(new Integer[0]);
to return an array of the proper size. In this case you can get rid of k. ArrayList uses an array internally but will resize it automatically if it needs more space so you don't have to do that micro-management. The toArray method on ArrayList will return a new array of the proper size if the array that's passed in is not big enough. A common thing you see is to just pass in an array of size 0 into toArray which means the returned value will always be the correctly sized array.
The usual way to do it is to create an array that you know can hold everything, add your items to that array, while keeping track of how many items you have added. At the end you return a copy of the array, truncated to the number of items.
Or, with Java 8, you can write it as a stream one-liner:
return Arrays.stream(array).filter(i -> (i / 16) > x).toArray();

What are some ways I can relate an index to an N length string?

Here's the situation:
I have 36 characters to choose from, a-z and 0-9.
char[] alphabet = "0123456789abcdefghijklmnopqrstuvwxyz".toCharArray();
And using an index, we want to create all possible strings of length N, from N = 1 to N = 2.
A length of 1 is rather simple,
private String generateString(int index){
if (index < 36){
char word = alphabet[index];
return String.valueOf(word);
}
if ( index < 1332) {
//lost
}
}
But what if we wanted a length of 2, well we can assume that all words of length 2 will have an index of > 36 and < 1332 (36 + (36^2)). But I am lost on how to relate these indexes to a word with length 2, and making sure all possible word combinations are hit.
I think there is a mathematical way to accomplish this, but I am just not seeing it.
I'm not sure if I got your question right. Do you want all combinations of letters in various string lengths (like in a brute force attack)? Then this might help you.
If your alphabet consists just of 0-z, then you can make use of Java's Integer.toString() method providing a radix of 36, and just do some counting and padding:
void start(int lengthFrom, int lengthTo) {
for (int length = lengthFrom; length <= lengthTo; length++) {
for (int i=0; i < Math.pow(36, length); i++) {
result(String.format("%" + length + "s", Integer.toString(i, 36)).replace(' ', '0'));
}
}
}
void result(String s) {
System.out.println(s);
}
If you need more flexibility in regard to your alphabet, check this code. Here you can add whatever characters, because it just fills them recursively from left to right:
char[] alphabet = "0123456789abcdefghijklmnopqrstuvwxyz".toCharArray();
void start(int lengthFrom, int lengthTo) {
for (int length = lengthFrom; length <= lengthTo; length++) {
char[] chars = new char[length];
fill(chars, 0);
}
}
void fill(char[] chars, int pos) {
if (chars.length == pos) {
result(new String(chars));
return;
}
for (char c : alphabet) {
chars[pos] = c;
fill(chars, pos+1);
}
}
void result(String s) {
System.out.println(s);
}
This method uses recursion. All recursive algorithms can be transformed to iterative algorithms; which usually consume less memory but are also less easy to read.
If you want an "index" for your Strings, you could build it using the result() method as the passed strings are ordered.
Oh, you're not talking about this, right?
Integer.parseInt(word, 36);
Integer.toString(index, 36);
So that
Integer.parseInt("1z", 36); // int(71)
Integer.toString(71, 36); // "1z"
For the two letter words, create a mapping [1,2,...,1296] -> ["00","01",...,"zz"] by folding the 1d index into a 2d one of size 36, ie. [1,2,...,1296] -> [(1,1), (2,1), (3,1), ..., (36,36)]:
private String generateTwoLetterString(final int index) {
if(index > 1296)
throw new IndexOutOfBoundsException("index is greater than 1296");
int j = (int) Math.ceil(index/36f);
int i = index % 36 == 0 ? 36 : index % 36;
return String.format("%s%s", alphabet[j-1], alphabet[i-1]);
}

Complex Java Permutation Generation Problem

I am trying to work out the best way to generate all possible permutations for a sequence which is a fixed number of digits and each digit has a different alphabet.
I have a number of integer arrays and each one can have different length and when generating the permutations only the values of the array can occupy the position in the final results.
A specific example is an int array called conditions with the following data:
conditions1 = {1,2,3,4}
conditions2 = {1,2,3}
conditions3 = {1,2,3}
conditions4 = {1,2}
conditions5 = {1,2}
and I want to create a 5 column table of all the possible permutations - this case 144 (4x3x3x2x2). Column 1 can only use the values from conditions1 and column 2 from conditions2, etc.
output would be :
1,1,1,1,1
1,1,1,1,2
1,1,1,2,1
1,1,1,2,2
1,1,2,1,1
.
.
through to
4,3,3,2,2
It's been too long since since I've done any of this stuff and most of the information I've found relates to permutations with the same alphabet for all fields. I can use that then run a test after removing all the permutations that have columns with invalid values but sounds inefficient.
I'd appreciate any help here.
Z.
Look ma, no recursion needed.
Iterator<int[]> permutations(final int[]... conditions) {
int productLengths = 1;
for (int[] arr : conditions) { productLengths *= arr.length; }
final int nPermutations = productLengths;
return new Iterator<int[]>() {
int index = 0;
public boolean hasNext() { return index < nPermutations; }
public int[] next() {
if (index == nPermutations) { throw new NoSuchElementException(); }
int[] out = new int[conditions.length];
for (int i = out.length, x = index; --i >= 0;) {
int[] arr = conditions[i];
out[i] = arr[x % arr.length];
x /= arr.length;
}
++index;
return out;
}
public void remove() { throw new UnsupportedOperationException(); }
};
}
Wrapping it in an Iterable<int[]> will make it easier to use with a for (... : ...) loop. You can get rid of the array allocation by doing away with the iterator interface and just taking in as argument an array to fill.

Categories