Mean, Median, and Mode - Newb - Java - java

We had a lab in Comsci I couldn't figure out. I did a lot of research on this site and others for help but they were over my head. What threw me off were the arrays. Anyway, thanks in advance. I already got my grade, just want to know how to do this :D
PS: I got mean, I just couldn't find the even numbered median and by mode I just gave up.
import java.util.Arrays;
import java.util.Random;
public class TextLab06st
{
public static void main(String args[])
{
System.out.println("\nTextLab06\n");
System.out.print("Enter the quantity of random numbers ===>> ");
int listSize = Expo.enterInt();
System.out.println();
Statistics intList = new Statistics(listSize);
intList.randomize();
intList.computeMean();
intList.computeMedian();
intList.computeMode();
intList.displayStats();
System.out.println();
}
}
class Statistics
{
private int list[]; // the actual array of integers
private int size; // user-entered number of integers in the array
private double mean;
private double median;
private int mode;
public Statistics(int s)
{
size = s;
list = new int[size];
mean = median = mode = 0;
}
public void randomize()
{
Random rand = new Random(12345);
for (int k = 0; k < size; k++)
list[k] = rand.nextInt(31) + 1; // range of 1..31
}
public void computeMean()
{
double total=0;
for (int f = 0; f < size; f++)
{
total = total + list[f];
}
mean = total / size;
}
public void computeMedian()
{
int total2 = 0;
Arrays.sort(list);
if (size / 2 == 1)
{
// total2 =
}
else
{
total2 = size / 2;
median = list[total2];
}
}
public void computeMode()
{
// precondition: The list array has exactly 1 mode.
}
public void displayStats()
{
System.out.println(Arrays.toString(list));
System.out.println();
System.out.println("Mean: " + mean);
System.out.println("Median: " + median);
System.out.println("Mode: " + mode);
}
}

Here are two implementations for your median() and mode() methods:
public void computeMedian() {
Arrays.sort(list);
if ( (list.size & 1) == 0 ) {
// even: take the average of the two middle elements
median = (list[(size/2)-1] + list[(size/2)]) / 2;
} else {
// odd: take the middle element
median = list[size/2];
}
}
public void computeMode() {
// precondition: The list array has exactly 1 mode.
Map<Integer, Integer> values = new HashMap<Integer, Integer>();
for (int i=0; i < list.size; ++i) {
if (values.get(list[i]) == null) {
values.put(list[i], 1);
} else {
values.put(list[i], values.get(list[i])+1);
}
}
int greatestTotal = 0;
// iterate over the Map and find element with greatest occurrence
Iterator it = values.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
if (pair.getValue() > greatestTotal) {
mode = pair.getKey();
greatestTotal = pair.getValue();
}
it.remove();
}
}

Related

Sort objects highest-lowest in Java with ArrayList?

Write a method to return the Toy that occurs in the list most frequent and another method to sort the toys by count.
This is my code
import java.util.ArrayList;
public class ToyStore {
private ArrayList<Toy> toyList;
public ToyStore() {
}
public void loadToys(String toys) {
toyList = new ArrayList<Toy>();
for (String item : toys.split(" ")) {
Toy t = getThatToy(item);
if (t == null) {
toyList.add(new Toy(item));
} else {
t.setCount(t.getCount() + 1);
}
}
}
public Toy getThatToy(String nm) {
for (Toy item : toyList) {
if (item.getName().equals(nm)) {
return item;
}
}
return null;
}
public String getMostFrequentToy() {
int position = 0;
int maximum = Integer.MIN_VALUE;
for (int i = toyList.size() - 1; i >= 0; i--) {
if (toyList.get(i).getCount() > maximum)
maximum = toyList.get(i).getCount();
position = i;
}
return toyList.get(position).getName();
}
public void sortToysByCount() {
ArrayList<Toy> t = new ArrayList<Toy>();
int count = 0;
int size = toyList.size();
for (int i = size; i > 0; i--) {
t.add(new Toy(getMostFrequentToy()));
t.get(count).setCount(getThatToy(getMostFrequentToy()).getCount());
toyList.remove(getThatToy(getMostFrequentToy()));
count++;
}
toyList = t;
}
public String toString() {
return toyList + "" + "\n" + "max == " + getMostFrequentToy();
}
}
Here is the method I care about
public void sortToysByCount() {
ArrayList<Toy> t = new ArrayList<Toy>();
int count = 0;
int size = toyList.size();
for (int i = size; i > 0; i--) {
t.add(new Toy(getMostFrequentToy()));
t.get(count).setCount(getThatToy(getMostFrequentToy()).getCount());
toyList.remove(getThatToy(getMostFrequentToy()));
count++;
}
toyList = t;
}
Here is my output
[sorry 4, bat 1, train 2, teddy 2, ball 2]
Here is what I want
[sorry 4, train 2, teddy 2, ball 2, bat 1];
What is wrong in my code? How do I do it?
The problem is in your getMostFrequentToy() method:
Replace
if (toyList.get(i).getCount() > maximum)
maximum = toyList.get(i).getCount();
position = i;
with
if (toyList.get(i).getCount() > maximum) {
maximum = toyList.get(i).getCount();
position = i;
}
because you want to get the position that corresponds to that maximum.
You have some in-efficiencies in your code. Every single time you call getMostFrequentToy(), you are iterating over the whole list, which may be fine as you are constantly removing objects, but you really don't need to make new Toy objects for those that already exist in the list.
So, this is "better", but still not sure you need to getThatToy when you should already know which one is the most frequent.
String frequent;
for (int i = size; i > 0; i--) {
frequent = getMostFrequentToy();
t.add(new Toy(frequent));
t.get(count).setCount(getThatToy(frequent).getCount());
toyList.remove(getThatToy(frequent));
count++;
}
Anyways, I think the instructions asked you to return the Toy object, not its name.
It's quite simple, just keep track of the max count.
public Toy getMostFrequentToy() {
Toy mostFrequent = null;
int maximum = Integer.MIN_VALUE;
for (Toy t : toyList) {
if (t.getCount() > maximum)
mostFrequent = t;
}
return t;
}
Now, the above code can become
public void sortToysByCount() {
ArrayList<Toy> t = new ArrayList<Toy>();
// int count = 0;
int size = toyList.size();
Toy frequent;
for (int i = size; i > 0; i--) {
frequent = getMostFrequentToy();
t.add(frequent);
// t.get(count).setCount(frequent.getCount()); // Not sure about this
toyList.remove(frequent);
// count++;
}
toyList.clear();
toyList.addAll(t);
}
Realistically, though, when you want to sort, you really should see how to create a Comparator for your Toy objects.

Simple prisoner's dilemma genetic algorithm

I have used an existing genetic algorithm from
here
and reworked it I but don't know what I'm doing wrong
This is the error that I get
Exception in thread "main" java.lang.NullPointerException at
simpleGa.Algorithm.crossover(Algorithm.java:69) at
simpleGa.Algorithm.evolvePopulation(Algorithm.java:34) at
simpleGa.GAprisonerdilemma.main(GAprisonerdilemma.java:41)
I can't figure out exactly where the mistake is. Read a lot about NullPointerException but couldn't figure it out
package simpleGa;
public class Population {
public static Individual[] individuals;
/*
* Constructors
*/
// Create a population
public Population(int populationSize, boolean initialise) {
individuals = new Individual[populationSize];
// Initialise population
if (initialise) {
// Loop and create individuals
for (int i = 0; i < size(); i++) {
Individual newIndividual = new Individual();
newIndividual.generateIndividual();
saveIndividual(i, newIndividual);
}
for(int i=0;i<size();i++)
{
if(i%2==1){Individual individual1=individuals[i-1];
Individual individual2=individuals[i];
if(individuals[i-1].getGene(i-1)==0 && individuals[i].getGene(i)==0){
individuals[i-1].fitness=individual1.fitness+1;
individuals[i].fitness=individual2.fitness+1;
}
if(individuals[i-1].getGene(i-1)==1 && individuals[i].getGene(i)==1){
individuals[i-1].fitness=individual1.fitness+2;
individuals[i].fitness=individual2.fitness+2;
}
if(individuals[i-1].getGene(i-1)==0 && individuals[i].getGene(i)==1){
individuals[i-1].fitness=individual1.fitness+3;
individuals[i].fitness=individual2.fitness+0;
}
if(individuals[i-1].getGene(i-1)==1 && individuals[i].getGene(i)==0){
individuals[i-1].fitness=individual1.fitness+0;
individuals[i].fitness=individual2.fitness+3;
}
}}}
}
/* Getters */
public Individual getIndividual(int index) {
return individuals[index];
}
public Individual getFittest() {
Individual fittest = individuals[0];
// Loop through individuals to find fittest
for (int i = 1; i < size(); i++) {
if (fittest.getFitness() <= getIndividual(i).getFitness()) {
fittest = getIndividual(i);
}
}
return fittest;
}
/* Public methods */
// Get population size
public int size() {
return individuals.length;
}
// Save individual
public void saveIndividual(int index, Individual indiv) {
individuals[index] = indiv;
}
}
package simpleGa;
public class Individual {
static int defaultGeneLength = 1000;
private long[] genes =new long [defaultGeneLength];
// Cache
public static int fitness = 0;
// Create a random individual
public void generateIndividual() {
for (int i = 0; i < size(); i++) {
long gene = Math.round(Math.random());
genes[i] = gene;
}
}
/* Getters and setters */
// Use this if you want to create individuals with different gene lengths
public static void setDefaultGeneLength(int length) {
defaultGeneLength = length;
}
public long getGene(int i) {
return genes[i];
}
public void setGene(int index, long value) {
genes[index] = value;
fitness = 0;
}
/* Public methods */
public int size() {
return genes.length;
}
public static int getFitness() {
return fitness;
}
public void setFitness(int i) {
fitness=i;
}
#Override
public String toString() {
String geneString = "";
for (int i = 0; i < size(); i++) {
geneString += getGene(i);
}
return geneString;
}
}
package simpleGa;
public class Algorithm {
/* GA parameters */
private static final double uniformRate = 0.5;
private static final double mutationRate = 0.015;
private static final int tournamentSize = 5;
private static final boolean elitism = true;
/* Public methods */
// Evolve a population
public static Population evolvePopulation(Population pop) {
Population newPopulation = new Population(pop.size(), false);
// Keep our best individual
if (elitism) {
newPopulation.saveIndividual(0, pop.getFittest());
}
// Crossover population
int elitismOffset;
if (elitism) {
elitismOffset = 1;
} else {
elitismOffset = 0;
}
// Loop over the population size and create new individuals with
// crossover
for (int i = elitismOffset; i < pop.size(); i++) {
Individual indiv1 = tournamentSelection(pop);
Individual indiv2 = tournamentSelection(pop);
Individual newIndiv = crossover(indiv1, indiv2);
newPopulation.saveIndividual(i, newIndiv);
}
// Mutate population
for (int i = elitismOffset; i < newPopulation.size(); i++) {
mutate(newPopulation.getIndividual(i));
}
for(int i=0;i<pop.size();i++)
{for(int j=0;j<pop.getIndividual(i).size();j++)
{if(i%2==1){Individual individual1=Population.individuals[i-1];
Individual individual2=Population.individuals[i];
if(Population.individuals[i-1].getGene(i-1)==0 && Population.individuals[i].getGene(i)==0){
Population.individuals[i-1].fitness=individual1.fitness+1;
Population.individuals[i].fitness=individual2.fitness+1;
}
if(Population.individuals[i-1].getGene(i-1)==1 && Population.individuals[i].getGene(i)==1){
Population.individuals[i-1].fitness=individual1.fitness+2;
Population.individuals[i].fitness=individual2.fitness+2;
}
if(Population.individuals[i-1].getGene(i-1)==0 && Population.individuals[i].getGene(i)==1){
Population.individuals[i-1].fitness=individual1.fitness+3;
Population.individuals[i].fitness=individual2.fitness+0;
}
if(Population.individuals[i-1].getGene(i-1)==1 && Population.individuals[i].getGene(i)==0){
Population.individuals[i-1].fitness=individual1.fitness+0;
Population.individuals[i].fitness=individual2.fitness+3;
} }}}``
return newPopulation;
}
// Crossover individuals
private static Individual crossover(Individual indiv1, Individual indiv2) {
Individual newSol = new Individual();
// Loop through genes
for (int i = 0; i < indiv1.size(); i++) {
// Crossover
if (Math.random() <= uniformRate) {
newSol.setGene(i, indiv1.getGene(i));
} else {
newSol.setGene(i, indiv2.getGene(i));
}
}
return newSol;
}
// Mutate an individual
private static void mutate(Individual indiv) {
// Loop through genes
for (int i = 0; i < indiv.size(); i++) {
if (Math.random() <= mutationRate) {
// Create random gene
long gene = Math.round(Math.random());
indiv.setGene(i, gene);
}
}
}
// Select individuals for crossover
private static Individual tournamentSelection(Population pop) {
// Create a tournament population
Population tournament = new Population(tournamentSize, false);
// For each place in the tournament get a random individual
for (int i = 0; i < tournamentSize; i++) {
int randomId = (int) (Math.random() * pop.size());
tournament.saveIndividual(i, pop.getIndividual(randomId));
}
// Get the fittest
Individual fittest = tournament.getFittest();
return fittest;
}
package simpleGa;
public class FitnessCalc {
/* Public methods */
// Set a candidate solution as a byte array
// To make it easier we can use this method to set our candidate solution
// with string of 0s and 1s
// Calculate inidividuals fittness by comparing it to our candidate solution
static int getFitness(Individual individual) {
int fitness = 0;
// Loop through our individuals genes and compare them to our cadidates
fitness=Individual.fitness;
return fitness;
}
}
// Get optimum fitness
}
package simpleGa;
import java.util.Scanner;
public class GAprisonerdilemma {
public static void main(String[] args) {
// Set a candidate solution
Scanner keyboard = new Scanner(System.in);
System.out.println("Input number of games!");
int k = keyboard.nextInt();
Individual.setDefaultGeneLength(k);
// Create an initial population
System.out.println("Input number of individuals in the population!");
int p = keyboard.nextInt();
Population myPop = new Population(p, true);
System.out.println("Input acceptable number of generations!");
int l = keyboard.nextInt();
// Evolve our population until we reach an optimum solution
int generationCount = 0;
int j=l+1;
System.out.println("Input requiered fitness value !");
int f = keyboard.nextInt();
int h=0;
// Evolve our population until we reach an optimum solution
for(int i=0;i<j;i++)
{
if(i==0){}
else{
if(myPop.getFittest().getFitness()>=f){if(h==0){h++;}
else{ System.out.println("Solution found!");
System.out.println("Generation: " + generationCount);
System.out.println( "Fitness(Points): " + myPop.getFittest().getFitness());
break;}
}else {myPop = Algorithm.evolvePopulation(myPop);
generationCount++;
System.out.println("Generation: " + generationCount + " Fittest: " + myPop.getFittest().getFitness());
}
if(i==j-1){ if(myPop.getFittest().getFitness()>=f)System.out.println("Solution found !");
else System.out.println("Solution not found closest solution is!");
System.out.println("Generation: " + generationCount);
System.out.println( " Fitness(Points): " + myPop.getFittest().getFitness());}
}
}
System.out.println("0 for betrays in that turn 1 for cooperates!");
System.out.println("Turns:");
System.out.println(myPop.getFittest());
}
}

Can't locate the problems in this simple Genetic Algorithm program

I have written a simple genetic algorithm program in java. What it is does is maximize the decimal value represented by the bits in the chromosome. Somehow mutation is not working as expected, e.g. causing two genes to mutate when just one is to change. The print statements I have included there show which to mutate, but in addition to that some more chromosomes get mutated. I can't figure out what the problem is :-(
Here are my java classes.
Gene.java
public class Gene {
private int value;
public Gene() {
value = Math.random() < 0.5 ? 0 : 1;
}
public Gene(int value) {
if (value != 0 && value != 1) {
throw new IllegalArgumentException("value must be either 0 or 1");
}
else {
this.value = value;
}
}
public void mutate() {
value = 1 - value;
}
public int value() {
return value;
}
#Override
public String toString() {
return String.valueOf(value);
}
}
Chromosome.java
import java.util.ArrayList;
import java.util.List;
public class Chromosome implements Comparable {
private ArrayList<Gene> genes;
private final int chromosomeLength;
public Chromosome(int length) {
this.genes = new ArrayList<>();
this.chromosomeLength = length > 0 ? length : 16;
for (int i = 0; i < chromosomeLength; i++) {
this.genes.add(i, new Gene());
}
}
public List<Gene> getAllele(int fromIndex, int toIndex) {
return new ArrayList<>(genes.subList(fromIndex, toIndex));
}
public void setAllele(int fromIndex, List<Gene> allele) {
int lastIndex = fromIndex + allele.size();
if (lastIndex > chromosomeLength) {
throw new IndexOutOfBoundsException("the allele exceeds beyond the size of the chromosome");
}
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
}
public int getChromosomeLength() {
return chromosomeLength;
}
public void setGeneAt(int index, Gene gene) {
genes.set(index, gene);
}
public Gene getGeneAt(int index) {
return genes.get(index);
}
public int value() {
return Integer.parseInt(this.toString(), 2);
}
#Override
public String toString() {
StringBuilder chromosome = new StringBuilder("");
genes.stream().forEach((Gene g) -> chromosome.append(g));
return chromosome.toString();
}
#Override
public int compareTo(Object anotherChromosome) {
Chromosome c = (Chromosome) anotherChromosome;
return this.value() - c.value();
}
}
GenePool.java
import java.util.ArrayList;
import java.util.Arrays;
public class GenePool {
private final ArrayList<Chromosome> genePool;
private final int genePoolSize;
private final int chromosomeLength;
private final double crossOverRate;
private final double mutationRate;
private int[] crossPoints;
public GenePool(int numOfChromosome, int chromosomeLength, double crossOverRate, double mutationRate) {
this.genePoolSize = numOfChromosome;
this.chromosomeLength = chromosomeLength > 0 ? chromosomeLength : 16;
this.crossOverRate = crossOverRate;
this.mutationRate = mutationRate;
crossPoints = new int[1];
crossPoints[0] = this.chromosomeLength / 2;
genePool = new ArrayList<>();
for (int i = 0; i < numOfChromosome; i++) {
genePool.add(new Chromosome(chromosomeLength));
}
}
public int getGenePoolSize() {
return genePoolSize;
}
public Chromosome getChromosomeAt(int index) {
return genePool.get(index);
}
public void setChromosomeAt(int index, Chromosome c) {
genePool.set(index, c);
}
public int getChromosomeLength() {
return chromosomeLength;
}
public Chromosome[] crossOver(Chromosome c1, Chromosome c2) {
Chromosome[] offsprings = new Chromosome[2];
offsprings[0] = new Chromosome(c1.getChromosomeLength());
offsprings[1] = new Chromosome(c1.getChromosomeLength());
Chromosome[] parentChromosomes = {c1, c2};
int selector = 0;
for (int i = 0, start = 0; i <= crossPoints.length; i++) {
int crossPoint = i == crossPoints.length ? c1.getChromosomeLength() : crossPoints[i];
offsprings[0].setAllele(start, parentChromosomes[selector].getAllele(start, crossPoint));
offsprings[1].setAllele(start, parentChromosomes[1 - selector].getAllele(start, crossPoint));
selector = 1 - selector;
start = crossPoint;
}
return offsprings;
}
public void mutateGenePool() {
int totalGeneCount = genePoolSize * chromosomeLength;
System.out.println("Mutating genes:");
for (int i = 0; i < totalGeneCount; i++) {
double prob = Math.random();
if (prob < mutationRate) {
System.out.printf("Chromosome#: %d\tGene#: %d\n", i / chromosomeLength, i % chromosomeLength);
genePool.get(i / chromosomeLength).getGeneAt(i % chromosomeLength).mutate();
}
}
System.out.println("");
}
public int getLeastFitIndex() {
int index = 0;
int min = genePool.get(index).value();
int currentValue;
for (int i = 1; i < genePoolSize; i++) {
currentValue = genePool.get(i).value();
if (currentValue < min) {
index = i;
min = currentValue;
}
}
return index;
}
public void saveFittest(ArrayList<Chromosome> offsprings) {
// sort in ascending order
offsprings.sort(null);
offsprings.stream().forEach((offspring) -> {
int leastFitIndex = getLeastFitIndex();
if (offspring.value() > genePool.get(leastFitIndex).value()) {
genePool.set(leastFitIndex, offspring);
}
});
}
public void evolve(int noOfGeneration) {
for (int generation = 1; generation <= noOfGeneration; generation++) {
System.out.println("Generation :" + generation);
ArrayList<Integer> selection = new ArrayList<>();
for (int i = 0; i < genePoolSize; i++) {
if (Math.random() <= crossOverRate) {
selection.add(i);
}
}
if (selection.size() % 2 == 1) {
selection.remove(selection.size() - 1);
}
ArrayList<Chromosome> offsprings = new ArrayList<>();
for (int i = 0; i < selection.size(); i += 2) {
int index1 = selection.get(i);
int index2 = selection.get(i + 1);
offsprings.addAll(Arrays.asList(crossOver(genePool.get(index1), genePool.get(index2))));
}
System.out.println("Before saving the offsprings");
displayChromosomes(genePool, "GenePool");
displayChromosomes(offsprings, "Offsprings");
saveFittest(offsprings);
System.out.println("Before mutation:");
displayChromosomes(genePool, "GenePool");
mutateGenePool();
System.out.println("After mutation:");
displayChromosomes(genePool, "GenePool");
System.out.println("\n\n");
}
}
public void displayChromosomes(ArrayList<Chromosome> geneList, String name) {
System.out.println(name);
if (geneList.isEmpty()) {
System.out.println("Empty list");
}
geneList.stream().forEach((c) -> {
System.out.println(c + " -> " + c.value());
});
System.out.println("");
}
}
GADemo.java
public class GADemo {
public static void main(String[] args) {
GenePool gp = new GenePool(6, 8, 0.25, 0.01);
gp.evolve(10);
}
}
After evolving for a number of generations, the chromosomes all tend to become exactly the same, or very similar. And the problem is that that value is not the maximum for that many bits, and sometimes even a small value. For example, for 8 bits the values should (tend to) approach 255, but this doesn't do so in my code. Someone please provide a hint where/how to look for and solve the problem.
Focus on these lines and imagine the references. These are from setAllele()
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
You are basically copying the reference from one onto the other. They are the same Gene so whatever mutation you do on those genes, will also affect even other Chromosomes.
You must produce a deep copy here.
Initially each chromosome has an own list of genes. But when you do the crossover operation you set gene objects from one chromosome into the gene list of other chromosome.
When you evolve the system, the number of shared genes will rise and therefore ultimately all chromosomes will share the same genes. No matter how you mutate a gene the chromosomes are not affected.
EDIT:
As Incognito also answered the setAllele method seems to be the culprit where gene sharing starts. You may want to introduce a method in the gene class where you can set its value given another gene.

How to create dynamic array in java with unclear and diffrent inpu INDEXes?

I am new to Java and I needed dynamic Array ... all of thing I found that's for dynamic Array we should use "Array List' that's ok but when I want the indexes to be the power of X that given from input , I face ERORR ! .. the indexes are unclear and the are not specified what is the first or 2th power ! .... can anyone help me how solve it?
public static void main(String[] args) throws Exception {
Scanner Reader = new Scanner(System.in);
ArrayList<Float> Zarayeb = new ArrayList<Float>();
Float s ;
int m;
System.out.print("Add Count of equation Sentences : ");
int N = Reader.nextInt();
if (N == 0)
return;
for (int i = 0; i < N ; i++) {
s = Reader.nextFloat() ;
System.out.print("x^");
m = Reader.nextInt();
if (Zarayeb.get(m)== null)
Zarayeb.add(0 , s);
else{
Float l ;
l = Zarayeb.get(m);
Zarayeb.add (m , l+s);
}
if (i < N-1)
System.out.print("\r+");
}
System.out.print("Add Count of equation Sentences : ");
N = Reader.nextInt();
if (N == 0)
return;
for (int i = 0; i < N ; i++) {
s = Reader.nextFloat() ;
System.out.print("x^");
m = Reader.nextInt();
if (Zarayeb.get(m)== null)
Zarayeb.add(m , s);
else{
Float l ;
l = Zarayeb.get(m);
Zarayeb.add (m , l+s);
}
if (i < N-1)
System.out.print("\r+");
}
System.out.print("Enter X: ");
float X = Reader.nextFloat();
float Sum = 0;
for (int i = 0; i < Zarayeb.size();i++) {
Sum += (Zarayeb.get(i) * Math.pow(X,i));
}
System.out.println("\nThe final answer is : " + Sum);
First I refactored your code a bit to make sense of it:
Main class with the top level logic:
import java.util.Scanner;
public class Main {
private Scanner scanner;
private final Totals totals = new Totals();
public static void main(final String[] args) {
final Main app = new Main();
app.run();
}
private void run() {
scanner = new Scanner(System.in);
try {
readAndProcessEquationSentences();
} finally {
scanner.close();
}
}
private void readAndProcessEquationSentences() {
readSentences(true);
readSentences(false);
System.out.println("The final answer is : " + totals.calculateSum(readBaseInput()));
}
private void readSentences(final boolean useInitialLogic) {
System.out.print("Enter number of equation sentences:");
final int numberOfSentences = scanner.nextInt();
if (numberOfSentences == 0) {
throw new RuntimeException("No sentences");
}
for (int i = 0; i < numberOfSentences; i++) {
Sentence sentence = Sentence.read(scanner);
if (useInitialLogic) {
totals.addInitialSentence(sentence);
} else {
totals.addNextSentence(sentence);
}
if (i < numberOfSentences - 1) {
System.out.print("\r+");
}
}
}
private float readBaseInput() {
System.out.print("Enter base: ");
return scanner.nextFloat();
}
}
Sentence class which represents one equation sentence entered by the user:
import java.util.Scanner;
public class Sentence {
private Float x;
private int y;
public static Sentence read(final Scanner scanner) {
final Sentence sentence = new Sentence();
System.out.println("Enter x^y");
System.out.print("x=");
sentence.x = scanner.nextFloat();
System.out.println();
System.out.print("y=");
sentence.y = scanner.nextInt();
System.out.println();
return sentence;
}
public Float getX() {
return x;
}
public int getY() {
return y;
}
}
Totals class which keeps track of the totals:
import java.util.ArrayList;
import java.util.List;
public class Totals {
private final List<Float> values = new ArrayList<Float>();
public void addInitialSentence(final Sentence sentence) {
if (values.size() <= sentence.getY()) {
addToStart(sentence);
} else {
addToValue(sentence);
}
}
private void addToStart(final Sentence sentence) {
values.add(0, sentence.getX());
}
public void addNextSentence(final Sentence sentence) {
if (values.size() <= sentence.getY()) {
values.add(sentence.getY(), sentence.getX());
} else {
addToValue(sentence);
}
}
private void addToValue(final Sentence sentence) {
Float total = values.get(sentence.getY());
total = total + sentence.getX();
values.add(sentence.getY(), total);
}
public float calculateSum(final float base) {
float sum = 0;
for (int i = 0; i < values.size(); i++) {
sum += (values.get(i) * Math.pow(base, i));
}
return sum;
}
}
I don't have the foggiest idea what this is supposed to do. I named the variables according to this foggy idea.
You are letting the user input values in two separate loops, with a slightly different logic I called 'initial' and 'next'.
In the initial loop you were doing this:
if (Zarayeb.get(m) == null)
Zarayeb.add(0 , s);
In the next loop this:
if (Zarayeb.get(m) == null)
Zarayeb.add(m , s);
There are problems with this because the ArrayList.get(m) will throw an IndexOutOfBoundException if m is out or range. So I changed that to the equivalent of:
if (Zarayeb.size() <= m) {
....
}
However, in the 'next' case this still does not solve it. What should happen in the second loop when an 'm' value is entered for which no element yet exists in the ArrayList?
Why do you need to enter sentences in two loops?
What is the logic supposed to achieve exactly?

Given a target sum, find if there is a pair of element in the given array which sums up to it

import java.util.HashMap;
public class target
{
public static void hash(int []a,int sum)
{
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
int i;
for (i = 0; i < a.length; ++i)
map.put(a[i], sum-a[i]);
for (i = 0; i < a.length; ++i)
if(map.containsValue(a[i]) && map.get(a[i])!=null)
{
System.out.println("("+a[i]+","+map.get(a[i])+")");
map.remove(a[i]);
}
}
public static void main(String[] args)
{
int []a={1, 2, 13, 34, 9, 3, 23, 45, 8, 7, 8, 3, 2};
hash(a,11);
}
}
I want to know if there is a better and more efficient solution that the above one. Complexity of this is n. Can I do better?
Your implementation misses duplicated pairs.
You could
sort the array
iterate from the start and for each element
calculate the required complement (sum - element)
do a reverse binary search (from the end of the sorted array) looking for that precise value
if found, remove both
It boils down to the observation that, with elements sorted:
n1 < n2 < n3 < n4 < n5 < n6
the most likely pairs are coming symmetrically from both ends to the middle. Now, the worst case is still bad, but at least you don't have the hashtable overhead
As I commented, your sollution is not O(N), because the containsValue make a search of all values stored at the HashMap. To solve it, I made a different approach using your solution:
public static void newVersion(int[] a, int sum){
HashMap<Integer, Boolean> map = new HashMap<Integer, Boolean>();
for (int i= 0; i< a.length; i++) {
map.put(sum - a[i], true);
}
for (int i = 0; i < a.length; i++) {
if (map.containsKey(a[i]) && map.get(a[i])) {
System.out.println("("+(sum-a[i])+","+a[i]+")");
map.put(a[i], false);
map.put(sum-a[i], false);
}
}
}
At the first step, it stores the "complement value" of each integer and at the second step it checks if the complement exists. If it exists, mark both pair as used.
This complexity is:
* O(N) for the first looping
* O(N) * (O(1) + O(1)) for the second loop and the containsValue and get.
* Finally: O(N) + O(N) .:. O(N) solution,
I have the following solution for this problem. The time complexity should be O(N) because the HashMap operations put, get and keySet are O(1).
import java.util.HashMap;
import java.util.Map;
/**
* Find a pair of numbers in an array given a target sum
*
*
*/
public class FindNums {
public static void findSumsForTarget(int[] input, int target)
{
// just print it instead of returning
Map<Integer, String> myMap = populateMap(input);
// iterate over key set
for (Integer currKey : myMap.keySet()) {
// find the diff
Integer diff = target - currKey;
// check if diff exists in the map
String diffMapValue = myMap.get(diff);
if(diffMapValue!=null)
{
// sum exists
String output = "Sum of parts for target " + target + " are " + currKey + " and " + diff;
System.out.println(output);
return; // exit; we're done - unless we wanted all the possible pairs and permutations
}
// else
// keep looking
}
System.out.println("No matches found!");
}
private static Map<Integer, String> populateMap(int[] input)
{
Map<Integer,String> myMap = new HashMap<Integer,String>();
for (int i = 0; i < input.length; i++) {
String currInputVal = myMap.get(input[i]);
if(currInputVal!=null) // value already exists
{
// append current index location to value
currInputVal = currInputVal + ", " + i;
// do a put with the updated value
myMap.put(input[i], currInputVal);
}
else
{
myMap.put(input[i], Integer.toString(i)); // first argument is autoboxed to Integer class
}
}
return myMap;
}
// test it out!
public static void main(String[] args)
{
int[] input1 = {2,3,8,12,1,4,7,3,8,22};
int[] input2 = {1,2,3,4,5,6,7,8,9,10};
int[] input3 = {2,-3,8,12,1,4,7,3,8,22};
int target1 = 19;
int target2 = 16;
// test
FindNums.findSumsForTarget(input1, target1);
FindNums.findSumsForTarget(input1, -1);
FindNums.findSumsForTarget(input2, target2);
FindNums.findSumsForTarget(input3, target1);
}
}
import java.util.*;
import java.io.*;
class hashsum
{
public static void main(String arg[])throws IOException
{
HashMap h1=new HashMap();
h1.put("1st",new Integer(10));
h1.put("2nd",new Integer(24));
h1.put("3rd",new Integer(12));
h1.put("4th",new Integer(9));
h1.put("5th",new Integer(43));
h1.put("6th",new Integer(13));
h1.put("7th",new Integer(5));
h1.put("8th",new Integer(32));
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter no.");
int no=Integer.parseInt(br.readLine());
Iterator i=h1.entrySet().iterator();
boolean flag=false;
while(i.hasNext())
{
Map.Entry e1=(Map.Entry)i.next();
Integer n1=(Integer)e1.getValue();
Iterator j=h1.entrySet().iterator();
while(j.hasNext())
{
Map.Entry e2=(Map.Entry)j.next();
Integer n2=(Integer)e2.getValue();
if(no==(n1+n2))
{
System.out.println("Pair of elements:"+n1 +" "+n2);
flag=true;
}
}
}
if(flag==false)
System.out.println("No pairs");
}
}
public static void hash1(int[] a, int num) {
Arrays.sort(a);
// printArray(a);
int top = 0;
int bott = a.length - 1;
while (top < bott) {
while (a[bott] > num)
bott--;
int sum = a[top] + a[bott];
if (sum == num) {
System.out.println("Pair " + a[top] + " " + a[bott]);
top++;
bott--;
}
if (sum < num)
top++;
if (sum > num)
bott--;
}
}
Solution: O(n) time and O(log(n)) space.
public static boolean array_find(Integer[] a, int X)
{
boolean[] b = new boolean[X];
int i;
for (i=0;i<a.length;i++){
int temp = X-a[i];
if(temp >= 0 && temp < X) //make sure you are in the bound or b
b[temp]=true;
}
for (i=0;i<a.length;i++)
if(a[i]<X && b[a[i]]) return true;
return false;
}
Recursively to find the subset whose sum is the targeted sum from given array.
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static Set<List<Integer>> set = new HashSet<>();
public static void main(String[] args) {
int[] biggerArray = {1, 2, 1, 1};
int targetedSum = 3;
findSubset(biggerArray, targetedSum);
}
public static void findSubset(int[] biggerArray, int targetedSum) {
for (int i = 0; i < biggerArray.length; i++) {
List<Integer> subset = new ArrayList<>();
if (biggerArray[i] > targetedSum)
continue;
else
subset.add(biggerArray[i]);
if (i + 1 < biggerArray.length)
find(subset, i, biggerArray, targetedSum, i);
}
System.out.println(set);
}
public static List<Integer> find(List<Integer> subset, int startIndex, final int[] biggerArray, final int targetedSum, final int skipIndex) {
if (skipIndex == startIndex) {
find(subset, startIndex + 1, biggerArray, targetedSum, skipIndex);
return null;
}
int subsetSum = findSumOfList(subset);
int remainedSum = targetedSum - subsetSum;
int i = startIndex;
if (remainedSum == 0) {
set.add(subset);
return null;
}
if ((startIndex < biggerArray.length) && (biggerArray[startIndex] == remainedSum)) {
List<Integer> temp = new ArrayList<Integer>(subset);
temp.add(biggerArray[i]);
set.add(temp);
}
else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] < remainedSum)) {
while (i + 1 <= biggerArray.length) {
List<Integer> temp = new ArrayList<Integer>(subset);
if (i != skipIndex) {
temp.add(biggerArray[i]);
find(temp, ++i, biggerArray, targetedSum, skipIndex);
}
else {
i = i + 1;
}
}
}
else if ((startIndex < biggerArray.length) && (biggerArray[startIndex] > remainedSum)) {
find(subset, ++i, biggerArray, targetedSum, skipIndex);
}
return null;
}
public static int findSumOfList(List<Integer> list) {
int i = 0;
for (int j : list) {
i = i + j;
}
return i;
}
}
We need not have two for loops. The match can be detected in the same loop while populating the map it self.
public static void matchingTargetSumPair(int[] input, int target){
Map<Integer, Integer> targetMap = new HashMap<Integer, Integer>();
for(int i=0; i<input.length; i++){
targetMap.put(input[i],target - input[i]);
if(targetMap.containsKey(target - input[i])){
System.out.println("Mathcing Pair: "+(target - input[i])+" , "+input[i]);
}
}
}
public static void main(String[] args) {
int[] targetInput = {1,2,4,5,8,12};
int target = 9;
matchingTargetSumPair(targetInput, target);
}
We can easily find if any pair exists while populating the array itself. Use a hashmap and for every input element, check if sum-input difference element exists in the hashmap or not.
import java.util.*;
class findElementPairSum{
public static void main(String[] args){
Map<Integer, Integer> hm = new HashMap<Integer, Integer>();
Scanner sc = new Scanner(System.in);
System.out.println("Enter the sum key: ");
int sum=sc.nextInt();
for(int i=0; i<10; i++){
int x = sc.nextInt();
if(!hm.containsKey(sum-x)){
hm.put(x, 1);
} else {
System.out.println("Array contains two elements with sum equals to: "+sum);
break;
}
}
}
}

Categories

Resources