Raman Spectrum processing in Java - java

I have 2D array of type doubles as spectral data in text file. I have to find peaks in the spectrum. I am using Binary Search to find peaks in the array, but I am getting false peaks also. How can I filter the result I am getting. If anybody know about this please help me
Here is the code which I am using
static ArrayList < Double > nPeaks(double[] array, int range) {
if (array == null) {
System.out.println("Error");
}
double result = 0, l, r;
double[] peaks = null;
// Check main body
for (int i = 0; i < array.length; i++) {
boolean isPeak = true;
// Check from left to right
l = Math.max(0, i - range);
r = Math.min(array.length - 1, i + range);
for (int j = (int) l; j <= r; j++) {
// Skip if we are on current
if (i == j) {
continue;
}
if (array[i] < array[j]) {
isPeak = false;
break;
}
}
if (isPeak) {
//System.out.println("Peak at " + i + " = " + array[i]);
peaklist.add(array[i]);
result++;
i += range;
}
}
return peaklist;
}

Your question is not clear to me. I assume you are generating the max to min order of input array. If yes, you are trying to create a sorted array(descending order).
Simply sort the array in descending order. That will have result like
peak1, peak2, peak3...peakn
where,
peak1 - is max value
peakn - is min value

One of the way to find peaks in spectrum is calculating the disspersion of whole spectrum and then devile it by 3*sigma and take floor funstion. After it you shold "see" only peaks and each place higher than 1 shold be a peak

Related

Finding the smallest number in array list java

So I have some code which is finding the distance between a series of points. One method uses the euclidean distance and is working fine, the other is using Manhattan and I don't know why it isn't working.
I have it set up so that the distance of the first element in the array list is zero for both methods, and therefore should print that image 1 is a match. However the Manhattan method always returns image 31, no matter how many different elements I test it with. I have double checked the elements in the array list and it should be returning image 1.
Does anybody have any ideas? Thanks in advance
public void matchEuclidean(){
for(int i = 0; i < numberimages; i++){
distanceE[i][0] = weights[i][0] - testweights[0][0];
distanceE[i][1] = weights[i][1] - testweights[0][1];
}
for(int i = 0; i < numberimages; i++){
distanceEu[i] = (Math.pow(distanceE[i][0], 2)) + (Math.pow(distanceE[i][1], 2));
distanceEu[i] = Math.sqrt(distanceEu[i]);
}
for (double no : distanceEu) {
list.add(Double.valueOf(no));
}
double max= Collections.min(list);
double min = list.indexOf(max) + 1;
System.out.println("(euclidean) the unknown image matches image " + (min));
}
public void matchManhattan(){
for(int i = 0; i < numberimages; i++){
distanceM[i][0] = weights[i][0] - testweights[0][0];
distanceM[i][1] = weights[i][1] - testweights[0][1];
}
for(int i = 0; i < numberimages; i++){
distanceMu[i] = distanceM[i][0] + distanceM[i][1];
}
for (double no : distanceMu) {
listM.add(Double.valueOf(no));
}
double max= Collections.min(listM);
double min = listM.indexOf(max) + 1;
System.out.println("(Manhattan) the unknown image matches image " + (min));
}
It looks like you neglected to use the Math.abs function in Manhattan distance:
distanceMu[i] = Math.abs(distanceM[i][0]) + Math.abs(distanceM[i][1]);
Without it, you don't really have a valid "distance" function: you can get negative values, and the triangle inequality does not hold
int a[] = {6,22,33,12,44,9};
int low = a[0];
for(int i = 1 ; i < a.length ; i ++ )
{
if(a[i] < low)
{
low = a[i];
}
}
System.out.println("The smallest number is the given array is : " + low);
}
}

How to implement merge sort without recursion

The arrays are always the size of powers of 2, and it can't be recursive.
If I've made any errors in asking my question this is my first time asking a question. Bear with me please.
The plan is to place markers in powers of two then loop through and place the ordered numbers into an array then putting them back in the array. Then should be placed into the original array in the groups that they were placed split into. Gradually getting bigger until the whole array is sorted.
public static void MergeSortNonRec(long[] a) {
//======================
//FILL IN YOUR CODE HERE
//======================
System.out.println(a.length); // print statement
if (a == null)
return;
int subArray1 = 0;
int subArray2 = 1;
int increment = 0;
int swapCounter = 0;
for (int i = 1; i <= a.length; i *= 2) {
// this loop determines the current size of the sub array
increment = i;
subArray1 = 0;
subArray2 = 0;
swapCounter = 0;
while (subArray2 <= a.length) {
// this will loop until we reach the end of the array
subArray2 += increment;
long[] spareArray = new long[2 * i];
swapCounter = 0;
while (swapCounter <= spareArray.length) {
System.out.println(subArray1 + " " + subArray2); // print statement
if (a[subArray1] < a[subArray2]) {
spareArray[swapCounter] = a[subArray1];
swapCounter++;
subArray1++;
} else
if (a[subArray1] > a[subArray2]) {
spareArray[swapCounter] = a[subArray2];
swapCounter++;
subArray2++;
} else
if (a[subArray1] == a[subArray2]) {
spareArray[swapCounter] = a[subArray1];
swapCounter++;
subArray1++;
System.out.println(swapCounter + " " + subArray1); // print statement
spareArray[swapCounter] = a[subArray1];
swapCounter++;
subArray2++;
}
} // this creates an array of the ordered elements
while (swapCounter == spareArray.length) {
subArray1 -= swapCounter / 2;
subArray2 -= swapCounter / 2;
// now the sub array pointers are back to the values they started at
int spareArrayPointer = 0;
for (; subArray1 <= subArray2; subArray1++) {
a[subArray1] = spareArray[spareArrayPointer];
spareArrayPointer++;
} // this places the values in the spare array into the original array
subArray1 -= spareArrayPointer;
spareArrayPointer = 0;
// takes the first pointer back to where it started
}
subArray1 += increment;
subArray2 += increment + increment;
} // end subArray2 <= a.length loop
} // end 2*i loop
} //MergeSortNonRec()
A non-recursive implementation of merge sort could still be based on top down merge sort, using a stack to push and pop pairs of indexes.
A more common implementation of non-recursive merge sort is bottom up, where an array of n elements is treated as n "sorted" runs of size 1 (since their size is 1, they can be considered sorted), then for each merge "pass", merge even and odd runs, which doubles the run size on each pass. Repeat until run size >= array size.
Wiki example. This example could be optimized by swapping A and B after each pass to change the direction of merge with each pass and avoid the copy back except for the lass pass (or determine number of passes in advance, and swap in place to start with run size = 2 before doing the merge passes).
https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation

Calculate the largest best combination of denominations for a number

Problem Statement:
I need to get the best combination of denomination for a given number.
Example: I have three denominations {50,25,10} and given number is 30 then list should return <10,10,10>. for number 80 it should return <50,10,10,10> as remaining 30 is not completely divide by 25.
For 35 it should return <25,10>
for 75 <50,25>
for 65 <50,10>
This is somewhat similar to coin problem but I am not able to get the values of denominations.
Refence StackOverFlow Coin change DP solution to keep track of coins
Here is what I have tried so far :
public static int[] minChange(int[] denom, int changeAmount) {
int n = denom.length;
int[] count = new int[changeAmount + 1];
int[] from = new int[changeAmount + 1];
count[0] = 1;
for (int i = 0; i < changeAmount; i++ )
if (count[i] > 0)
for (int j = 0; j < n; j++ ) {
int p = i + denom[j];
if (p <= changeAmount) {
if (count[p] == 0 || count[p] > count[i] + 1) {
count[p] = count[i] + 1;
from[p] = j;
}
}
}
// No solutions:
if (count[changeAmount] == 0)
return null;
// Build answer.
int[] result = new int[count[changeAmount] - 1];
int k = changeAmount;
while (k > 0) {
result[count[k] - 2] = denom[from[k]];
k = k - denom[from[k]];
}
return result;
}
This works well if value are completely divisible by one of denomination other wise i doesn't work at all.
Once you have the solution in the 2D array for the dynamic programming solution, you can find out what denominations were optimal by backtracking through your array from the end (arr[n][n]).

Finding all possible subset sum which is equal to 0 out of set of positive and negative numbers? [duplicate]

This question already has answers here:
given a set of n integers, return all subsets of k elements that sum to 0
(3 answers)
Closed 6 years ago.
You have an array which has a set of positive and negative numbers, print all the subset sum which is equal to 0.
I can think of approach where i can cam make all powersets of givcen array and check if their sum is 0. BUt that does not llok like optimized solution to
me.
After reading looks a bit similar problem on net , looks like it can be solved with dynamic programming like below program to find if there is combination exist
to make sum 11 just an example ?
public boolean subsetSum(int input[], int total) {
boolean T[][] = new boolean[input.length + 1][total + 1];
for (int i = 0; i <= input.length; i++) {
T[i][0] = true;
}
for (int i = 1; i <= input.length; i++) {
for (int j = 1; j <= total; j++) {
if (j - input[i - 1] >= 0) {
T[i][j] = T[i - 1][j] || T[i - 1][j - input[i - 1]];
} else {
T[i][j] = T[i-1][j];
}
}
}
return T[input.length][total];
}
public static void main(String args[]) {
TestDynamic ss = new TestDynamic();
int arr1[] = {2, 3, 7, 8};
System.out.print(ss.subsetSum(arr1, 11));
}
But i am not sure how to extend above programe to
1) Include negative number
2) find combination of elements whick makes sum as zero( Above program just finds whether its possible to make given sum but does not
find which set of numbers makes it zero)
Here is a full implementation in Javascript. You can run it with node.js.
function target_sum(a, k, x)
{
if (k == a.length) return [];
if (a[k] == x) {
return [[a[k]]];
} else {
var s = target_sum(a, k + 1, x); // not using a[k]
var t = target_sum(a, k + 1, x - a[k]); // using a[k]
for (var i = 0; i < t.length; ++i) {
t[i].unshift(a[k]); // a[k] is part of the solution
s.push(t[i]); // merge t[] into s[]
}
return s;
}
}
var s = target_sum([1,4,5,2,7,8,-3,-5,-6,9,3,-7,-1,5,6], 0, 0);
for (var i = 0; i < s.length; ++i)
console.log(s[i].join(","));
Note that this is an exponential algorithm. Don't use it on large arrays.
Erwin Rooijakkers also pointed to the right direction. In particular, this post gives another algorithm. I could be wrong about the following – I believe that algorithm trades speed for space. It avoids staging arrays into the call stack, but it has to do more recursions to achieve that.
EDIT: about the algorithm you mentioned. It is not exponential, but it only works for positive numbers if I am right. Its time complexity is also proportional to the target sum, which may not be ideal depending on input.

Java duplicates distinct unique array value

I am trying to solve this, but i don't know how...
Values[10] = {1,1,4,4,2,3,3,2,1,3}
to print:
{1,2,3,4} or {1,4,2,3} (not sorted, any order, but distinct)
I also need to count the number of times each number has occurred, both without sort, new arrays or boolean methods or other data structures, please advise as i am stuck.
Is there a simple method i can use to just print the unique values/ distinct values ?
It can be accomplished if your are willing to destroy your current array. and you assume that the array is either of type Integer (so nullable) or if not there is some bound such as all int are poistive so you can use -1.
for(int i = 0; i < values.length; i++){ //for entire array
Integer currVal = values[i]; // select current value
int count = 1; // and set count to 1
if(currVal != null){ // if value not seen
for( int j = i + 1; j < values.length; j++){ // for rest of array
if(values[j] == currVal){ // if same as current Value
values[j] = null; // mark as seen
count++; // and count it
}
}
System.out.print("Number : " + currVal + " Count : " + count + "\n");
//print information
}
// if seen skip.
}
In plain english, Go through the array in 2 loops, roughly O(n^2) time.
Go to index i. If index has not yet been seen (is not null) then go through the rest of array, mark any indexs with same value as seen (make it null) and increment count varable. At end of loop print value and count. If Index has be seen (is null) skip and go to next index. At end of both loops all values will be left null.
Input : Values[] = {1,1,4,4,2,3,3,2,1,3}
Output : Values[] = {1,null,4,null,2,3,null,null,null,null}
Number : 1 Count : 3
Number : 4 Count : 2
Number : 2 Count : 2
Number : 3 Count : 3
Edit: corrected my mistake in output, pointed out by commenters.
Another solution, without creating additional objects:
Arrays.sort(values);
for(int i = 0; i < values.length; i++) {
if (i == 0 || value[i] != value[i-1]) {
System.out.println(values[i]);
}
}
And the shortest solution I can think of:
Integer[] values = {1,1,4,4,2,3,3,2,1,3};
Set<Integer> set = new HashSet<Integer>();
set.addAll(Arrays.asList(values));
System.out.println(set);
Assuming the values are guaranteed to be integers, you could also do it by incrementing a check value, scan over the array, sum the number of that check value in the array, add it to an accumulator and loop while the accumulator < array.length.
Something like this (untested):
public void checkArray(int[] toCheck) {
int currentNum = 0;
int currentCount = 0;
int totalSeen = 0;
StringBuilder sb = new StringBuilder();
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for(int i=0; i<toCheck.length; i++) {
min = Math.min(toCheck[i], min);
max = Math.max(toCheck[i], max);
}
System.out.print("{ ");
for(currentNum = min; currentNum < max; currentNum++) {
for(int i=0; i<toCheck.length; i++) {
if(toCheck[i] == currentNum) currentCount++;
}
if(currentCount != 0) {
if(currentNum == min) System.out.print(currentCount + "(" +currentCount+ ")");
else System.out.print(", " + currentCount + " (" +currentCount+ ")");
}
totalSeen += currentCount;
currentCount = 0;
}
System.out.println(" }");
}
It should be noted that while this technically fulfills all your requirements, it will be far less efficient than gbtimmon's approach.
If your ints were {1,2,3,150000}, for example, it will needlessly spin over all the values between 4 and 149999.
Edit: added better limits from tbitof's suggestion.
Your question isn't quite clear to me, since it sounds like you want to do these things without creating any additional objects at all. But if it's just about not creating another array, you could use a Map<Integer, Integer>, where the key is the number from your original array, and the value is the count of times you've seen it. Then at the end you can look up the count for all numbers, and print out all the keys by using Map.keyset()
Edit: For example:
Map<Integer,Integer> counts = new HashMap<Integer, Integer>();
for( int i : values ) {
if( counts.containsKey(i) ) {
counts.put(i, counts.get(i) + 1);
} else {
counts.put(i, 1);
}
}
// get the set of unique keys
Set uniqueInts = counts.keyset();

Categories