I have a piece of Matlab code but could not find out how to convert to a Java code. What does this row mean? How can be converted to Java?
Matlab code:
b = all(x <= y) && any(x<y);
Hint: x = [1,2,3,4,5], y = [5,4,3,2,1]
What is b as the result?
You can use Java Streams like in
var x = new int[] {1, 2, 3, 4, 5};
var y = new int[] {5, 4, 3, 2, 1};
var b = IntStream.range(0, x.length).allMatch(i -> x[i] <= y[i])
&& IntStream.range(0, x.length).anyMatch(i -> x[i] < y[i]);
not handling x and y having different sizes!
From the matlab official site:
A <= B returns a logical array with elements set to logical 1 (true) where A is less than or equal to B; otherwise, the element is logical 0 (false).
Up to this you have 11100 in the first comparison.
B = all(A) tests along the first array dimension of A whose size does not equal 1, and determines if the elements are all nonzero or logical 1 (true). In practice, all is a natural extension of the logical AND operator.
So all(x <= y) must return 0.
B = any(A) tests along the first array dimension of A whose size does not equal 1, and determines if any element is a nonzero number or logical 1 (true). In practice, any is a natural extension of the logical OR operator.
So any(x < y) should be 1.
&& is AND
The rest is up to you
Related
I have an array of numbers and another number K.
My task is to reduce the number of distinct elements in the array. For that, I can update the array several times. For updating the array, I have to follow these steps:
Select an element at index i and add that element by K, and reduce all other remaining elements by K.
For updating an array I can select the same index several times.
Example:
K = 1
Array: [3,1,3]
Answer: 3
I am picking index = 1, as [3-1, 1+1, 3-1] = [2,2,2] so we have number 2 that appears 3 times so this element occurs maximum number of times. So answer is 3.
Another example:
K = 1
Array: [1,2,2]
Answer: 2
It's not possible to make all elements same, so we have number 2 that appears 2 times, so answer is 2.
Array size can be [1, 1000], and the value of K and elements in array is in range [0, 1000]
Here is my code that I tried, my my approach is not correct.
public static int process(int K, int[] A) {
Map<Integer, Integer> map = new TreeMap<>();
for (int key : A) {
map.put(key, map.getOrDefault(key, 0) + 1);
}
int result = 0;
boolean flag = false;
int last = -1, cur = -1;
for (int key : map.keySet()) {
if (flag == false) {
flag = true;
last = key;
continue;
}
cur = key;
int a = map.get(last), b = map.get(cur);
if (Math.abs(last - cur) > K) {
result += a + b;
} else {
result += Math.max(a, b);
}
}
last = cur;
return result;
}
When looking at the examples with K = 1, it is clear that the answer
depends on the parity of the elements. Only elements with same parity can be set to the same level,
and all elements with same parity can be joined.
For example:
[2 4 6] -> [1 5 5] -> [2 4 4] -> [3 3 3]
[1 2 2] -> [2 1 1] ... no progress
With K = 1, we have to consider value modulo 2, i.e. modulo 2*K.
When K is different of one, for example K = 2, two numbers can be joined only there are separated by a distance multiple of 4, i.e. of 2*K.
[2 6 6] -> [4 4 4]
For K different from 1, instead of creating buckets for numbers with same parity,
we just create buckets according to value modulo 2K.
We just have to pay attention to use the modulo and not the remainder, the values are different for negative values.
Then the answer if simply the highest size of a bucket.
Output:
K = 1 Array : 3 1 3 -> 3
K = 1 Array : 1 2 2 -> 2
K = 1 Array : 2 3 4 7 4 9 11 -> 4
K = 1 Array : -3 -1 2 3 -> 3
K = 3 Array : -7 -1 0 1 2 4 5 -> 3
Here is a simple code in C++ to illustrate the algorithm.
In this code, the value val_modulo modulo 2K of each element is calculated.
Then, the orresponding counter is increased
Bucket[val_modulo] = Bucket[val_modulo] + 1
At the end, the highest value corresponds to the number of repetitions of the most repeated final value.
We may note that the number of non empty bucket corrresponds to the number of different
final values (not used in this code).
#include <iostream>
#include <vector>
#include <string>
#include <map>
void print (const std::vector<int> &A, const std::string &after = "\n", const std::string &before = "") {
std::cout << before;
for (int x: A) {
std::cout << x << " ";
}
std::cout << after;
}
int Modulo (int n, int mod) {
int ans = n % mod;
if (ans < 0) ans += mod;
return ans;
}
int max_equal(int K, std::vector<int> A) {
K = std::abs(K); // useful befoe taking the modulo
std::map<int, int> Buckets;
int nmax = 0;
int mod = 2*K;
for (int x: A) {
int val_modulo = Modulo (x, mod); // and not x*mod, as x can be negative
Buckets[val_modulo]++;
}
for (auto x: Buckets) {
if (x.second > nmax) {
nmax = x.second;
}
}
return nmax;
}
int main() {
std::vector<std::vector<int>> examples = {
{3, 1, 3},
{1, 2, 2},
{2, 3, 4, 7, 4, 9, 11},
{-3, -1, 2, 3},
{-7, -1, 0, 1, 2, 4, 5}
};
std::vector<int> tab_K = {1, 1, 1, 1, 3};
for (int i = 0; i < examples.size(); ++i) {
std::cout << "K = " << tab_K[i] << " Array : ";
print (examples[i], " -> ");
auto ans = max_equal (tab_K[i], examples[i]);
std::cout << ans << "\n";
}
return 0;
}
The problem is conceptual, and translating it in somewhat computing code.
Let's look:
We pick a number (by index, which is irrelevant), and for all the occurrences we add K. All others we subtract K And then the number of same occurrences must be maximal.
The same occurrences can only grow when the picked number + K is equal to another number - K.
The data structure:
A map with the array numbers as key, and mapped to frequency (how often the number occurs in the array).
So:
pickedNumber.value + K = otherNumber.value - K
=> otherNumber.value = pickedNumber.value + 2*K
Note that as there is only one single otherNumber, derived from the pickedNumber.
(It might occur more than once.)
And we want maximal:
pickedNumber.frequency + otherNumber.frequency maximal.
Though map is not really needed, a sorted array would do too, let's do a map:
The algorithm:
Kept simple.
int[] numbers = {3, 1, 3};
int index = pickedIndexOfBestSolution(numbers, 1);
System.out.println("Index: " + index);
int pickedIndexOfBestSolution(int[] numbers, int k) {
Map<Integer, Long> frequencyTable = IntStream.of(numbers)
.boxed()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
int bestNumber = frequencyTable.entrySet().stream()
.sorted(Comparator.comparingLong(e -> -e.getValue()
- frequencyTable.getOrDefault(e.getKey() + 2*k, 0L)))
.findFirst()
.map(e -> e.getKey())
.orElseThrow();
int index = -1;
while (numbers[++index] != bestNumber) {
}
return index;
}
The frequency table I filled using an IntStream and groupingBy (just as SQL).
As counting is done with long, I just kept that.
To find the max I counted the new occurrence count trying to add the "other" number's frequency too; 0 when no other number.
Instead of using .reverse() to reverse the comparison (largest, max, first), I took the negative value, which to me seems more calculatory.
Notice that a Stream with findFirst to find the max is probably optimal too: no need that the stream creates an intermediate list.
For the index I used brute force (while loop), a kind of indexOf.
Notice if there is no other number, it returns the index of a number with the most occurrences. Which is fine.
In short:
You see the different approach. Actually simpler, and more solid. In fact applying
some (minor) intelligence first. Trying to nail down the problem first.
Given two arrays of ints, a and b, try to create an arithmetic sequence by adding ints from b into a. Return the maximum length of a or -1 if there does not exist an arithmetic sequence e.g. a = [2, 4, 8], b = [1, 6, 10, 12] -> a = [2, 4, 6, 8, 10, 12] -> return 6
I tried creating a new array and merging both a and b and counting the longest subsequence but the count could remove elements from a which should not be touched
static int maxSeq(int[] arr1, int[] arr2){
if(arr1.length ==0)return 0;
int n =arr1.length, m = arr2.length;
int[] arr = new int[n+m];
System.arraycopy(arr1,0,arr,0,n);
System.arraycopy(arr2,0,arr,n,m);
Arrays.sort(arr);
int result =0;
Map<Integer,Integer>[]d = new HashMap[n+m];
for(int i =0; i < arr.length;i++){
d[i] = new HashMap<Integer, Integer>();
}
for(int i =1; i < arr.length; ++i){
for(int j = 0; j<i;++j ){
int diff = arr[i]-arr[j];
int len =2;
if(d[j].containsKey(diff)){
len = d[j].get(diff) +1;
}
d[i].put(diff,len);
result = Math.max(result,d[i].get(diff));
}
}
return result;
}
a = [2, 4, 8], b = [1, 6, 10, 12] -> a = [2, 4, 6, 8, 10, 12] -> return 6
int[] a = {5,7,13,14}, b = {9,11,15}; return -1 not 6
I think you should try to fix your code.
if(d[j].containsKey(diff)){ len = d[j].get(diff) +1; }
Here you are looking for differences in a map of some index j, and there should be only one map of key value paires, not array of maps.
The key here is to fill in array A with numbers from array B so A become an arithmetic sequence.
Solution:
First find the minimum gap between 2 consequence number in A
With the given "gap", try to see if an arithmetic sequence can be build by looping through the 2 arrays, and find out if numbers in B can fill in array A so A become arithmetic with step = "gap". Take count of the length if success.
If it can be found, try to see if smaller gap can build longer arithmetic sequence by looping through all the divisor of the original "gap" as the new "gap" and test again. (example: A = [ 1,5], B= [3,7,9] => Previous step see that we can build arithmetic sequence [1,5,9], but the final answer should be [1,3,5,7,9].
I'd like to share my solution (probably is not optimized and I did not wrote many tests, but it worked on your two sample tests):
Idea:
Notice the common difference d of arithmetic sequence is upperbounded by min(a[i] - a[i-1]), otherwise we won't be able to visit all elements in a
We iterate on common difference d to check the length of each potential list, and find the max length
Complete code in Python:
(Suppose a, b are both sorted)
def max_arithmetic_length(a, b):
min_diff = float('inf') # common difference d is upper bounded by min_diff
for i in range(1, len(a)):
min_diff = min(min_diff, a[i] - a[i-1])
d_a = {x : True for x in a}
d_b = {x : True for x in b}
max_cnt = 0
for d in range(1, min_diff + 1):
skip_current_d = False # a switch to skip outer loop
for x in a:
if (x - a[0]) % d != 0: # must exist: a[i] - a[0] = kd
skip_current_d = True
break
if skip_current_d:
continue
cur = a[0]
cnt = 0
visited = {}
while cur in d_a or cur in d_b:
cnt += 1
visited[cur] = True
cur += d
if a[-1] not in visited: # if the last element in a is visited, then every element in a is visited
continue
# check those smaller than a[0] (may only exist in b)
cur = a[0] - d
while cur in b:
cnt += 1
cur -= d
max_cnt = max(cnt, max_cnt)
return max_cnt if max_cnt else -1
a = [2, 4, 8]
b = [1, 6, 10, 12]
print(max_arithmetic_length(a,b)) # return 6
a = [5,7,13,14]
b = [9,11,15]
print(max_arithmetic_length(a,b)) # return -1
Before Java 8 versions, we can initialize a two-dimensional array using for loop like below. How can I do the below in JDK 1.8 using lambda expressions?
int[][] board = new int[3][3];
int v = 1;
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = v;
v++;
System.out.println(v);
}
}
System.out.println(Arrays.deepToString(board));
Basically, I am looking for an array like below
[[1,6],[2,7],[3,8],[4,9]]
I highly recommend you stick with using the for-loop for initialization of arrays with primitive values. My recommendation is stronger in the case of a multidimensional array.
However, here is the way:
int a = 4; // Number of outer array elements
int b = 2; // Number of inner array elements
int[][] board = IntStream
.range(0, a) // iterate 0..3
.mapToObj(i -> IntStream.range(0, b) // for each iteratoe 0..1
.map(j -> 1 + (i + (a + 1) * j)) // calculate the value
.toArray()) // compose the inner array
.toArray(int[][]::new); // compose the outer array
Note that the IntStream is able to create an array of primitives since it is a sequence of primitive int-valued elements. its method IntStream::toArray reutrns int[].
The composition of the outer array is a bit tricky since int[] is no longer a primitive value but an array itself. There is needed to use a method IntStream::mapToObj which maps int to an object - then the Stream<int[]> is returned and the method Stream::toArray(IntFunction<A[]> generator) converting to array with parameter has to be used since you cannot convert Object[] to int[][].
The parameter passed is simple. int[][]::new is nothing different than i -> new int[a][b].
Use IntStream. This will create a continuous stream of integers from 0 inclusive to n exclusive. So for a 3 x 3 matrix, the IntStream is 0, 1, 2.
make another IntStream for each integer in the outer stream from 0 to number of columns - also 3.
You cannot increment v in a stream because it must be "effectively final". Instead we use the equation board[j][i] = 1 + (j + m * i) which is effectively the similar to computing the index of the value if you were to flatten board into a single array (1D matrix).
import java.util.stream.IntStream;
import java.util.Arrays;
class J {
public static void main(String[] args) {
int n = 4;
int m = 2;
// n x m matrix
int[][] board = new int[n][m];
// Cols (m)
IntStream.range(0, m).forEach( i -> {
// Rows (n)
IntStream.range(0, n).forEach( j -> {
// Multiply i by row count
// to account for the row we are in
board[j][i] = 1 + (j + n * i);
});
});
System.out.println(Arrays.deepToString(board));
}
}
Output:
[[1, 5], [2, 6], [3, 7], [4, 8]]
Note: Just because streams allow you to write a neater, functional programming-like syntax, there is often times an associated performance toll. It stresses the idea, "why fix what's not broken?". For a 3 x 3 board, you probably won't see a difference. But, if your board were a lot larger, it probably won't prove itself to be worth it, considering all the objects created and extra space used behind the scene. Sometimes a simple for-loop (especially when working with arrays) is better.
Remember, simplicity is key.
Here is a stream solution that is "nested for cycles" look a like.
Get the sequence of the numbers from 0 to N(Upper limit exclusive -> N = board.length;
Get the sequence of the numbers from 0 to M(Upper limit exclusive -> M = board[i].length;
For each of the couples (i, j) set the value of board[i][j] using the func (i + j * step + 1) where step is defined as 5.
Output for int[][] board = new int[4][2];
[[1, 6], [2, 7], [3, 8], [4, 9]]
Output for int[][] board = new int[4][3];
[[1, 6, 11], [2, 7, 12], [3, 8, 13], [4, 9, 14]]
int step = 5;
IntStream.range(0, board.length).forEach(i ->
IntStream.range(0, board[i].length).forEach(j ->
board[i][j] = i + j * step + 1
)
);
You can use a combination of the IntStream methods range and iterate:
int width = 4, height = 2;
IntStream.rangeClosed(1, width)
.mapToObj(column -> IntStream.iterate(column, v -> v + width)
.limit(height)
.toArray())
.toArray(int[][]::new);
By using iterate for the inner loop and rangeClosed(1, width) instead of range(0, width) we can simplify the calcuation a bit. Using toArray removes the need to create and modify the array yourself and would enable parallel processing.
It is important to actually use streams properly to make them more than just weird looking for loops. Merely replacing your loop by a range(0, x).forEach(...) to modify a local variable does not really "use streams", and it is better to stick to for loops then.
A question in the Barron's APCS book asks to consider the following program segment:
// Precondition: a[0]...a[n-1] is an initialized array of integers, and 0 < n <= a.length.
int c = 0;
for (int i = 0; i < n; i++) {
if (a[i] >= 0) {
a[c] = a[i];
c++;
}
}
n = c;
Given the segment, I am supposed to choose the best postcondition for the segment. The postconditions given are:
A) a[0]...a[n-1] has been stripped of all positive integers.
B) a[0]...a[n-1] has been stripped of all negative integers.
D) a[0]...a[n-1] has been stripped of all nonnegative integers.
C) a[0]...a[n-1] has been stripped of all occurrences of zero.
E) The updated value of n is less than or equal to the value of n before execution of the segment.
The book says the correct answer is B. Why is that? If array a were to contain only negative integers, the value of n at the end of the segment would be 0, and a[0]...a[n-1] would then be a[0]...a[-1].
The answer of the book is wrong.
The correct answer is E.
Suppose n = 5, and you have 5 values a[i = 0, 4] = {-1, -2, -3, 4, 5}
After execution the value of a[i] are: {4, 5, -3, 4, 5}
And n = c = 2
The function read: Loop through the list, if a non-negative int found (n >= 0) then update the beginner of array with a copy value of it.
Hence c = non-negative int count
From this observation, you can choose the correct answer then.
Consider 9 variables that can have values from to 1 to 9 each. What is a good and fast way to check if each variables has a distinct value. The first thought came to my mind was to sum them up to see if it is equal to n(n+1)/2 but this is nowhere foolproof. Any ideas?
Edit : Thanks a lot guys. Totally forgot about Set. What a noob I am.
Add them all to a Set, and check that the size of the Set is 9.
For example, to check if an array of 9 int are all different:
int[] array = new int[9];
// fill array
Set<Integer> set = new HashSet<Integer>();
for (int i : array)
set.add(i);
boolean allDistinct = set.size() == 9;
The set does all the work, because sets only allow distinct values to be added. If any values are the same, the size will be less than 9.
This technique works for any class of value types, any range and any quantity of values.
Start with a bitmask with bits 0 through 9 set, then clear the bits corresponding to values of each variable. If the resultant bitmask is a power of two, all values were distinct+; otherwise, there were duplicates.
int a, b, c, d, e, f, g, h, i;
int mask = 0x3FF; // bits zero through 9 are set
mask &= ~(1<<a);
mask &= ~(1<<b);
...
mask &= ~(1<<i);
if ((mask & -mask) == mask) {
// all bits were distinct
}
See this answer for an explanation of the bit trick used in the last condition.
+ You have ten possible values and nine variables; in order for the nine values to be distinct, they must clear out nine out of ten bits from the bitmask with all ten bits initially set. Removing nine out of ten bits leaves you with only one bit set to 1, meaning that the result is a power of two.
Use XOR to find the duplicate number is a trick.
int[] arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 9 };
int answer = 0;
for (int i = 0; i < arr.length; i++) {
answer = answer ^ (arr[i] + 1) ^ i;
}
System.out.println(answer - 1);
Output:
5
This algorithm is working with any count of number, but every number must be in interval <0, 31> or you can change mask and bit type to long for interval <0, 63>.
int[] numbers = {0, 1, 2, 3, 3, 5, 6, 7};
int mask = 0;
for (int number : numbers) {
int bit = 1 << number;
if ((mask & bit) > 0) {
System.out.println("Found duplicity " + number);
return;
}
mask |= bit;
}
System.out.println("No duplicity");