How to find nearest value in java from POJO properties? - java

class CalorieExpenditures {
String activity
int lbs90
int lbs100
int lbs110
int lbs120
int lbs130
int lbs140
int lbs150
int lbs160
int lbs170
int lbs180
int lbs190
int lbs200
int lbs220
int lbs240
int lbs260
int lbs280
int lbs300
}
From the above POGO (b'se i am using grails).
How to find the nearest lbs property from POGO
e.g
if i pass 282 it will return lbs280 and if i pass 295 it will return lbs300.
logic is the difference between two values if the difference is same will return the grater value.
You can suggest java method or grails method to work with.
I need a simple program that finds nearest value.
Thanks in advance.

Below is example to find given number from int array, with nearest lower & upper
public class FindNearestInt
{
public static void main(String[] args)
{
Random random = new Random();
int array[] = new int[30];
//Initialise array with rendom values
for (int i = 0; i < array.length; i++)
{
array[i] = random.nextInt(200);
}
System.out.println(Arrays.toString(array));
Arrays.sort(array);
System.out.println(Arrays.toString(array));
// Number you want to find in array
int searchFor = 57;
//Nearest lower you searching for
int nearestLower = 0;
//Nearest upper you searching for
int nearestUpper = Integer.MAX_VALUE;
int searchForExist = -1;
for (int i = 0; i < array.length; i++)
{
int j = array[i];
if (j < searchFor)
{
if(j > nearestLower){
nearestLower = j;
}
} else if (j > searchFor){
if(j < nearestUpper){
nearestUpper = j;
}
} else {
nearestLower = -1;
nearestUpper = -1;
searchForExist = j;
break;
}
}
System.out.println("Nearest Lower : " + nearestLower);
// This will print -1 if number exist in array
System.out.println("Provided Number Already Exist : " + searchForExist);
System.out.println("Nearest Upper : " + nearestUpper);
}
}

A simpler and faster solution is to use a formula
public static int nearest(int num) {
return num < 90 ? 90 :
num < 200 ? Math.round(num/10.0) * 10 :
num < 300 ? Math.round(num/20.0) * 20 : 300;

def calorieExpendituresWeightCategory(float weight){
int nearest = 0;
int min = Integer.MAX_VALUE
CalorieExpenditures.properties.each {
if(it.toString().startsWith("lbs")){
int j = it.toString().substring(it.toString().indexOf("lbs"))
int k = (weight - j) * (weight - j)
if(k < min){
min = k
nearest = j
}
}
}
return nearest
}
This works for me i think simple and works for me.
Thanks for the answers.

Related

Tim Sort vs LSD Radix Sort for Suffix Arrays?

I'm confused on why tim sort which makes my suffix array implement O(nlognlogn) faster than LSD radix sort which should make the implementation O(nlogn). Perhaps is it that radix sort simply works better with larger string lengths?
here is my radix sort implementation in java and I don't know if I'm just not making it as efficient as it could be:
class Suffix {
int index;
int[] rank = new int[2];
public Suffix(int i, int r1, int r2){
index = i;
rank[0] = r1;
rank[1] = r2;
}
}
public class Main {
public static int getMax(Suffix[] suffixArray, int index){
int max = Integer.MIN_VALUE;
for(Suffix i : suffixArray){
if(i.rank[index] > max)max = i.rank[index];
}
return max;
}
public static void countingSort(Suffix[] suffixes, int exp, int index){
int[] count = new int[10];
Suffix[] sorted = new Suffix[suffixes.length];
for(Suffix i : suffixes)count[(i.rank[index]/exp) % 10]++;
for(int i = 1; i < 10; i++)count[i] += count[i - 1];
for(int i = suffixes.length - 1; i >= 0; i--){
Suffix current = suffixes[i];
int position = count[(current.rank[index]/exp) % 10] - 1;
sorted[position] = current;
count[(current.rank[index]/exp) % 10]--;
}
for(int i = 0; i < suffixes.length; i++)suffixes[i] = sorted[i];
}
public static void radixSort(Suffix[] suffixes, int index){
int max = getMax(suffixes, index);
for(int exp = 1; max/exp > 0; exp *= 10)countingSort(suffixes, exp, index);
}
public static void sort(Suffix[] suffixes){
int positiveCounter = 0;
for(Suffix i : suffixes){
if(i.rank[1] >= 0)positiveCounter++;
}
Suffix[] positives = new Suffix[positiveCounter];
int positivesIndex = 0;
int tempIndex = 0;
for(Suffix i : suffixes){
if( i.rank[1] >= 0){
positives[positivesIndex] = i;
positivesIndex++;
}
else {
suffixes[tempIndex] = i;
tempIndex++;
}
}
radixSort(positives, 1);
for(int i = 0; i < positives.length; i++){
suffixes[tempIndex] = positives[i];
tempIndex++;
}
radixSort(suffixes, 0);
}

Find the max value of the same length nails after hammered

I'm trying to solve this problem:
Given an array of positive integers, and an integer Y, you are allowed to replace at most Y array-elements with lesser values. Your goal is for the array to end up with as large a subset of identical values as possible. Return the size of this largest subset.
The array is originally sorted in increasing order, but you do not need to preserve that property.
So, for example, if the array is [10,20,20,30,30,30,40,40,40] and Y = 3, the result should be 6, because you can get six 30s by replacing the three 40s with 30s. If the array is [20,20,20,40,50,50,50,50] and Y = 2, the result should be 5, because you can get five 20s by replacing two of the 50s with 20s.
Below is my solution with O(nlogn) time complexity. (is that right?) I wonder if I can further optimize this solution?
Thanks in advance.
public class Nails {
public static int Solutions(int[] A, int Y) {
int N = A.length;
TreeMap < Integer, Integer > nailMap = new TreeMap < Integer, Integer > (Collections.reverseOrder());
for (int i = 0; i < N; i++) {
if (!nailMap.containsKey(A[i])) {
nailMap.put(A[i], 1);
} else {
nailMap.put(A[i], nailMap.get(A[i]) + 1);
}
}
List < Integer > nums = nailMap.values().stream().collect(Collectors.toList());
if (nums.size() == 1) {
return nums.get(0);
}
//else
int max = nums.get(0);
int longer = 0;
for (int j = 0; j < nums.size(); j++) {
int count = 0;
if (Y < longer) {
count = Y + nums.get(j);
} else {
count = longer + nums.get(j);
}
if (max < count) {
max = count;
}
longer += nums.get(j);
}
return max;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String[] input = scanner.nextLine().replaceAll("\\[|\\]", "").split(",");
System.out.println(Arrays.toString(input));
int[] A = new int[input.length - 1];
int Y = Integer.parseInt(input[input.length - 1]);
for (int i = 0; i < input.length; i++) {
if (i < input.length - 1) {
A[i] = Integer.parseInt(input[i]);
} else {
break;
}
}
int result = Solutions(A, Y);
System.out.println(result);
}
}
}
A C++ implementation would like the following where A is the sorted pin size array and K is the number of times the pins can be hammered.
{1,1,3,3,4,4,4,5,5}, K=2 should give 5 as the answer
{1,1,3,3,4,4,4,5,5,6,6,6,6,6,6}, K=2 should give 6 as the answer
int maxCount(vector<int>& A, int K) {
int n = A.size();
int best = 0;
int count = 1;
for (int i = 0; i < n-K-1; i++) {
if (A[i] == A[i + 1])
count = count + 1;
else
count = 1;
if (count > best)
best = count;
}
int result = max(best+K, min(K+1, n));
return result;
}
Since the array is sorted to begin with, a reasonably straightforward O(n) solution is, for each distinct value, to count how many elements have that value (by iteration) and how many elements have a greater value (by subtraction).
public static int doIt(final int[] array, final int y) {
int best = 0;
int start = 0;
while (start < array.length) {
int end = start;
while (end < array.length && array[end] == array[start]) {
++end;
}
// array[start .. (end-1)] is now the subarray consisting of a
// single value repeated (end-start) times.
best = Math.max(best, end - start + Math.min(y, array.length - end));
start = end; // skip to the next distinct value
}
assert best >= Math.min(y + 1, array.length); // sanity-check
return best;
}
First, iterate through all the nails and create a hash H that stores the number of nails for each size. For [1,2,2,3,3,3,4,4,4], H should be:
size count
1 : 1
2 : 2
3 : 3
4 : 3
Now create an little algorithm to evaluate the maximum sum for each size S, given Y:
BestForSize(S, Y){
total = H[S]
while(Y > 0){
S++
if(Y >= H[S] and S < biggestNailSize){
total += H[S]
Y -= H[S]
}
else{
total += Y
Y = 0
}
}
return total;
}
Your answer should be max(BestForSize(0, Y), BestForSize(1, Y), ..., BestForSize(maxSizeOfNail, Y)).
The complexity is O(n²). A tip to optimize is to start from the end. For example, after you have the maximum value of nails in the size 4, how can you use your answer to find the maximum number of size 3?
Here is my java implementation: First I build a reversed map of each integer and its occurence for example {1,1,1,1,3,3,4,4,5,5} would give {5=2, 4=2, 3=2, 1=4}, then for each integer I calculate the max occurence that we can get of it regarding the K and the occurences of the highest integers in the array.
public static int ourFunction(final int[] A, final int K) {
int length = A.length;
int a = 0;
int result = 0;
int b = 0;
int previousValue = 0;
TreeMap < Integer, Integer > ourMap = new TreeMap < Integer, Integer > (Collections.reverseOrder());
for (int i = 0; i < length; i++) {
if (!ourMap.containsKey(A[i])) {
ourMap.put(A[i], 1);
} else {
ourMap.put(A[i], ourMap.get(A[i]) + 1);
}
}
for (Map.Entry<Integer, Integer> entry : ourMap.entrySet()) {
if( a == 0) {
a++;
result = entry.getValue();
previousValue = entry.getValue();
} else {
if( K < previousValue)
b = K;
else
b = previousValue;
if ( b + entry.getValue() > result )
result = b + entry.getValue();
previousValue += entry.getValue();
}
}
return result;
}
Since the array is sorted, we can have an O(n) solution by iterating and checking if current element is equals to previous element and keeping track of the max length.
static int findMax(int []a,int y) {
int n = a.length,current = 1,max = 0,diff = 0;
for(int i = 1; i< n; i++) {
if(a[i] == a[i-1]) {
current++;
diff = Math.min(y, n-i-1);
max = Math.max(max, current+diff);
}else {
current = 1;
}
}
return max;
}
given int array is not sorted than you should sort
public static int findMax(int []A,int K) {
int current = 1,max = 0,diff = 0;
List<Integer> sorted=Arrays.stream(A).sorted().boxed().collect(Collectors.toList());
for(int i = 1; i< sorted.size(); i++) {
if(sorted.get(i).equals(sorted.get(i-1))) {
current++;
diff = Math.min(K, sorted.size()-i-1);
max = Math.max(max, current+diff);
}else {
current = 1;
}
}
return max;
}
public static void main(String args[]) {
List<Integer> A = Arrays.asList(3,1,5,3,4,4,3,3,5,5,5,1);
int[] Al = A.stream().mapToInt(Integer::intValue).toArray();
int result=findMax(Al, 5);
System.out.println(result);
}

Find Median from a 2D Matrix where each row should be sorted and the multiplication of row and column number should be odd

Suppose a matrix of 3X3 where the elements are [{1,2,3}{3,6,6}{5,9,9}]. The expected output is 5. But the added code here showing 9. As the solution here is a copy from internet, please help me to understand the code as well. How the min-max value help to find the median and the other approaches as well as the use of binary search.
public class Solution {
public int binarySearch(ArrayList<Integer> arr, int x)
{
int l = 0, r = arr.size() - 1;
while (l <= r)
{
int m = l + (r-l)/2;
if (arr.get(m) == x)
return m;
if (arr.get(m) < x)
l = m + 1;
else
r = m - 1;
}
return -1;
}
public int findMedian(ArrayList<ArrayList<Integer>> A) {
int start=0;
int end=A.size()*A.get(0).size();
int value=-1;
int row=A.size();
int col=A.get(0).size();
int max=Integer.MIN_VALUE;
int min=Integer.MAX_VALUE;
for(int i=0;i<A.size();i++){
if(A.get(i).get(0)<min){
min=A.get(i).get(0);
}
if(A.get(i).get(col-1)>max){
max=A.get(i).get(col-1);
}
}
int desiredIndex=(row * col+1)/2;
while(min<max){
int mid=min+(max-min)/2;
int place = 0;
int index = 0;
for(int i = 0; i < row; ++i)
{
index = binarySearch(A.get(i),mid);
System.out.println("index of : "+index);
if(index < 0)
index = Math.abs(index) - 1;
else
{
while(index <A.get(i).size() && A.get(i).get(index) == mid)
index += 1;
}
place = place + index;
}
if (place < desiredIndex)
min = mid + 1;
else
max = mid;
}
return min;
}
}
I'm not sure where you were searching, but the solution to your problem is readily available online:
public class MedianInRowSorted {
// function to find median in the matrix
static int binaryMedian(int m[][],int r, int c)
{
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for(int i=0; i<r ; i++)
{
// Finding the minimum element
if(m[i][0] < min)
min = m[i][0];
// Finding the maximum element
if(m[i][c-1] > max)
max = m[i][c-1];
}
int desired = (r * c + 1) / 2;
while(min < max)
{
int mid = min + (max - min) / 2;
int place = 0;
int get = 0;
// Find count of elements smaller than mid
for(int i = 0; i < r; ++i)
{
get = Arrays.binarySearch(m[i],mid);
// If element is not found in the array the
// binarySearch() method returns
// (-(insertion_point) - 1). So once we know
// the insertion point we can find elements
// Smaller than the searched element by the
// following calculation
if(get < 0)
get = Math.abs(get) - 1;
// If element is found in the array it returns
// the index(any index in case of duplicate). So we go to last
// index of element which will give the number of
// elements smaller than the number including
// the searched element.
else
{
while(get < m[i].length && m[i][get] == mid)
get += 1;
}
place = place + get;
}
if (place < desired)
min = mid + 1;
else
max = mid;
}
return min;
}
You can test it by running this code inside your main method:
int matrix [][] = {{1,2,3},{3,6,6},{5,9,9}};
System.out.println(binaryMedian(matrix, 3, 3));
It'll return 5, which is the correct median. Let me know if you have any questions and I can go more in depth as to how the function works!

Why does the maximum sum subarray stop working consistently if my int array has more than 65535 elements?

I have a program that generates an array based on the user input (the array can be descending, ascending and two types of random) and then it calculates the maximum subarray sum using bruteforce, divide and conquer, and dynamic programming. It seems to work fine and dandy up to values of 65535. After that, each sum is different, which shouldn't happen. 35535 is 2 to the power of 16 minus 1, so I was wondering if I'm hitting some limit. When I print the array it seems to print fine, so I don't think that the problem is that the array isn't generating properly.
This is the main class:
public class MainClass {
public static void main(String[] args) {
int n = Integer.parseInt(args[1]);
int[] maxsubarray1;
maxsubarray1 = new Generator(n,args[3]).getArray();
int[] maxsubarray2 = Arrays.copyOf(maxsubarray1,maxsubarray1.length);
int[] maxsubarray3 = Arrays.copyOf(maxsubarray1,maxsubarray1.length);
System.out.println(Arrays.toString(maxsubarray1));
solver solver = new solver();
int solution;
//if (args[5].equalsIgnoreCase("bruteforce")){
long startTime = System.currentTimeMillis();
solution = solver.bruteforce(maxsubarray1, n);
System.out.println("__________BRUTE FORCE________\nThe sum of the array is "+solution);
long endTime = System.currentTimeMillis() - startTime;
System.out.println(endTime);
//}
//if (args[5].equalsIgnoreCase("divideconquer")){
long startTime2 = System.currentTimeMillis();
int solutiondivideconquer = solver.divideconquer(maxsubarray2, 0, n);
System.out.println("__________DIVIDE AND CONQUERE________\nThe sum of the array is "+ solutiondivideconquer);
long endTime2 = System.currentTimeMillis() - startTime2;
System.out.println(endTime2);
//}
//if (args[5].equalsIgnoreCase("dynprog")){
long startTime3 = System.currentTimeMillis();
int solutiondynprog = solver.dynprog(maxsubarray3, n);
System.out.println("__________DYNAMIC PROGRAMMING________\nThe sum of the array is "+ solutiondynprog);
long endTime3 = System.currentTimeMillis() - startTime3;
System.out.println(endTime3);
//}
}
}
This is the generator code:
import java.util.concurrent.ThreadLocalRandom;
public class Generator {
int size;
String type;
int[] generatedArray;
public Generator(int mysize, String mytype){
size = mysize;
type = mytype;
generatedArray = new int[size];
}
public void ascending(){
for(int i = 0; i < this.size; i++)
generatedArray[i] = i+1;
}
public void descending(){
for(int i = this.size -1; i >= 0; i--)
generatedArray[i] = i+1;
}
public void random(){
for(int i = 0; i <= this.size -1; i++)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10*this.size, 10*this.size);
}
public void randominter(){
for(int i = 0; i <= this.size -1; i++)
if (i % 2 == 0)
generatedArray[i] = ThreadLocalRandom.current().nextInt(1, 10*this.size);
else if (i % 2 == 1)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10*this.size, -1);
}
public int[] getArray(){
if (type.equalsIgnoreCase("descending")){
this.descending();
return generatedArray;
}
if (type.equalsIgnoreCase("ascending")){
this.ascending();
return generatedArray;
}
if (type.equalsIgnoreCase("random")){
this.random();
return generatedArray;
}
if (type.equalsIgnoreCase("randominter")){
this.randominter();
return generatedArray;
}
return null;
}
}
And this is the solver class:
public class solver {
//brute force algorithm with complexity O(n^2)
int bruteforce(int array[], int n){
int max = Integer.MIN_VALUE;
//We go throght all the elements of the list and we try all the
//posible combinations with all the other elements
for (int i = 0; i < n; i++){
int sum = 0;
for (int j = i; j < n ; j++){
//we add the an element in the sum
sum += array[j];
//we check if the sum with the new element is greater that the value we had before
if(sum > max){
//if it's greater, it becomes the new value
max = sum;
}
}
}
//we return the maximum value we have found
return max;
}
//to implement the divide and conquer algorithm we have to take into account the
// maximum subarray can have elements in the right subarray and in the left subarray
int maxCrossingSum(int array[], int l, int m, int h){
int sum = 0;
int left_sum = Integer.MIN_VALUE;
//Has the elements on the left part of the arrray
for ( int i = (int)m; i >= l; i--){
sum = sum + array[i];
if( sum > left_sum ){
left_sum = sum;
}
}
sum = 0;
int right_sum = 0;
//Has the elements in the right part of the array
for ( int j = (int)m+1; j <= h; j++){
sum = sum + array [j];
if (sum > right_sum){
right_sum = sum;
}
}
//returns the sun of the elements on the left and the right of the array
return left_sum + right_sum;
}
//returns the sum of the maximum subarray
int maxSubarraySum(int array[], int l, int h){
if(l == h)
return array[1];
int m = (l + h)/2;
//checks which is the maximum between left and right
int maxBetweenLeftRight = max(maxSubarraySum(array, l, m), maxSubarraySum(array, m+1,h));
int crossing = maxCrossingSum(array, l, m,h-1);
//retrns the maximum between one of the sides and the crossing sum
return max(maxBetweenLeftRight, crossing);
}
//divide and conquere algorithm with complexity O(nlogn)
//only made to make it more understandable from the main
//can call maxSubarraySum and it would be the same
int divideconquer (int array[], int l, int h){
return maxSubarraySum(array, l, h);
}
//dynamic programming algorithm with complexity O(n)
int dynprog(int array[], int n){
int a = array[0];
int b = array[0];
//for all the elements checks if the sum was better until the
//step before or adding the element
for (int i = 1 ; i < n; i++){
a= max (a+ array[i], array[i]);
b= max(b, a);
}
return b;
}
}
Changing all the ints to longs didn't help either.
I've copied your code, changed all ints to longs and it's working fine. Also changed n = Integer.parseInt(args[0]) instead of n = Integer.parseInt(args[1]).
Then I called my program like program_name 1000 random.
I've checked in excel, and only bruteforce was wrong. I've changed Integer.MIN_VALUE to Long.MIN_VALUE. And int sum to long sum.
Main.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class Main {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
long[] maxsubarray1;
maxsubarray1 = new Generator(n, args[1]).getArray();
long[] maxsubarray2 = Arrays.copyOf(maxsubarray1, maxsubarray1.length);
long[] maxsubarray3 = Arrays.copyOf(maxsubarray1, maxsubarray1.length);
System.out.println(Arrays.toString(maxsubarray1));
solver solver = new solver();
long solution;
//if (args[5].equalsIgnoreCase("bruteforce")){
long startTime = System.currentTimeMillis();
solution = solver.bruteforce(maxsubarray1, n);
System.out.println("__________BRUTE FORCE________\nThe sum of the array is " + solution);
long endTime = System.currentTimeMillis() - startTime;
System.out.println(endTime);
//}
//if (args[5].equalsIgnoreCase("divideconquer")){
long startTime2 = System.currentTimeMillis();
long solutiondivideconquer = solver.divideconquer(maxsubarray2, 0, n);
System.out.println("__________DIVIDE AND CONQUERE________\nThe sum of the array is " + solutiondivideconquer);
long endTime2 = System.currentTimeMillis() - startTime2;
System.out.println(endTime2);
//}
//if (args[5].equalsIgnoreCase("dynprog")){
long startTime3 = System.currentTimeMillis();
long solutiondynprog = solver.dynprog(maxsubarray3, n);
System.out.println("__________DYNAMIC PROGRAMMING________\nThe sum of the array is " + solutiondynprog);
long endTime3 = System.currentTimeMillis() - startTime3;
System.out.println(endTime3);
//}
}
}
solver.java
public class solver {
//brute force algorithm with complexity O(n^2)
long bruteforce(long array[], int n){
long max = Long.MIN_VALUE;
//We go throght all the elements of the list and we try all the
//posible combinations with all the other elements
for (int i = 0; i < n; i++){
long sum = 0;
for (int j = i; j < n ; j++){
//we add the an element in the sum
sum += array[j];
//we check if the sum with the new element is greater that the value we had before
if(sum > max){
//if it's greater, it becomes the new value
max = sum;
}
}
}
//we return the maximum value we have found
return max;
}
//to implement the divide and conquer algorithm we have to take into account the
// maximum subarray can have elements in the right subarray and in the left subarray
long maxCrossingSum(long array[], long l, long m, long h){
long sum = 0;
long left_sum = Integer.MIN_VALUE;
//Has the elements on the left part of the arrray
for ( int i = (int)m; i >= l; i--){
sum = sum + array[i];
if( sum > left_sum ){
left_sum = sum;
}
}
sum = 0;
long right_sum = 0;
//Has the elements in the right part of the array
for ( int j = (int)m+1; j <= h; j++){
sum = sum + array [j];
if (sum > right_sum){
right_sum = sum;
}
}
//returns the sun of the elements on the left and the right of the array
return left_sum + right_sum;
}
//returns the sum of the maximum subarray
long maxSubarraySum(long array[], long l, long h){
if(l == h)
return array[1];
long m = (l + h)/2;
//checks which is the maximum between left and right
long maxBetweenLeftRight = max(maxSubarraySum(array, l, m), maxSubarraySum(array, m+1,h));
long crossing = maxCrossingSum(array, l, m,h-1);
//retrns the maximum between one of the sides and the crossing sum
return max(maxBetweenLeftRight, crossing);
}
//divide and conquere algorithm with complexity O(nlogn)
//only made to make it more understandable from the main
//can call maxSubarraySum and it would be the same
long divideconquer (long array[], int l, int h){
return maxSubarraySum(array, l, h);
}
//dynamic programming algorithm with complexity O(n)
long dynprog(long array[], int n){
long a = array[0];
long b = array[0];
//for all the elements checks if the sum was better until the
//step before or adding the element
for (int i = 1 ; i < n; i++){
a= max (a+ array[i], array[i]);
b= max(b, a);
}
return b;
}
private long max(long a, long b) {
if (a > b ) return a;
else return b;
}
}
Generator.java
import java.util.concurrent.ThreadLocalRandom;
public class Generator {
int size;
String type;
long[] generatedArray;
public Generator(int mysize, String mytype) {
size = mysize;
type = mytype;
generatedArray = new long[size];
}
public void ascending() {
for (int i = 0; i < this.size; i++)
generatedArray[i] = i + 1;
}
public void descending() {
for (int i = this.size - 1; i >= 0; i--)
generatedArray[i] = i + 1;
}
public void random() {
for (int i = 0; i <= this.size - 1; i++)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10 * this.size, 10 * this.size);
}
public void randominter() {
for (int i = 0; i <= this.size - 1; i++)
if (i % 2 == 0)
generatedArray[i] = ThreadLocalRandom.current().nextInt(1, 10 * this.size);
else if (i % 2 == 1)
generatedArray[i] = ThreadLocalRandom.current().nextInt(-10 * this.size, -1);
}
public long[] getArray() {
if (type.equalsIgnoreCase("descending")) {
this.descending();
return generatedArray;
}
if (type.equalsIgnoreCase("ascending")) {
this.ascending();
return generatedArray;
}
if (type.equalsIgnoreCase("random")) {
this.random();
return generatedArray;
}
if (type.equalsIgnoreCase("randominter")) {
this.randominter();
return generatedArray;
}
return null;
}
}
I was wrong, it CAN BE an overflow error if Array[i] = i + 1, since the sum is length * (min + max) / 2 > Integer.MAX_VALUE

java codility Frog-River-One

I have been trying to solve a Java exercise on a Codility web page.
Below is the link to the mentioned exercise and my solution.
https://codility.com/demo/results/demoH5GMV3-PV8
Can anyone tell what can I correct in my code in order to improve the score?
Just in case here is the task description:
A small frog wants to get to the other side of a river. The frog is currently located at position 0, and wants to get to position X. Leaves fall from a tree onto the surface of the river.
You are given a non-empty zero-indexed array A consisting of N integers representing the falling leaves. A[K] represents the position where one leaf falls at time K, measured in minutes.
The goal is to find the earliest time when the frog can jump to the other side of the river. The frog can cross only when leaves appear at every position across the river from 1 to X.
For example, you are given integer X = 5 and array A such that:
A[0] = 1
A[1] = 3
A[2] = 1
A[3] = 4
A[4] = 2
A[5] = 3
A[6] = 5
A[7] = 4
In minute 6, a leaf falls into position 5. This is the earliest time when leaves appear in every position across the river.
Write a function:
class Solution { public int solution(int X, int[] A); }
that, given a non-empty zero-indexed array A consisting of N integers and integer X, returns the earliest time when the frog can jump to the other side of the river.
If the frog is never able to jump to the other side of the river, the function should return −1.
For example, given X = 5 and array A such that:
A[0] = 1
A[1] = 3
A[2] = 1
A[3] = 4
A[4] = 2
A[5] = 3
A[6] = 5
A[7] = 4
the function should return 6, as explained above. Assume that:
N and X are integers within the range [1..100,000];
each element of array A is an integer within the range [1..X].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(X), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
And here is my solution:
import java.util.ArrayList;
import java.util.List;
class Solution {
public int solution(int X, int[] A) {
int list[] = A;
int sum = 0;
int searchedValue = X;
List<Integer> arrayList = new ArrayList<Integer>();
for (int iii = 0; iii < list.length; iii++) {
if (list[iii] <= searchedValue && !arrayList.contains(list[iii])) {
sum += list[iii];
arrayList.add(list[iii]);
}
if (list[iii] == searchedValue) {
if (sum == searchedValue * (searchedValue + 1) / 2) {
return iii;
}
}
}
return -1;
}
}
You are using arrayList.contains inside a loop, which will traverse the whole list unnecessarily.
Here is my solution (I wrote it some time ago, but I believe it scores 100/100):
public int frog(int X, int[] A) {
int steps = X;
boolean[] bitmap = new boolean[steps+1];
for(int i = 0; i < A.length; i++){
if(!bitmap[A[i]]){
bitmap[A[i]] = true;
steps--;
if(steps == 0) return i;
}
}
return -1;
}
Here is my solution. It got me 100/100:
public int solution(int X, int[] A)
{
int[] B = A.Distinct().ToArray();
return (B.Length != X) ? -1 : Array.IndexOf<int>(A, B[B.Length - 1]);
}
100/100
public static int solution (int X, int[] A){
int[]counter = new int[X+1];
int ans = -1;
int x = 0;
for (int i=0; i<A.length; i++){
if (counter[A[i]] == 0){
counter[A[i]] = A[i];
x += 1;
if (x == X){
return i;
}
}
}
return ans;
}
A Java solution using Sets (Collections Framework) Got a 100%
import java.util.Set;
import java.util.TreeSet;
public class Froggy {
public static int solution(int X, int[] A){
int steps=-1;
Set<Integer> values = new TreeSet<Integer>();
for(int i=0; i<A.length;i++){
if(A[i]<=X){
values.add(A[i]);
}
if(values.size()==X){
steps=i;
break;
}
}
return steps;
}
Better approach would be to use Set, because it only adds unique values to the list. Just add values to the Set and decrement X every time a new value is added, (Set#add() returns true if value is added, false otherwise);
have a look,
public static int solution(int X, int[] A) {
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < A.length; i++) {
if (values.add(A[i])) X--;
if (X == 0) return i;
}
return -1;
}
do not forget to import,
import java.util.HashSet;
import java.util.Set;
Here's my solution, scored 100/100:
import java.util.HashSet;
class Solution {
public int solution(int X, int[] A) {
HashSet<Integer> hset = new HashSet<Integer>();
for (int i = 0 ; i < A.length; i++) {
if (A[i] <= X)
hset.add(A[i]);
if (hset.size() == X)
return i;
}
return -1;
}
}
Simple solution 100%
public int solution(final int X, final int[] A) {
Set<Integer> emptyPosition = new HashSet<Integer>();
for (int i = 1; i <= X; i++) {
emptyPosition.add(i);
}
// Once all the numbers are covered for position, that would be the
// moment when the frog will jump
for (int i = 0; i < A.length; i++) {
emptyPosition.remove(A[i]);
if (emptyPosition.size() == 0) {
return i;
}
}
return -1;
}
Here's my solution.
It isn't perfect, but it's good enough to score 100/100.
(I think that it shouldn't have passed a test with a big A and small X)
Anyway, it fills a new counter array with each leaf that falls
counter has the size of X because I don't care for leafs that fall farther than X, therefore the try-catch block.
AFTER X leafs fell (because it's the minimum amount of leafs) I begin checking whether I have a complete way - I'm checking that every int in count is greater than 0.
If so, I return i, else I break and try again.
public static int solution(int X, int[] A){
int[] count = new int[X];
for (int i = 0; i < A.length; i++){
try{
count[A[i]-1]++;
} catch (ArrayIndexOutOfBoundsException e){ }
if (i >= X - 1){
for (int j = 0; j< count.length; j++){
if (count[j] == 0){
break;
}
if (j == count.length - 1){
return i;
}
}
}
}
return -1;
}
Here's my solution with 100 / 100.
public int solution(int X, int[] A) {
int len = A.length;
if (X > len) {
return -1;
}
int[] isFilled = new int[X];
int jumped = 0;
Arrays.fill(isFilled, 0);
for (int i = 0; i < len; i++) {
int x = A[i];
if (x <= X) {
if (isFilled[x - 1] == 0) {
isFilled[x - 1] = 1;
jumped += 1;
if (jumped == X) {
return i;
}
}
}
}
return -1;
}
Here's what I have in C#. It can probably still be refactored.
We throw away numbers greater than X, which is where we want to stop, and then we add numbers to an array if they haven't already been added.
When the count of the list has reached the expected number, X, then return the result. 100%
var tempArray = new int[X+1];
var totalNumbers = 0;
for (int i = 0; i < A.Length; i++)
{
if (A[i] > X || tempArray.ElementAt(A[i]) != 0)
continue;
tempArray[A[i]] = A[i];
totalNumbers++;
if (totalNumbers == X)
return i;
}
return -1;
below is my solution. I basically created a set which allows uniques only and then go through the array and add every element to set and keep a counter to get the sum of the set and then using the sum formula of consecutive numbers then I got 100% . Note : if you add up the set using java 8 stream api the solution is becoming quadratic and you get %56 .
public static int solution2(int X, int[] A) {
long sum = X * (X + 1) / 2;
Set<Integer> set = new HashSet<Integer>();
int setSum = 0;
for (int i = 0; i < A.length; i++) {
if (set.add(A[i]))
setSum += A[i];
if (setSum == sum) {
return i;
}
}
return -1;
}
My JavaScript solution that got 100 across the board. Since the numbers are assumed to be in the range of the river width, simply storing booleans in a temporary array that can be checked against duplicates will do. Then, once you have amassed as many numbers as the quantity X, you know you have all the leaves necessary to cross.
function solution(X, A) {
covered = 0;
tempArray = [];
for (let i = 0; i < A.length; i++) {
if (!tempArray[A[i]]) {
tempArray[A[i]] = true;
covered++
if(covered === X) return i;
}
}
return -1;
}
Here is my answer in Python:
def solution(X, A):
# write your code in Python 3.6
values = set()
for i in range (len(A)):
if A[i]<=X :
values.add(A[i])
if len(values)==X:
return i
return -1
Just tried this problem as well and here is my solution. Basically, I just declared an array whose size is equal to position X. Then, I declared a counter to monitor if the necessary leaves have fallen at the particular spots. The loop exits when these leaves have been met and if not, returns -1 as instructed.
class Solution {
public int solution(int X, int[] A) {
int size = A.length;
int[] check = new int[X];
int cmp = 0;
int time = -1;
for (int x = 0; x < size; x++) {
int temp = A[x];
if (temp <= X) {
if (check[temp-1] > 0) {
continue;
}
check[temp - 1]++;
cmp++;
}
if ( cmp == X) {
time = x;
break;
}
}
return time;
}
}
It got a 100/100 on the evaluation but I'm not too sure of its performance. I am still a beginner when it comes to programming so if anybody can critique the code, I would be grateful.
Maybe it is not perfect but its straightforward. Just made a counter Array to track the needed "leaves" and verified on each iteration if the path was complete. Got me 100/100 and O(N).
public static int frogRiver(int X, int[] A)
{
int leaves = A.Length;
int[] counter = new int[X + 1];
int stepsAvailForTravel = 0;
for(int i = 0; i < leaves; i++)
{
//we won't get to that leaf anyway so we shouldnt count it,
if (A[i] > X)
{
continue;
}
else
{
//first hit!, keep a count of the available leaves to jump
if (counter[A[i]] == 0)
stepsAvailForTravel++;
counter[A[i]]++;
}
//We did it!!
if (stepsAvailForTravel == X)
{
return i;
}
}
return -1;
}
This is my solution. I think it's very simple. It gets 100/100 on codibility.
set.contains() let me eliminate duplicate position from table.
The result of first loop get us expected sum. In the second loop we get sum of input values.
class Solution {
public int solution(int X, int[] A) {
Set<Integer> set = new HashSet<Integer>();
int sum1 = 0, sum2 = 0;
for (int i = 0; i <= X; i++){
sum1 += i;
}
for (int i = 0; i < A.length; i++){
if (set.contains(A[i])) continue;
set.add(A[i]);
sum2 += A[i];
if (sum1 == sum2) return i;
}
return -1;
}
}
Your algorithm is perfect except below code
Your code returns value only if list[iii] matches with searchedValue.
The algorithm must be corrected in such a way that, it returns the value if sum == n * ( n + 1) / 2.
import java.util.ArrayList;
import java.util.List;
class Solution {
public int solution(int X, int[] A) {
int list[] = A;
int sum = 0;
int searchedValue = X;
int sumV = searchedValue * (searchedValue + 1) / 2;
List<Integer> arrayList = new ArrayList<Integer>();
for (int iii = 0; iii < list.length; iii++) {
if (list[iii] <= searchedValue && !arrayList.contains(list[iii])) {
sum += list[iii];
if (sum == sumV) {
return iii;
}
arrayList.add(list[iii]);
}
}
return -1;
}
}
I think you need to check the performance as well. I just ensured the output only
This solution I've posted today gave 100% on codility, but respectivly #rafalio 's answer it requires K times less memory
public class Solution {
private static final int ARRAY_SIZE_LOWER = 1;
private static final int ARRAY_SIZE_UPPER = 100000;
private static final int NUMBER_LOWER = ARRAY_SIZE_LOWER;
private static final int NUMBER_UPPER = ARRAY_SIZE_UPPER;
public static class Set {
final long[] buckets;
public Set(int size) {
this.buckets = new long[(size % 64 == 0 ? (size/64) : (size/64) + 1)];
}
/**
* number should be greater than zero
* #param number
*/
public void put(int number) {
buckets[getBucketindex(number)] |= getFlag(number);
}
public boolean contains(int number) {
long flag = getFlag(number);
// check if flag is stored
return (buckets[getBucketindex(number)] & flag) == flag;
}
private int getBucketindex(int number) {
if (number <= 64) {
return 0;
} else if (number <= 128) {
return 1;
} else if (number <= 192) {
return 2;
} else if (number <= 256) {
return 3;
} else if (number <= 320) {
return 4;
} else if (number <= 384) {
return 5;
} else
return (number % 64 == 0 ? (number/64) : (number/64) + 1) - 1;
}
private long getFlag(int number) {
if (number <= 64) {
return 1L << number;
} else
return 1L << (number % 64);
}
}
public static final int solution(final int X, final int[] A) {
if (A.length < ARRAY_SIZE_LOWER || A.length > ARRAY_SIZE_UPPER) {
throw new RuntimeException("Array size out of bounds");
}
Set set = new Set(X);
int ai;
int counter = X;
final int NUMBER_REAL_UPPER = min(NUMBER_UPPER, X);
for (int i = 0 ; i < A.length; i++) {
if ((ai = A[i]) < NUMBER_LOWER || ai > NUMBER_REAL_UPPER) {
throw new RuntimeException("Number out of bounds");
} else if (ai <= X && !set.contains(ai)) {
counter--;
if (counter == 0) {
return i;
}
set.put(ai);
}
}
return -1;
}
private static int min(int x, int y) {
return (x < y ? x : y);
}
}
This is my solution it got me 100/100 and O(N).
public int solution(int X, int[] A) {
Map<Integer, Integer> leaves = new HashMap<>();
for (int i = A.length - 1; i >= 0 ; i--)
{
leaves.put(A[i] - 1, i);
}
return leaves.size() != X ? -1 : Collections.max(leaves.values());
}
This is my solution
public func FrogRiverOne(_ X : Int, _ A : inout [Int]) -> Int {
var B = [Int](repeating: 0, count: X+1)
for i in 0..<A.count {
if B[A[i]] == 0 {
B[A[i]] = i+1
}
}
var time = 0
for i in 1...X {
if( B[i] == 0 ) {
return -1
} else {
time = max(time, B[i])
}
}
return time-1
}
A = [1,2,1,4,2,3,5,4]
print("FrogRiverOne: ", FrogRiverOne(5, &A))
Actually I re-wrote this exercise without seeing my last answer and came up with another solution 100/100 and O(N).
public int solution(int X, int[] A) {
Set<Integer> leaves = new HashSet<>();
for(int i=0; i < A.length; i++) {
leaves.add(A[i]);
if (leaves.contains(X) && leaves.size() == X) return i;
}
return -1;
}
I like this one better because it is even simpler.
This one works good on codality 100% out of 100%. It's very similar to the marker array above but uses a map:
public int solution(int X, int[] A) {
int index = -1;
Map<Integer, Integer> map = new HashMap();
for (int i = 0; i < A.length; i++) {
if (!map.containsKey(A[i])) {
map.put(A[i], A[i]);
X--;
if (X == 0) {index = i;break;}
}
}
return index;
}
%100 with js
function solution(X, A) {
let leafSet = new Set();
for (let i = 0; i < A.length; i += 1) {
if(A[i] <= 0)
continue;
if (A[i] <= X )
leafSet.add(A[i]);
if (leafSet.size == X)
return i;
}
return -1;
}
With JavaScript following solution got 100/100.
Detected time complexity: O(N)
function solution(X, A) {
let leaves = new Set();
for (let i = 0; i < A.length; i++) {
if (A[i] <= X) {
leaves.add(A[i])
if (leaves.size == X) {
return i;
}
}
}
return -1;
}
100% Solution using Javascript.
function solution(X, A) {
if (A.length === 0) return -1
if (A.length < X) return -1
let steps = X
const leaves = {}
for (let i = 0; i < A.length; i++) {
if (!leaves[A[i]]) {
leaves[A[i]] = true
steps--
}
if (steps === 0) {
return i
}
}
return -1
}
C# Solution with 100% score:
using System;
using System.Collections.Generic;
class Solution {
public int solution(int X, int[] A) {
// go through the array
// fill a hashset, until the size of hashset is X
var set = new HashSet<int>();
int i = 0;
foreach (var a in A)
{
if (a <= X)
{
set.Add(a);
}
if (set.Count == X)
{
return i;
}
i++;
}
return -1;
}
}
https://app.codility.com/demo/results/trainingXE7QFJ-TZ7/
I have a very simple solution (100% / 100%) using HashSet. Lots of people check unnecessarily whether the Value is less than or equal to X. This task cannot be otherwise.
public static int solution(int X, int[] A) {
Set<Integer> availableFields = new HashSet<>();
for (int i = 0; i < A.length; i++) {
availableFields.add(A[i]);
if (availableFields.size() == X){
return i;
}
}
return -1;
}
public static int solutions(int X, int[] A) {
Set<Integer> values = new HashSet<Integer>();
for (int i = 0; i < A.length; i++) {
if (values.add(A[i])) {
X--;
}
if (X == 0) {
return i;
}
}
return -1;
}
This is my solution. It uses 3 loops but is constant time and gets 100/100 on codibility.
class FrogLeap
{
internal int solution(int X, int[] A)
{
int result = -1;
long max = -1;
var B = new int[X + 1];
//initialize all entries in B array with -1
for (int i = 0; i <= X; i++)
{
B[i] = -1;
}
//Go through A and update B with the location where that value appeared
for (int i = 0; i < A.Length; i++)
{
if( B[A[i]] ==-1)//only update if still -1
B[A[i]] = i;
}
//start from 1 because 0 is not valid
for (int i = 1; i <= X; i++)
{
if (B[i] == -1)
return -1;
//The maxValue here is the earliest time we can jump over
if (max < B[i])
max = B[i];
}
result = (int)max;
return result;
}
}
Short and sweet C++ code. Gets perfect 100%... Drum roll ...
#include <set>
int solution(int X, vector<int> &A) {
set<int> final;
for(unsigned int i =0; i< A.size(); i++){
final.insert(A[i]);
if(final.size() == X) return i;
}
return -1;
}

Categories

Resources