calculate the average value across indicies of a hash map - java

I tried writing this code to test out my idea on how to calculate the average value across like indices of a hash map.
i.e. for each array contained within the hashmap if the first value for the first array was 2, and the first value for the second array was 4 , and the first value for the third array was 3, I want to assign the value of (4+3+2/3)= 3 to the final double[] array for the first index, and so on for all the indices 2 through n.
int Size = 3;
double[] AVERAGED_WEIGHTS = new double[Size];
//store weights to be averaged.
Map<Integer,double[]> cached_weights = new HashMap<Integer,double[]>();
double[] weights = new double[Size];
int iteration = 0;
do
{
weights[iteration] = Math.floor(Math.random() * 10000) / 10000;
iteration++;
//store weights for averaging
cached_weights.put( iteration , weights );
}
while (iteration < Size);
//calc averages
for (Entry<Integer, double[]> entry : cached_weights.entrySet())
{
int key = entry.getKey();
double[] value = entry.getValue();
AVERAGED_WEIGHTS[ key - 1 ] += value[ key - 1 ];
if (key == iteration)
{
AVERAGED_WEIGHTS[ key - 1 ] /= key;
}
}
for(int i = 0; i < weights.length; i++)
{
weights[i] = AVERAGED_WEIGHTS[i];
}
This mimics the structure of the original program wherein the weights are populated through a do while loop. This code is broken though and does not sucessfully perform the operation described above. I've been searching online and trying different ways to fix it but I've not been able to solve it. Perhaps someone can spot my faulty logic.

Maybe I misunderstood you, but you are not computing the average because for each array in your map, you are not taking into account all its positions. You are using the key and that makes absolutely no sense. Anyways, your code is very confusing. What you need to do is simply one loop inside the other. One going through the arrays and another going through the elements of each array. A way to compute the average is the following (in a didactic way):
//compute averages
double[] sums = new double[size];
double[] averages = new double[size];
for (Entry<Integer, double[]> entry : cachedWeights.entrySet()) {
double[] value = entry.getValue();
for(int pos=0; pos < Math.min(size, value.length); pos++){
sums[pos] += value[pos];
}
}
for(int pos=0; pos < size; pos++){
averages[pos] = sums[pos] / cachedWeights.size();
}

Related

Program throws a ArrayIndexOutOfBoundsException when using Bucket Sort on an array that's sorted backwards

I need to run an array that's sorted backwards (I.E. 100, 99, 98, 97 . . . . 3, 2, 1, 0, highest to lowest) through a bucket sort that will sort it lowest to highest. The code that generates the array looks like this:
int n = 100;//Decides how large the arrays fed to the sorts are, minimum value of 100
int k = n - 1;
int howMany = 10;//Decides how many times the sorts are timed whenever the program is run
int[] baseArray = new int[n];
//Loops entire thing as many times as howMany dictates, will refer to it as PRIME LOOP
for (int m = 0; m < howMany; m++) {
for (int i = 0; i < n; i++) //Generates array that's sorted backwards
{
baseArray[i] = k;
k--;
}
int[] bucketArray = new int[n];
for (int i = 0; i < n; i++) {
bucketArray[i] = baseArray[i];
}
bucketSort(bucketArray); //Sends the array to bucket sort (This is line 218)**************
}
Here's the actual bucket sort:
//Bucket Sort
public static void bucketSort(int[] input) {
// get hash codes
final int[] code = hash(input);
// create and initialize buckets to ArrayList: O(n)
List<Integer>[] buckets = new List[code[1]];
for (int i = 0; i < code[1]; i++) {
buckets[i] = new ArrayList();
}
// distribute data into buckets: O(n)
for (int i : input) {
buckets[hash(i, code)].add(i); //This is line 349*******************************************
}
// sort each bucket O(n)
for (List bucket : buckets) {
Collections.sort(bucket);
}
int ndx = 0;
// merge the buckets: O(n)
for (int b = 0; b < buckets.length; b++) {
for (int v : buckets[b]) {
input[ndx++] = v;
}
}
}
private static int[] hash(int[] input) {
int m = input[0];
for (int i = 1; i < input.length; i++) {
if (m < input[i]) {
m = input[i];
}
}
return new int[] { m, (int) Math.sqrt(input.length) };
}
private static int hash(int i, int[] code) {
return (int) ((double) i / code[0] * (code[1] - 1));
}
The first time the code goes through the for-loop (prime loop) bucket sort spits out the array with it properly sorted lowest to highest. However, without fail the second time it goes through the prime loop it gives me an ArrayIndexOutOfBoundsException, specifically,
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 18 out of bounds for length 10
at SeniorResearch.Final_Project_Driver.bucketSort(Final_Project_Driver.java:349)
at SeniorResearch.Final_Project_Driver.main(Final_Project_Driver.java:218)
(I marked out the mentioned lines above)
Can anyone help me figure out why this is happening? What's changing from PRIME LOOP 1 to PRIME LOOP 2 that's causing an ArrayIndexOutOfBoundsException in the bucket sort and how do I fix it?
In your bucketSort method at you think you are using final int[] code = hash(input); to calculate the number of buckets, but in reality, you are calculating the hash of your array.
So what you have to do is calculate the number of different hash codes for your array elements.
Use the method which calculates the hash of a single integer, then count how many different hashes you've got, then add each integer into the "hash-bucket", and so on...

Algorithm to calculate maximum points by deleting a number

I am going through this leetcode algorithm, I am trying to understand it by reading the explanation many times since 2 days, but I am not able to get the concept how the program is solved.
This is the problem statement:
Given an array nums of integers, you can perform operations on the
array.
In each operation, you pick any nums[i] and delete it to earn nums[i]
points. After, you must delete every element equal to nums[i] - 1 or
nums[i] + 1.
You start with 0 points. Return the maximum number of points you can
earn by applying such operations.
Example 1: Input: nums = [3, 4, 2] Output: 6 Explanation: Delete 4 to
earn 4 points, consequently 3 is also deleted. Then, delete 2 to earn
2 points. 6 total points are earned.
Here is the explanation for on how it is solved:
Algorithm
For each unique value k of nums in increasing order, let's maintain
the correct values of avoid and using, which represent the answer if
we don't take or take k respectively.
If the new value k is adjacent to the previously largest value prev,
then the answer if we must take k is (the point value of k) + avoid,
while the answer if we must not take k is max(avoid, using).
Similarly, if k is not adjacent to prev, the answer if we must take k
is (the point value of k) + max(avoid, using), and the answer if we
must not take k is max(avoid, using).
At the end, the best answer may or may not use the largest value in
nums, so we return max(avoid, using).
and the corresponding Java program:
public int deleteAndEarn(int[] nums) {
int[] count = new int[10001];
for (int x: nums) count[x]++;
int avoid = 0, using = 0, prev = -1;
for (int k = 0; k <= 10000; ++k) if (count[k] > 0) {
int m = Math.max(avoid, using);
if (k - 1 != prev) {
using = k * count[k] + m;
avoid = m;
} else {
using = k * count[k] + avoid;
avoid = m;
}
prev = k;
}
return Math.max(avoid, using);
}
I am not able to understand how avoid and using variables are used here and how it is solving the problem statement.
Can you please help me in understanding this.
I went through the problem on that page.
The algorithm is based on a very nice trick. It is very easy to solve this problem when you process the input first before applying the algorithm.
The input is reorganized into buckets.
Lets say you have the input : 1 1 2 3 3 2 2 4 4 4
You can reorganize it into
(Two 1s), (Three 2s), ( Two 3s), (Three 4s)
Now according to the problem, if you pick any bucket you should give up the bucket containing ( bucket-element-value - 1 ) and ( bucket-element-value + 1 ), which are actually adjacent ones to this bucket.
The problem now boils down to how would you pick buckets to get maximum sum given that constraint that you cannot get the adjacent bucket values ?
It is simple - As you go through the buckets, you have two things that you can do with a bucket. Either avoid it or use it.
If you avoid it, what is the maximum amount you can achieve - it depends on what you did with the previous one.
amountWhenAvoided[i] = Math.max( amountWhenAvoided[i-1], amountWhenTaken[i-1] );
If you use it, what is the maximum amount you can achieve? You get that bucket's value + whatever you got when you left/avoided the previous bucket.
amountWhenTaken[i] = amountWhenAvoided[i-1] + valueOfBucket[i]
Once you reach end of buckets the answer will be :
Math.max( amountWhenTaken[n], amountWhenAvoided[n] )
You could code this like:
public int deleteAndEarn( int[] nums ) {
//reorganize.
int[] valueOfBucket= new int[10001] //This is the maximum size of the buckets.
for ( int num : nums ) {
valueOfBucket[num] += num; //Populate each bucket.
}
//Now go through each bucket - remember - a bucket could be empty that's fine.
int[] amountWhenTaken = new int[n];
int[] amountWhenAvoided = new int[n];
amountWhenTaken[0] = 0; //Because there are no buckets to start with - buckets start from 1
amountWhenAvoided[0] = 0;
for ( int i = 1; i <= n; i++ ) {
amountWhenAvoided[i] = Math.max( amountWhenAvoided[i-1], amountWhenTaken[i-1] );
amountWhenTaken[i] = amountWhenAvoided[i-1] + valueOfBucket[i];
}
return Math.max( amountWhenTaken[n], amountWhenAvoided[n] );
}
If you observe the code above, it is really not needed to do it with arrays. Because the current element in the array depends on its previous element, so we can do it with just two variables lets call them avoiding, using
Then the second for loop can be written as:
public int deleteAndEarn( int[] nums ) {
//reorganize.
int[] valueOfBucket= new int[10001] //This is the maximum size of the buckets.
for ( int num : nums ) {
valueOfBucket[num] += num; //Populate each bucket.
}
//Now go through each bucket - remember - a bucket could be empty that's fine.
int using_prev = 0;
int avoiding_prev = 0;
int avoiding_curr = 0;
int using_curr = 0;
for ( int i = 1; i <= n; i++ ) {
avoiding_curr = Math.max( avoiding_prev, using_prev);
using_curr = avoiding_prev + valueOfBucket[i];
avoiding_prev = avoiding_curr;
using_prev = using_curr;
}
return Math.max( avoiding_curr, using_curr );
}

Two sum - Doesn't work

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Consider input [3,2,4] and target is 6. I added (3,0) and (2,1) to the map and when I come to 4 and calculate value as 6 - 4 as 2 and when I check if 2 is a key present in map or not, it does not go in if loop.
I should get output as [1,2] which are the indices for 2 and 4 respectively
public int[] twoSum(int[] nums, int target) {
int len = nums.length;
int[] arr = new int[2];
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i = 0;i < len; i++)
{
int value = nums[i] - target;
if(map.containsKey(value))
{
System.out.println("Hello");
arr[0] = value;
arr[1] = map.get(value);
return arr;
}
else
{
map.put(nums[i],i);
}
}
return null;
}
I don't get where the problem is, please help me out
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice. Consider input [3,2,4] and target is 6. I added (3,0) and (2,1) to the map and when I come to 4 and calculate value as 6 - 4 as 2 and when I check if 2 is a key present in map or not, it does not go in if loop.
Okay, let's take a step back for a second.
You have a list of values, [3,2,4]. You need to know which two will add up 6, well, by looking at it we know that the answer should be [1,2] (values 2 and 4)
The question now is, how do you do that programmatically
The solution is (to be honest), very simple, you need two loops, this allows you to compare each element in the list with every other element in the list
for (int outter = 0; outter < values.length; outter++) {
int outterValue = values[outter];
for (int inner = 0; inner < values.length; inner++) {
if (inner != outter) { // Don't want to compare the same index
int innerValue = values[inner];
if (innerValue + outterValue == targetValue) {
// The outter and inner indices now form the answer
}
}
}
}
While not highly efficient (yes, it would be easy to optimise the inner loop, but given the OP's current attempt, I forewent it), this is VERY simple example of how you might achieve what is actually a very common problem
int value = nums[i] - target;
Your subtraction is backwards, as nums[i] is probably smaller than target. So value is getting set to a negative number. The following would be better:
int value = target - nums[i];
(Fixing this won't fix your whole program, but it explains why you're getting the behavior that you are.)
This code for twoSum might help you. For the inputs of integer array, it will return the indices of the array if the sum of the values = target.
public static int[] twoSum(int[] nums, int target) {
int[] indices = new int[2];
outerloop:
for(int i = 0; i < nums.length; i++){
for(int j = 0; j < nums.length; j++){
if((nums[i]+nums[j]) == target){
indices[0] = i;
indices[1] = j;
break outerloop;
}
}
}
return indices;
}
You can call the function using
int[] num = {1,2,3};
int[] out = twoSum(num,4);
System.out.println(out[0]);
System.out.println(out[1]);
Output:
0
2
You should update the way you compute for the value as follows:
int value = target - nums[i];
You can also check this video if you want to better visualize it. It includes Brute force and Linear approach:

How to create int array containing (quasi) random values in a given range but with a fixed % of duplicates?

I am trying to create (in Java) an integer array containing a specified number of integers, k, (for example, 50, 500, 1000, etc.) that does not use library functions or Collections, but contains a random assortment of numbers in the range (i.e. from 1 to k), with a specified percentage of duplicates.
I have figured out how to implement the shuffle, but I am not sure how to best implement the dups threshold. What I have so far:
static void shuffle(int[] array) {
int n = array.length;
for (int i = 0; i < array.length; i++) {
// Get a random index of the array past i.
int random = i + (int) (Math.random() * (n - i));
// Swap the random element with the present element.
int randomElement = array[random];
array[random] = array[i];
array[i] = randomElement;
}
}
Then, using this method:
//Create an ascending ordered array of size k to be shuffled
int [] tempInit = new int [filesizes[i]];
for(int k = 0; k < filesizes[i]; k++)
{
tempInit[k] = k+1;
}
//Shuffle the ascending array
shuffle(tempInit);
for(int k = 0; k < tempInit.length; k++)
{
System.out.println(tempInit[k]);
}
One way I imagine it could work would be to use the percentage of duplicates required (let's say it's 20%) and then randomly select a fixed number of integers, and loop through the array and replace every element (if not equal to one of the fixed numbers) with one of these fixed numbers. I'm not sure what sort of logic would make sense to select these fixed numbers, or the amount of fixed numbers to use for replacement purposes.
Try this! For 80% for number 1 and 5% for each other up to 5:
Map<Double, Integer> map = new LinkedHashMap<>();
map.put(0.8, 1);
map.put(0.85, 2);
map.put(0.9, 3);
map.put(0.95, 4);
map.put(1, 5);
Random random = new Random();
double result = random.nextDouble();
int value = map.entrySet().stream().filter(entry -> entry.getKey() < result).reduce(0, Math::min);
edit: solved this as follows:
double percentDupes= 0.2;
//Create an ascending ordered array of size k to be shuffled
int [] tempSorted = new int [filesizes[i]];
for(int k = 0; k < filesizes[i]; k++)
{
tempSorted[k] = k+1;
}
//Shuffle the ascending array
shuffleArray(tempSorted);
//Figure out the proportion of the array to replace with duplicate values of elements already in the array
Double proportion = tempSorted.length*percentDupes;
int ratio = proportion.intValue();
//Instantiate a new array of size "ratio"
int [] tempShuffled = new int[ratio];
//Fill the new, smaller array with randomly selected elements from the original, sorted array
for(int b = 0; b< tempShuffled.length; b++)
{
int randNum = i + (int) (Math.random() * (tempSorted.length - i)); //Select a random element of the array to have as a duplicate
tempShuffled[b] = tempSorted[randNum]; //tempSorted was previously shuffled
}
//Shuffle this sub-array
shuffleArray(tempShuffled);
//Loop through (shuffled) original array and, if the values don't match, replace a non-dup with a dup value
for(int c= 0; c<tempShuffled.length; c++ )
{
if(tempSorted[c] != tempShuffled[c])
{
tempSorted[c] = tempShuffled[c];
}
}
//Final output to print to file
for(int k = 0; k < tempSorted.length; k++)
{
System.out.println(tempSorted[k]);
}

Need help sorting an integer array through code

I've been working on code to sort integer in an array list, but my code is only returning only 2 numbers can anybody help me understand what I'm doing wrong here. How do I get all the numbers to be displayed? The numbers in my array
ArrayList testNumbers = new ArrayList();
testNumbers.add(48);
testNumbers.add(3);
testNumbers.add(23);
testNumbers.add(99);
[48,3,23,99]. Any help would be greatly appreciated.
public ArrayList<Integer> listSort(ArrayList<Integer> numbers) {
// create variable to store max number
int maxNumber = 0;
// creates an array that will store the sorted numbers
ArrayList<Integer> sortedIntArray = new ArrayList<Integer>();
// loops through each number in the numbers arraylist
for (int i = 0; i < numbers.size(); i++) {
if (numbers.get(i) > maxNumber) {
// set the number to the new max number
maxNumber = numbers.get(i);
// add current max number to sorted array
sortedIntArray.add(maxNumber);
// remove the max number from numbers array
numbers.remove(numbers.get(i));
}
}
return sortedIntArray;
}
//the sortedIntArray returns
[48,99]
Use java.util.Collections.sort(List<T> list). Or are you required to implement your own sorting algorithm?
If you take a careful look at your code, it doesn't do anything if the number you are currently looking at is not bigger than maxNumber.
It adds in 48 because 48 > 0. Then it discards 3 and 23 because they are less than 48. then it adds 99 because it is greater than 48.
I believe you want to archive a classical Selection Sort.
Maybe try good old wikipedia: http://en.wikipedia.org/wiki/Selection_sort
public ArrayList<Integer> listSort(ArrayList<Integer> numbers) {
// create variable to store max number
int maxNumber = 0;
// creates an array that will store the sorted numbers
ArrayList<Integer> sortedIntArray = new ArrayList<Integer>();
// loops through each number in the numbers arraylist
for (int i = numbers.size(); i > 0; i--) {
maxNumber = numbers.get(0);
for(int j = 0; j < numbers.size(); j++) {
if (numbers.get(j) > maxNumber) {
// set the number to the new max number
maxNumber = numbers.get(i);
}
}
// add current max number to sorted array
sortedIntArray.add(maxNumber);
// remove the max number from numbers array
numbers.remove(numbers.get(i));
// add current max number to sorted array
sortedIntArray.add(maxNumber);
}
return sortedIntArray;
}
Basically you're only adding numbers that are greater than the max number you've seen. You also need to account for numbers that are smaller, and store them appropriately.
You are only adding to sortedIntArray when the array element you're looking at is bigger than the biggest found so far. 48 gets added because you haven't found any so far. Then 99 gets added because it's larger than 48.
You need to pass through the array more than once. As it stands, what you're doing is finding every number larger than all the previous numbers in the array. If you're really just looking for a selection sort (not a great idea, it's pretty slow) you want:
int size = numbers.size();
for (int i = 0; i < size; i++)
{
int maxNumber = 0;
for (int j = 0; j < numbers.size(); j++)
{
if (numbers.get(j) > numbers.get(maxNumber))
maxNumber = j;
}
SortedIntArray.add(numbers.get(maxNumber));
numbers.remove(maxNumber);
}
This also returns your array from largest to smallest, which isn't necessarily what you want. Also, by removing from numbers, you're changing the array so it won't be available to you once you're done (unless you pass a clone). In general, you need to rethink your set-up.
you mixed several sorting strats
public ArrayList<Integer> listSort(ArrayList<Integer> numbers) {
// create variable to store max number
int maxNumber = 0;
// creates an array that will store the sorted numbers
ArrayList<Integer> sortedIntArray = new ArrayList<Integer>();
// loops through each number in the numbers arraylist
while (!numbers.isEmpty()) {
int i;
for(i=0;i<number.size();i++){//double loop to get the current max numbers
if (numbers.get(i) > maxNumber) {
// set the number to the new max number
maxNumber = numbers.get(i);
}
}
// add current max number to sorted array
sortedIntArray.add(maxNumber);
// remove the max number from numbers array
number.listIterator(i).remove();
maxNumber=0;//reset maxNumber
}
}
return sortedIntArray;
}
I'm guessing you are asking this for a homework assignment. If you aren't just use any managed languages built in sort method as it will be faster than anything you write.
You are removing entries as you process them.
This means the size is shrinking when you insert entries.
After you add two entries, you have removed two entries leaving two entries so the loop stops.
try this algorithm it works with classes.. you can plug a list of class' into it as well
package drawFramePackage;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Random;
public class QuicksortAlgorithm {
ArrayList<AffineTransform> affs;
ListIterator<AffineTransform> li;
Integer count, count2;
/**
* #param args
*/
public static void main(String[] args) {
new QuicksortAlgorithm();
}
public QuicksortAlgorithm(){
count = new Integer(0);
count2 = new Integer(1);
affs = new ArrayList<AffineTransform>();
for (int i = 0; i <= 128; i++){
affs.add(new AffineTransform(1, 0, 0, 1, new Random().nextInt(1024), 0));
}
affs = arrangeNumbers(affs);
printNumbers();
}
public ArrayList<AffineTransform> arrangeNumbers(ArrayList<AffineTransform> list){
while (list.size() > 1 && count != list.size() - 1){
if (list.get(count2).getTranslateX() > list.get(count).getTranslateX()){
list.add(count, list.get(count2));
list.remove(count2 + 1);
}
if (count2 == list.size() - 1){
count++;
count2 = count + 1;
}
else{
count2++;
}
}
return list;
}
public void printNumbers(){
li = affs.listIterator();
while (li.hasNext()){
System.out.println(li.next());
}
}
}

Categories

Resources