Related
I want to set values in an array based on an index and using a computation. In numpy I would write the following:
array[array < 0] = 2 * array[array < 0]
Can something like this be achieved with ND4J as well?
Edit: And what about more complicated statements / indexing such as:
array[array2 < 0] = 2 * array3[array2 < 0]
(Assuming dimensions of array1, array2 and array3 match)
Conditional assign is what you would be the closest:
import org.nd4j.linalg.indexing.BooleanIndexing;
import org.nd4j.linalg.indexing.conditions.Conditions;
INDArray array1 = Nd4j.create(new double[] {1, 2, 3, 4, 5, 6, 7});
INDArray array2 = Nd4j.create(new double[] {7, 6, 5, 4, 3, 2, 1});
INDArray comp = Nd4j.create(new double[] {1, 2, 3, 4, 3, 2, 1});
BooleanIndexing.replaceWhere(array1, array2, Conditions.greaterThan(4));
There are quite a few conditions and things you can use in there. I would suggest using the second array and applying your arithmetic you want on a whole array and letting BooleanIndexing replace what you want selecting elements from the second array you pass in.
Here is my code
import java.util.*;
public class ArrayExample {
public static void main(String[] args) {
Integer arr[] = {5,4,3,2,15,8,9};
List<Integer> list = Arrays.asList(arr);
Collections.sort(list);
System.out.println(list);
list.add(6);// here I am adding 6 to my array.
System.out.println(list);
// Here I should get output as [2,3,4,5,6,8,9,15]
}
}
You can't because this declaration :
List<Integer> list = Arrays.asList(arr);
From documentation :
Arrays.asList Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)
This method acts as bridge between array-based and collection-based
APIs, in combination with Collection.toArray(). The returned list is
serializable and implements RandomAccess.
for that you can't add to this list, even if you try to remove list.remove(index); this not work.
so to solve your problem you can use :
List<Integer> list = new ArrayList<>();//declare the list
for(Integer i : arr){
list.add(i);//add element by element to the list
}
Or simply you can use :
List<Integer> list = new ArrayList<>(Arrays.asList(arr));
//----------------------------------^------------------^
If you want the array to stay sorted, you will have to sort it after each insert.
However, using a binary search, you could also find the index i where the item should be inserted and insert it there using list.add(i,6). Which would be more efficient.
No you cannot add, as you are using Arrays.asList(arr);
List<Integer> list = Arrays.asList(arr);
asList returning a fixed-size list, you cannot add any element in that, once the list is formed.
You may get java.lang.UnsupportedOperationException
[2, 3, 4, 5, 8, 9, 15]
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at Test.main(Test.java:14)
You can add an element without using a list by using 2 arrays: a source array src and a destination array dest. The destination array will have one more element than the source one. You simply need to copy all the elements of the source array to the destination, and add your new element. Depends on different requirement of your post title & your post body, I added 2 solutions:
Solution 1
This solution add an element to your array AFTER sorting the array, as mentioned in the post title. But please notice that the element added is located at the tail of the new array.
Integer src[] = { 5, 4, 3, 2, 15, 8, 9 };
Integer dest[] = new Integer[src.length + 1];
Arrays.sort(src);
System.out.println(Arrays.toString(src));
// [2, 3, 4, 5, 8, 9, 15]
System.arraycopy(src, 0, dest, 0, src.length);
dest[src.length] = 6;
System.out.println(Arrays.toString(dest));
// [2, 3, 4, 5, 8, 9, 15, 6]
// ^
Solution 2
This solution add an element to your array BEFORE sorting the array. It contains the expected array as mentioned in your code comment in the post body.
Integer src[] = { 5, 4, 3, 2, 15, 8, 9 };
Integer dest[] = new Integer[src.length + 1];
System.arraycopy(src, 0, dest, 0, src.length);
dest[src.length] = 6;
Arrays.sort(dest);
System.out.println(Arrays.toString(dest));
// [2, 3, 4, 5, 6, 8, 9, 15]
// ^
See also:
Sorting methods in Arrays (Java Platform SE 8) - Oracle Help Center
System#arraycopy(Object, int, Object, int, int)
I have a task and I have some problems with it - hard to change a mindset i guess.
I need to create a collection, which keep integers and must perform such functions as:
Add and remove elements by its index and value (okay, i think it can be ArrayList or LinkedList, am I right?)
In case if element will be added other elements must be increased by a value of added element.
In case if element will be removed other elements must be decreased by a value of added element.
Last two functions..I have no clues how to make it. Probably some of you can show me a direction, where I need to move and what I need to do?
In my mind I need to create LinkedList (it allows me to remove elements by its index and value) and use some wrapped types for list. But how?
UPDATE
To clarify (from comments), this is the desired result of calling add() and remove():
add(1): [1]
add(2): [3, 2] // Existing values are incremented
add(3): [6, 5, 3]
add(4): [10, 9, 7, 4]
add(0): [10, 9, 7, 4, 0]
add(5): [15, 14, 12, 9, 5, 5]
remove(3): [15, 14, 12, 9, 5, 5] // Value not found, so no change
remove(9): [6, 5, 3, -4, -4] // All values are decremented
remove(5): [1, -2, -9, -9]
I would use an ArrayList. You can add elements in a specific index with
add(index, value)
You can remove elements by index with
remove(index)
For the second function, you can iterate the full ArrayList and add the value of the new element. After that, you add it to the ArrayList. For the third function you do it the opposite way: fist remove it and then you decrease its value to the remainig elements.
Last thing, remember you shouldn't (in fact I think you can't) remove an element of the ArrayList while you iterate it. So if you want to remove an element by its value, you can iterate the ArrayList keeping the indexes of the elements you want to remove, and then remove them. Hope it helps.
I think you need to get familiar with Java API Collection first, when you do that I'm pretty sure you will be able to resolve what you want.
I recommend this site: http://www.java2novice.com/java-collections-and-util
If I understood your question correctly, you don't need to change the elements in your collection to implement addition and subtraction (from all elements):
You could store in a variable (lets call it diff) the difference between the elements in the collection and the required result and update diff each time you add or remove an element.
Note that when you add an element, you probably have to alter the added element according to diff.
Example:
adding 1 to the array: [0], diff=1, array + diff: [1]
adding 2 to the array: [0, -1], diff=3 , array + diff: [3, 2]
adding 3 to the array: [0, -1, -3], diff=6, array + diff: [6, 5, 3]
removing 5 from array (actually removing 5-diff): [0, -3], diff=1, array + diff: [1,-2]
you can use ArrayList no need to use linkedlist in your use case
you need to iterate over the list and sum the integer with the existing values and add it to the list
you need to check if the list contains the Integer before removing it
you can try this code
public static void main(String[] args) throws Exception {
List<Integer> list = new ArrayList<>();
addAndSum(list, 1);
System.out.println(list);
addAndSum(list, 2);
System.out.println(list);
addAndSum(list, 3);
System.out.println(list);
addAndSum(list, 4);
System.out.println(list);
addAndSum(list, 0);
System.out.println(list);
addAndSum(list, 5);
System.out.println(list);
removeAndSustract(list, 3);
System.out.println(list);
removeAndSustract(list, 9);
System.out.println(list);
removeAndSustract(list, 5);
System.out.println(list);
}
private static void addAndSum(List<Integer> list, Integer i) {
for (int j = 0; j < list.size(); j++)
list.set(j, list.get(j) + i);
list.add(i);
}
private static void removeAndSustract(List<Integer> list, int i) {
if (list.contains(i)) {
list.remove((Integer) i);
for (int j = 0; j < list.size(); j++)
list.set(j, list.get(j) - i);
}
}
the output
[1]
[3, 2]
[6, 5, 3]
[10, 9, 7, 4]
[10, 9, 7, 4, 0]
[15, 14, 12, 9, 5, 5]
[15, 14, 12, 9, 5, 5]
[6, 5, 3, -4, -4]
[1, -2, -9, -9]
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
This question is hard to explain in one sentence, and I also can't seem to find a good, simple way to do it. What I am asking: If I have a list (array) of numbers (Also could be strings), let's say the numbers up to 7, and I want to select 5 of the numbers, all being different, how would I find all the different combinations of five numbers possible, and save them in an array.
e.g. I have a list of 7 numbers. I can only use 5 different numbers. My combinations would be:
1. 1 2 3 4 5
2. 1 2 3 4 6
3. 1 2 3 4 7
4. 1 2 3 5 6
5. 1 2 3 5 7
etc.
How can I write a java program that will give me all these combinations in an array. An explanation would also be appreciated.
You can do this using recursion (not something I say often)
public static <T> void combinations(List<T> values, int maxCount, CombinationListener<T> listener) {
List<T> comb = (List<T>) Arrays.asList(new Object[maxCount]);
boolean[] used = new boolean[values.size()];
combinations0(values, used, comb, 0, maxCount, listener);
}
static <T> void combinations0(List<T> values, boolean[] used, List<T> comb, int idx, int maxCount, CombinationListener<T> listener) {
if (idx == maxCount) {
listener.onComlination(comb);
return;
}
for (int i = 0; i < values.size(); i++) {
if (used[i]) continue;
used[i] = true;
comb.set(idx, values.get(i));
combinations0(values, used, comb, idx + 1, maxCount, listener);
used[i] = false;
}
}
public static void main(String[] args) {
combinations(Arrays.asList(1, 2, 3, 4, 5, 6, 7), 5, new CombinationListener<Integer>() {
#Override
public void onComlination(List<Integer> list) {
System.out.println(list);
}
});
}
interface CombinationListener<T> {
void onComlination(List<T> list);
}
prints
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 6]
[1, 2, 3, 4, 7]
[1, 2, 3, 5, 4]
[1, 2, 3, 5, 6]
[1, 2, 3, 5, 7]
[1, 2, 3, 6, 4]
[1, 2, 3, 6, 5]
[1, 2, 3, 6, 7]
... many deleted ...
[7, 6, 5, 2, 4]
[7, 6, 5, 3, 1]
[7, 6, 5, 3, 2]
[7, 6, 5, 3, 4]
[7, 6, 5, 4, 1]
[7, 6, 5, 4, 2]
[7, 6, 5, 4, 3]
I'm not going to provide you with a full solution as that’s not helpful for anyone but a few suggestions towards an initial solution (not necessarily an optimal one)
By far the simplest thing to do is to create all combinations of any length and eliminate all that aren't of length 5. You can do this by going through each number of the input and determining if you will or won't include it and keeping track of how many included numbers you have; rejecting the combination if it doesn't have 5 numbers at the end.
The naive way to do this would be nested for loops
for(int i=0;i<2;i++){
//either include the first or not depending on if i is 0 or 1
for(int j=0;j<2;j++){
//either include the first or not depending on if i is 0 or 1
for(........
..........
built the combination and if its length 5 add it to a collection
}
}
}
This of course hard codes the size of the original input size; this can be avoiding using a recursive function that takes as arguments a combinationObject that is being built, the inputNumbers and the current recursion depth (so it know which of the input numbers to decide on. And it would return some collection (eg hashset or arraylist) that would be the summation of all the collections generated "below" it in terms of recursion (at each level the function would call itself twice; once for include and once for don't include.
This recursive function would look something like
public Collection<CombinationObject> addDigit(CombinationObject combinationSoFar, InputObject numbersToChooseFrom, int depth){
if (depth==numbersToChooseFrom.size()){
Collection<CombinationObject> collection=new HashSet<CombinationObject>();
collection.add(combinationSoFar.add(numbersToChooseFrom.get(depth); //add a digit
collection.add(combinationSoFar); //don't add a digit
return collection;
}else{
Collection<CombinationObject> collection=new HashSet<CombinationObject>();
collection.addAll(addDigit(combinationSoFar.add(InputObject.getDigit(depth), InputObject numbersToChooseFrom,depth+1);
collection.addAll(addDigit(combinationSoFar, InputObject numbersToChooseFrom,depth+1);
return collection;
}
}
Nb. combinationSoFar should be immutable and the .add method should return a new object
This is probably not an ideal solution in terms of efficiency but will hopefully get you started
Example:
Input: 3, 6, 3
Output: True (since 3 + 3 = 6)
Input: 3, 2, 6, 4
Output: False (since no combination will result in equality)
Input: 4, 7, 3, 6
Output: True (since 4 + 6 = 7 + 3)
can you guys give me an idea on how to code this?
i've started on how to code this but i'm confused on how I can add the numbers and compair them
I'll explain how a person could work on this without knowing magic words (like "partition problem", "dynamic programming", etc.) with which to consult some big book of answers (like Wikipedia).
If you take one instance of the largest not-yet-used number from the input and assign it to one of your two groups, then you have reduced the problem to a smaller instance of (a generalized version of) the same problem.
The generalized problem is, can you divide the input numbers into two groups such that the difference between the two groups' sums is a particular non-negative integer?
Let's say our input numbers are 4, 3, 2, 1 and we need to make two groups so that the difference between the groups' sums is 0.
We assign 4 to one of the groups, and in this particular case it doesn't matter which group.
Now our remaining input numbers are 3, 2, 1 and, ignoring the 4 that we already dealt with, we need to make these three numbers into two groups so that the difference between the groups' sums is 4. (That will balance out the difference between the two groups that we created by assigning the 4 to one of the groups.) As promised, this is a smaller instance of the original type of problem.
The difficulty is that sometimes, such as with 5, 5, 4, 3, 3 (example found in Wikipedia "Partition problem"), it's not obvious which group the next number needs to go into. If you keep track of what you've done, then when you find out your latest attempt didn't work, you can come back ("backtrack") and try the other way.
5, 5, 4, 3, 3 {} {}
5, 4, 3, 3 {5} {}
4, 3, 3 {5} {5}
3, 3 {5, 4} {5}
3 {5, 4} {5, 3}
{5, 4} {5, 3, 3} NO - backtrack
{5, 4, 3} {5, 3} NO - backtrack
3 {5, 4, 3} {5}
{5, 4, 3} {5, 3} NO - already tried - backtrack
{5, 4, 3, 3} {3} NO - backtrack
3, 3 {5} {5, 4} NO - symmetric to what we already tried - backtrack
4, 3, 3 {5, 5} {}
3, 3 {5, 5} {4}
3 {5, 5} {4, 3}
{5, 5} {4, 3, 3} YES
Will we be able to get the answer quickly? Well, this isn't the question that was asked, but in light of the complexity of backtracking, it's natural to ask. And the answer turns out to be, no, not even if we have the smartest person in the history of the world working for us. No one has ever found a method that is guaranteed to perform quickly no matter what instance of this kind of problem we give it. Maybe we can do pretty well for many instances of these problems, but in general and on average, a program to do this sort of thing is destined to be slow.
This is the partition problem, which is NP-complete. Despite that, there's a dynamic programming solution that you can use. See the Wikipedia article.
http://en.wikipedia.org/wiki/Partition_problem
public class Weirdie {
private boolean calculate(int[] array) {
boolean match = false;
List<Integer> list = new ArrayList<Integer>();
int length = array.length;
for(int i=0;i<length;i++) {
for(int j=i+1;j<length;j++) {
int sum = array[i] + array[j];
if(list.contains(sum)) {
match = true;
break;
} else {
list.add(sum);
}
}
if(match) {
break;
}
}
return match;
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] array = { 3, 6, 3, 4, 8};
int[] array2 = { 3, 2, 6, 4};
int[] array3 = { 4, 7, 3, 6 };
Weirdie w = new Weirdie();
System.out.println(w.calculate(array));
System.out.println(w.calculate(array2));
System.out.println(w.calculate(array3));
}
}
Actually I still confusing with your requirement.As your description,number group 1 {3,6,3} will output true because of 3+3=6.And you said number group 2 {3,2,6,4} will output false,but appearently 2+4=6 is also match your condition.With your third number group,I think the reason why number group 1 output true is 3+6=6+3.
To determine is a array can be divided into two equal summed arrays, we can also find a subset which has half the sum of the whole array.
For e.g: Input: 4, 7, 3, 6
We should find a sub set whose sum == 10, which is a simple DP prob.
public static boolean isSubset(int[] a, int sum, int n) {
if(sum == 0)
return true;
if(n<0)
return false;
return isSubset(a, sum-a[n], n-1) || isSubset(a, sum, n-1);
}
OK! just use brute force calculation, my checking every possible option
int[] numbersArray = new int[10];
int sum = 0;
for(int j = 0; j < numbersArray.lenght;j++) // sum
sum += numbersArray[j];
for(int i = 0; i < numbersArray.lenght;i++)
{
int numChecking = numbersArray[i]; // right half ..
if((sum-numChecking) == numChecking)
return true;
}
return false;
// i haven't tested it but, this will check all possibility's for 1 value..