printing optimal binary search tree in preorder dynamic programming algorith - java

I have just finished up computing the average cost of an OBST and I know I computed it correctly. My next task is to print the tree in preorder. I have an attempt at this using recursion but can't seem to shake the null pointer error.
Here's my code:
public class OBST {
static String[] keysA;
static Integer[][] root;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int tot = sc.nextInt();
HashMap<String, Double> hm = new HashMap<String, Double>();
int uniqNum = 0;
String[] rawInput = new String[tot];
for(int i=0; i<tot; i++) {
String tmp1 = sc.next();
if(i==0) {
hm.put(tmp1, 1.0);
uniqNum += 1.0;
} else if( i != 0) {
if(!hm.containsKey(tmp1)) {
hm.put(tmp1, 1.0);
uniqNum += 1.0;
} else {
Double tmpfreq = 0.0;
tmpfreq = hm.get(tmp1);
hm.put(tmp1, (tmpfreq + 1.0));
}
}
}
Set<String> keys = hm.keySet();
keysA = keys.toArray(new String[uniqNum]);
Double[] freqsA = new Double[uniqNum];
Arrays.sort(keysA);
for(int i=0; i<uniqNum; i++) {
Double tmp = 0.0;
String tmpK = keysA[i];
tmp = hm.get(tmpK);
tmp = tmp/tot;
freqsA[i] = tmp;
}
Double[][] eee = new Double[uniqNum+2][uniqNum+1];
Double[][] www = new Double[uniqNum+2][uniqNum+1];
//matrix to store optimal structure
root = new Integer[uniqNum+1][uniqNum+1];
for(int i=1; i<uniqNum+2; i++) {
eee[i][i-1] = 0.0;
www[i][i-1] = 0.0;
}
for(int l=1; l<uniqNum+1; l++) {
for(int i=1; i<=uniqNum-l+1; i++) {
int j = i + l - 1;
eee[i][j] = Double.MAX_VALUE;
www[i][j] = www[i][j-1] + freqsA[j-1];
for(int r=i; r<=j; r++) {
Double t = eee[i][r-1] + eee[r+1][j] + www[i][j];
if(t<eee[i][j]) {
eee[i][j] = t;
root[i][j] = r-1;
}
}
}
}
//total cost
System.out.println(eee[1][uniqNum]);
printTree(1,uniqNum-1,-1, "");
}
public static void printTree(int min, int max, int parent, String s) {
int r = root[min][max];
if(parent == -1 ) {
System.out.println(keysA[r] + " is root");
} else if(min < parent) {
System.out.println(keysA[r] + " is the left child of " + s);
} else {
System.out.println(keysA[r] + " is the right child of " + s);
} if(min < max) {
printTree(min,r,r+1,keysA[r]);
printTree(r+1,max,r,keysA[r]);
}
}
}
My trouble is in the method print tree.

Looks like you aren't checking your bounds correctly. If there is no left or right child, you shouldn't be printing that side. so make sure you check that r+1 is within the array size, and also that a node exists there. do the same for both left and right sides.

Related

Why is Java string array appending a string to null in first cell?

Here is my class below, that compares elements in two string arrays, and returns the word with the highest frequency in both arrays. However as visible from the output, the first index is appending none to null in spite of initializing both arrays with the String none. Can someone kindly let me know what I am doing wrong that is leading to this?
public class HelloWorld{
public String[] pro;
public String[] con;
String proSplitter;
String conSplitter;
public HelloWorld() {
this.pro = new String[9];
this.con = new String[9];
for(int i=0;i<this.pro.length;i++)
{
this.pro[i]="none";
this.con[i]="none";
}
}
public String[] getPro() {
return pro;
}
public String[] getCon() {
return con;
}
public void setPro(String pros, int proIndex) {
pro[proIndex] = pros;
}
public void setCon(String cons, int conIndex) {
con[conIndex] = cons;
}
public String[] proWord(){
for(int i=0;i<9;i++)
{
proSplitter = proSplitter + pro[i] + ",";
}
for(int i=0;i<9;i++)
{
conSplitter = conSplitter + con[i] + ",";
}
String[] values = proSplitter.split(",");
for(int i=0;i<values.length;i++)
{
values[i] = values[i].trim();
}
String[] values1 = conSplitter.split(",");
for(int i=0;i<values1.length;i++)
{
values1[i] = values1[i].trim();
}
int [] fr = new int [values.length];
int visited = -1;
for(int i = 0; i < values.length; i++){
int count = 1;
for(int j = i+1; j < values.length; j++){
if(!values[i].equalsIgnoreCase("none"))
{
if(values[i].compareTo(values[j])==0){
count++;
//To avoid counting same element again
fr[j] = visited;
}
}
}
if(fr[i] != visited)
fr[i] = count;
}
int max = fr[0];
int index = 0;
for (int i = 0; i < fr.length; i++)
{
if (max < fr[i])
{
max = fr[i];
index = i;
}
}
int [] fr1 = new int [values1.length];
int visited1 = -1;
for(int i = 0; i < values1.length; i++){
int count1 = 1;
for(int j = i+1; j < values1.length; j++){
if(!values1[i].equalsIgnoreCase("none"))
{
if(values1[i].compareTo(values1[j])==0){
count1++;
//To avoid counting same element again
fr1[j] = visited1;
}
}
}
if(fr1[i] != visited1)
fr1[i] = count1;
}
for(int i = 0;i<values.length;i++)
{
System.out.println("pro = "+values[i]);
}
for(int i = 0;i<values1.length;i++)
{
System.out.println("con = "+values1[i]);
}
int max1 = fr1[0];
int index1 = 0;
for (int i = 0; i < fr1.length; i++)
{
if (max1 < fr1[i])
{
max1 = fr1[i];
index1 = i;
}
}
String sentence[] = new String[2];
if(values[index].equalsIgnoreCase(values1[index1])) {
sentence[0] = "balanced";
}else {
sentence[0] = values[index];
sentence[1] = values1[index1];
}
return sentence;
}
public static void main(String[] args){
HelloWorld tracker = new HelloWorld();
tracker.setPro("Apple, Pear", 1);
tracker.setCon("Banana", 1);
tracker.setPro("Apple", 2);
tracker.setCon("Water Melon", 2);
tracker.setPro("Guava", 3);
tracker.setCon("Ball", 3);
tracker.setPro("Apple", 4);
tracker.setCon("Mango, Plum", 4);
String[] arr = tracker.proWord();
System.out.println("pro = "+arr[0]);
System.out.println("con = "+arr[1]);
}
}
The output being generated is :
pro = nullnone
pro = Apple
pro = Pear
pro = Apple
pro = Guava
pro = Apple
pro = none
pro = none
pro = none
pro = none
con = nullnone
con = Banana
con = Water Melon
con = Ball
con = Mango
con = Plum
con = none
con = none
con = none
con = none
pro = Apple
con = nullnone
As mentioned by Arnaud, the immediate problem is that you're leaving proSplitter uninitialized, so its value is null. Then, when you come to append a string to it with proSplitter = proSplitter + pro[i] + ",";, proSplitter will be converted (effectively) to "null", and then stuff is appended to the end. So, instead, make it "" initially.
However, you've got another problem here, which is that you're mutating a member variable each time you invoke that method - so it's not null (or empty) second time around, it still contains what was there previously.
The fix for that is straightforward: instead of using a member variable, declare these as local variables.
You've also got the problem that you're effectively duplicating the code to count the most frequent thing in an array: this is what methods are for, to allow you to run the same code over different inputs.
You can also make use of library methods. For example:
String mostFrequent(String[] array) {
int maxFreq = 0;
String maxFreqS = "";
for (String s : array) {
if (s.equalsIgnoreCase("none")) continue;
int freq = Collections.frequency(Arrays.asList(array), s);
if (freq > maxFreq) {
maxFreq = freq;
maxFreqS = s;
}
}
return maxFreqS;
}
(There are lots of inefficiencies here. The point is more about writing this as a method, to remove the duplication).
Then you can use this inside your existing method, and it will be a whole lot easier for others - and you - to read.

save contents from void method to variable

I am trying to print write the contents from void method to a file but I cant seem to get it to work. I call my method in the main and it prints to the console just fine. I have tried many different approaches but not one worked. Can anyone help/guide me in the right direction?
I have pasted my code below for reference. In my main function I call dijkstra(M, SV - 1) that prints my array to the screen, my goal is to have that same array printed to a file.
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.util.Scanner;
public class Main_2 {
static int SV = 0; // source vertex
static int N = 0;
static int M[][];
public static int distance[];
static int minDistance(int dist[], Boolean shortestPath[]) {
int min = Integer.MAX_VALUE, minI = -1;
for (int i = 0; i < N; i++)
if (shortestPath[i] == false && dist[i] <= min) {
min = dist[i];
minI = i;
}
return minI;
}
public static void printArr(int dist[], int n) {
// System.out.println("vertex distance");
for (int i = 0; i < N; i++)
System.out.println("[" + dist[i] + "]");
}
public static void dijkstra(int graph[][], int src) {
// The output array. dist[i] will hold
// the shortest distance from src to i
int dist[] = new int[N];
// sptSet[i] will true if vertex i is included in shortest
// path tree or shortest distance from src to i is finalized
Boolean shortestPath[] = new Boolean[N];
// Initialize all distances as INFINITE and stpSet[] as false
for (int i = 0; i < N; i++) {
dist[i] = Integer.MAX_VALUE;
shortestPath[i] = false;
}
// Distance of source vertex from itself is always 0
dist[src] = 0;
// Find shortest path for all vertices
for (int i = 0; i < N - 1; i++) {
// Pick the minimum distance vertex from the set of vertices
// not yet processed. u is always equal to src in first
// iteration.
int u = minDistance(dist, shortestPath);
// Mark the picked vertex as processed
shortestPath[u] = true;
// Update dist value of the adjacent vertices of the
// picked vertex.
for (int j = 0; j < N; j++)
// Update dist[v] only if is not in sptSet, there is an
// edge from u to v, and total weight of path from src to
// v through u is smaller than current value of dist[v]
if (!shortestPath[j] && graph[u][j] != 0 && dist[u] != Integer.MAX_VALUE
&& dist[u] + graph[u][j] < dist[j])
dist[j] = dist[u] + graph[u][j];
}
// print the constructed distance array
printArr(dist, N);
}
public static void main(String[] args) {
try {
int i = 0, j = 0; // counters
FileInputStream textFile = new FileInputStream("EXAMPLE(2).txt"); // name of input file must go in here
Scanner scan = new Scanner(textFile);
N = scan.nextInt(); // read in the size
String flush = scan.nextLine(); // gets rid of linefeed
System.out.println(N);
M = new int[N][N]; // instantiates array
// this loop reads in matrix from input file
String line;
while (i < N && (line = scan.nextLine()) != null) {
j = 0;
String delim = " ";
String tokens[] = line.split(delim);
for (String a : tokens) {
M[i][j] = Integer.parseInt(a);
j++;
}
i++;
}
if (i > N)
;
SV = scan.nextInt();
} catch (Exception e) {
e.printStackTrace();
}
printMatrix(M);
System.out.println(SV);
System.out.println();
dijkstra(M, SV - 1);
try {
FileWriter fw = new FileWriter("Shortest_path.txt"); // writes transitive closure to file
BufferedWriter bw = new BufferedWriter(fw);
for (int i = 0; i < N; i++) {
// bw.write(dist[i]);
}
} catch (Exception e) {
System.out.println(e);
}
}
public static void printMatrix(int[][] Matrix) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(Matrix[i][j]);
System.out.print(" ");
}
System.out.println();
}
}
}
try (FileWriter fileWriter = new FileWriter("YourFileName.txt");
PrintWriter printWriter = new PrintWriter(fileWriter)) {
for (int i=0; i<N; i++) {
printWriter.printf(Integer.toString(dist[i]));
}
} catch (Exception e) {
System.out.println(e);
}
"A" simple solution, would be to pass the PrintStream you want to use to the method, for example...
public static void printArr(int dist[], int n, PrintStream ps) {
for (int i = 0; i < N; i++) {
ps.println("[" + dist[i] + "]");
}
}
This will then require you to pass a PrintStream instance to the method when ever you call it. Since dijkstra also calls printArr, you will need to pass the instance of the PrintStream to it as well...
public static void dijkstra(int graph[][], int src, PrintStream ps) {
//...
// print the constructed distance array
printArr(dist, N, ps);
}
Then you just create an instance of the PrintStream you want to use and pass it to the methods...
public static void main(String[] args) {
try (FileInputStream textFile = new FileInputStream("EXAMPLE(2).txt")) {
int i = 0, j = 0; // counters
Scanner scan = new Scanner(textFile);
N = scan.nextInt(); // read in the size
String flush = scan.nextLine(); // gets rid of linefeed
System.out.println(N);
M = new int[N][N]; // instantiates array
// this loop reads in matrix from input file
String line;
while (i < N && (line = scan.nextLine()) != null) {
j = 0;
String delim = " ";
String tokens[] = line.split(delim);
for (String a : tokens) {
M[i][j] = Integer.parseInt(a);
j++;
}
i++;
}
if (i > N)
;
SV = scan.nextInt();
try (PrintStream ps = new PrintStream("EXAMPLE(2).txt")) {
printMatrix(M);
System.out.println(SV);
System.out.println();
dijkstra(M, SV - 1, ps);
}
} catch (Exception e) {
e.printStackTrace();
}
}
I restructured your main method slightly, as the output is depended on the success of the input ;). Also see The try-with-resources statement for more details
This means you could do something like...
dijkstra(M, SV - 1, System.out);
and it would once again print the output to the console :)

Training data algorithm not working. (Perceptron)

I am trying to write an algorithm to train perceptron but there seems to be values exceeding max value for double. I have been trying to figure out since yesterday but cannot.
The value of weights seems to be exceeding as well as the value of variable output.
The text file that is read in is of the form:
Input variables and the output
/**
* Created by yafael on 12/3/16.
*/
import java.io.*;
import java.util.*;
public class Perceptron {
static double[] weights;
static ArrayList<Integer> inputValues;
static ArrayList<Integer> outputValues;
static int[] inpArray;
static int[] outArray;
public static int numberOfInputValues(String filePath)throws IOException
{
Scanner valueScanner = new Scanner(new File(filePath));
int num = valueScanner.nextInt();
return num;
}
public static void inputs(String filePath)throws IOException
{
inputValues = new ArrayList<Integer>();
outputValues = new ArrayList<Integer>();
Scanner valueScanner = new Scanner(new File(filePath));
int num = valueScanner.nextInt();
while (valueScanner.hasNext())
{
String temp = valueScanner.next();
String[] values = temp.split(",");
for(int i = 0; i < values.length; i++)
{
if(i+1 != values.length)
{
inputValues.add(Integer.parseInt(values[i]));
}else
{
outputValues.add(Integer.parseInt(values[i]));
}
}
}
valueScanner.close();
}
public static void trainData(int[] inp, int[] out, int num,int epoch)
{
weights = new double[num];
Random r = new Random();
int i,ep;
int error = 0;
/*
* Initialize weights
*/
for(i = 0; i < num; i++)
{
weights[i] = r.nextDouble();
}
for(ep = 1; ep<= epoch; ep++)
{
double totalError = 0;
for(i = 0; i < inp.length/(num); i++)
{
double output = calculateOutput(inp, i, weights);
System.out.println("Output " + (i + 1) + ": " + output);
//System.out.println("Output: " + output);
if(output > 0)
{
error = out[i] - 1;
}else
{
error = out[i] - 0;
}
for(int temp = 0; temp < num; temp++)
{
double epCalc = (1000/(double)(1000+ep));
weights[temp] += epCalc*error*inp[((i*weights.length)+temp)];
//System.out.println("Epoch calculation: " + epCalc);
//System.out.println("Output: " + output);
//System.out.println("error: " + error);
//System.out.println("input " + ((i*weights.length)+temp) + ": " + inp[(i*weights.length)+temp]);
}
totalError += (error*error);
}
//System.out.println("Total Error: " + totalError);
if(totalError == 0)
{
System.out.println("In total error");
for(int temp = 0; temp < num; temp++)
{
System.out.println("Weight " +(temp)+ ": " + weights[temp]);
}
double x = 0.0;
for(i = 0; i < inp.length/(num); i++)
{
for(int j = 0; j < weights.length; j++)
{
x = inp[((i*num) + j)] * weights[j];
}
System.out.println("Output " + (i+1) + ": " + x);
}
break;
}
}
if(ep >= 10000)
{
System.out.println("Solution not found");
}
}
public static double calculateOutput(int[] input, int start, double[] weights)
{
start = start * weights.length;
double sum = 0.0;
for(int i = 0; i < weights.length; i++)
{
//System.out.println("input[" + (start + i) + "]: " + input[(start+i)]);
//System.out.println("weights[i]" + weights[i]);
sum += (double)input[(start + i)] * weights[i];
}
return sum - 1.0 ;
}
public static void main(String args[])throws IOException
{
BufferedReader obj = new BufferedReader(new InputStreamReader(System.in));
//Read the file path from the user
String fileName;
System.out.println("Please enter file path for Execution: ");
fileName = obj.readLine();
int numInputValues = numberOfInputValues(fileName);
//Call the function to store values in the ArrayList<>
inputs(fileName);
inpArray = inputValues.stream().mapToInt(i->i).toArray();
outArray = outputValues.stream().mapToInt(i->i).toArray();
trainData(inpArray, outArray, numInputValues, 10000);
}
}
I believe your code is problematic, so i am giving you a simple example but i am sure you will get help from this code to resolve your problem.
import java.util.Random;
public class Perceptron {
double[] weights;
double threshold;
public void Train(double[][] inputs, int[] outputs, double threshold, double lrate, int epoch) {
this.threshold = threshold;
int n = inputs[0].length;
int p = outputs.length;
weights = new double[n];
Random r = new Random();
//initialize weights
for(int i=0;i<n;i++) {
weights[i] = r.nextDouble();
}
for(int i=0;i<epoch;i++) {
int totalError = 0;
for(int j =0;j<p;j++) {
int output = Output(inputs[j]);
int error = outputs[j] - output;
totalError +=error;
for(int k=0;k<n;k++) {
double delta = lrate * inputs[j][k] * error;
weights[k] += delta;
}
}
if(totalError == 0)
break;
}
}
public int Output(double[] input) {
double sum = 0.0;
for(int i=0;i<input.length;i++) {
sum += weights[i]*input[i];
}
if(sum>threshold)
return 1;
else
return 0;
}
public static void main(String[] args) {
Perceptron p = new Perceptron();
double inputs[][] = {{0,0},{0,1},{1,0},{1,1}};
int outputs[] = {0,0,0,1};
p.Train(inputs, outputs, 0.2, 0.1, 200);
System.out.println(p.Output(new double[]{0,0})); // prints 0
System.out.println(p.Output(new double[]{1,0})); // prints 0
System.out.println(p.Output(new double[]{0,1})); // prints 0
System.out.println(p.Output(new double[]{1,1})); // prints 1
}
}

Cartesian products of two sets in Java

I'm trying to solve a problem from a textbook I'm using that has to do with cartesian products and sets without using built-in java APIs or any fancy function.
For example
Set A contains = {1,3,4}
Set B contains = {2,5}
their products would yield to this result {(1,2),(1,5),(3,2),(3,5),(4,2),(4,5)}
I have written some methods to perform various functions on each set but here is what I came up with. How could I implement this to the sets?
public String cartesian(Set other)
{
String result = "";
int res;
for ( int i = 0; i < this.size; ++i )
{
for ( int j = 0; j < other.size; ++j )
{
//System.out.println("#####"+ other.size);
//result = data[i] + ""+ other[i] + "";
//res = data[i] *= other.data[j];
}
}
return result;
}
The method returns the result as a string. My logic is to got through each set's element at the same time but I get stuck at thinking up a way to cross them together.
Here is the rest of my code.
public class Sets {
public static void main(String[] args)
{
Set set1;
set1 = new Set();
Set set2 = new Set();
set1.add(1);
set1.add(2);
set1.add(3);
set2.add(3);
set2.add(4);
/*set2.add(4);
set2.add(5);*/
//System.out.println(set1.difference(set2));
System.out.println(set1.cartesianReformed(set2));
}
}
User-defined Set class
class Set
{
private int[] data;
private int size;
public Set()
{
data = new int[20];
size = 0;
}
public void add(int value)
{
int[] copy;
//avoiding duplicates
if ( !in(value) )
{
if ( size > data.length )
{
copy = new int[data.length * 2];
System.arraycopy(data, 0, copy,0,data.length);
data = copy;
}
data[size] = value;
size++;
}
else
{
System.out.println("You are trying to insert a number that's already here ---> " + value);
}
}
public String toString()
{
String result = "{";
for(int i = 0; i < size; i++)
{
result += "" + data[i];
//Add a comma after all but the last item
if ( i < size - 1 )
{
result += ",";
}
}
result += "}";
return result;
}
public boolean in(int value)
{
boolean result = false;
for(int i = 0; i < size; i++)
{
if ( data[i] == value )
{
result = true;
}
}
return result;
}
public Set intersection(Set other)
{
Set result = new Set();
for ( int i = 0; i < size; ++i )
{
if ( other.in(data[i]) )
{
result.add(data[i]);
}
}
return result;
}
public boolean equals(Set other)
{
boolean result = false;
int count = 0;
for ( int i = 0; i < size; ++i ) //iterating over this
{
if ( other.in(data[i]) )
{
count++;
}
if ( count == size )
{
result = true;
}
}
return result;
}
public Set difference(Set other)
{
Set result = new Set();
for(int i = 0; i < size; ++i)
{
if ( !other.in(data[i]) )
{
result.add(data[i]);
}
}
return result;
}
public String cartesian(Set other)
{
String result = "";
int res;
for ( int i = 0; i < this.size; ++i )
{
for ( int j = 0; j < other.size; ++j )
{
//System.out.println("#####"+ other.size);
//result = data[i] + ""+ other[i] + "";
//res = data[i] *= other.data[j];
}
}
return result;
}
public Set union(Set other) {
Set result = (Set)other.clone();
for (int i = 0; i < size; i++) {
result.add(data[i]);
}
return result;
}
public Object clone() {
Set result = new Set();
for (int i = 0; i < size; i++) {
result.add(data[i]);
}
return result;
}
}
Something like this will work:
public String cartesian (Set other)
{
String [] cart = new String [this.size * other.size];
int k = 0;
for (int i : this.data)
{
for (int j : other.data)
{
cart[k++] = "(" + i + "," + j + ")";
}
}
return Arrays.toString(cart);
}
Returns:
[(1,2), (1,5), (3,2), (3,5), (4,2), (4,5)]
Note:
Naming your class Set is a bad idea since it conflicts with java.util.Set.
Let's get to the crux of the matter. You essentially need all the combinations of elements in 2 lists. The following is a very simple way of looking at it, by using nested for-loops to go over the elements in the sets A and B.
Set<Integer> A = new HashSet<Integer>();
Set<Integer> B = new HashSet<Integer>();
for(int i = 1 ; i < 5 ; i++)
A.add(i);
for(int i = 10 ; i < 13 ; i++)
B.add(i);
System.out.println("A: " + A);
System.out.println("B: " + B);
List<Set<Integer>> list = new ArrayList<Set<Integer>>();
for(Integer i: A) {
for(Integer j: B) {
Set<Integer> combination = new HashSet<Integer>();
combination.add(i);
combination.add(j);
list.add(combination);
}
}
System.out.println(list);

How Improve Run-time when sorting arrays

I have managed to create a working solution for "Mixing Milk" for USACO, but the judge says my program takes too long.
I think this has to do with the way I sort the list of Farmers by asking price in lines 29 - 44. Is there any way I can improve the run time?
/*
ID:
LANG: JAVA
TASK: milk
*/
import java.util.*;
import java.io.*;
public class milk {
public static void main(String[] args) throws IOException {
double startTime = System.currentTimeMillis();
BufferedReader s = new BufferedReader(new InputStreamReader(new FileInputStream(new File("test.in"))));
PrintWriter w = new PrintWriter(new File("test.out"));
// BufferedReader s = new BufferedReader(new InputStreamReader(new FileInputStream(new File("milk.in"))));
// PrintWriter w = new PrintWriter(new File("milk.out"));
String[] st = s.readLine().split(" ");
int N = Integer.parseInt(st[0]);
int M = Integer.parseInt(st[1]);
int[] P = new int[M];
int[] A = new int[M];
String[] sets = new String[M];
for (int i = 0; i < M; i++) {
sets[i] = s.readLine();
st = sets[i].split(" ");
P[i] = Integer.parseInt(st[0]);
}
int maxp = ("" + maxVal(P)).length();
for (int i = 0; i < M; i++) {
st = sets[i].split(" ");
while (st[0].length() < maxp) {
st[0] = "0" + st[0];
}
sets[i] = st[0] + " " + st[1];
}
Arrays.sort(sets);
int cap = 0;
for (int i = 0; i < M && cap <= N; i++) {
st = sets[i].split(" ");
P[i] = Integer.parseInt(st[0]);
A[i] = Integer.parseInt(st[1]);
cap += A[i];
}
int sum = 0;
int units = 0;
int a;
for (int i = 0; units < N; i++) {
if (A[i] <= N - units) {
sum = sum + P[i] * A[i];
units += A[i];
} else {
a = N - units;
if (a > A[i]) {
a = A[i];
}
sum = sum + P[i] * a;
units += a;
}
}
System.out.println(units);
System.out.println(sum);
w.println(sum);
w.close();
double endTime = System.currentTimeMillis();
System.out.println("Took " + ((endTime - startTime) / 1000) + " seconds.");
}
public static int maxVal(int[] x) {
int max = 0;
for (int i : x) {
if (i > max) {
max = i;
}
}
return max;
}
}
EDIT: Thanks Andreas!
Changed code and made the time limit:
/*
ID:
LANG: JAVA
TASK: milk
*/
import java.util.*;
import java.io.*;
public class milk {
public static void main(String[] args) throws IOException {
double startTime = System.currentTimeMillis();
// BufferedReader s = new BufferedReader(new InputStreamReader(new FileInputStream(new File("test.in"))));
// PrintWriter w = new PrintWriter(new File("test.out"));
BufferedReader s = new BufferedReader(new InputStreamReader(new FileInputStream(new File("milk.in"))));
PrintWriter w = new PrintWriter(new File("milk.out"));
String temp = s.readLine();
int spc = temp.indexOf(" ");
int N = Integer.parseInt(temp.substring(0, spc));
int M = Integer.parseInt(temp.substring(spc + 1));
System.out.println(N + " " + M);
int[] P = new int[M];
int[] A = new int[M];
Farmer[] f = new Farmer[M];
for (int i = 0; i < M; i++) {
temp = s.readLine();
spc = temp.indexOf(" ");
f[i] = new Farmer(Integer.parseInt(temp.substring(0, spc)), Integer.parseInt(temp.substring(spc + 1)));
}
Arrays.sort(f);
for (int i = 0; i < M; i++) {
P[i] = f[i].getPrice();
A[i] = f[i].getInventory();
}
int sum = 0;
int units = 0;
int a;
for (int i = 0; units < N; i++) {
if (A[i] <= N - units) {
sum = sum + P[i] * A[i];
units += A[i];
} else {
a = N - units;
if (a > A[i]) {
a = A[i];
}
sum = sum + P[i] * a;
units += a;
}
}
System.out.println(units);
System.out.println(sum);
w.println(sum);
w.close();
double endTime = System.currentTimeMillis();
System.out.println("Took " + ((endTime - startTime) / 1000) + " seconds.");
}
}
class Farmer implements Comparable<Farmer> {
private int price;
private int inventory;
public Farmer(int price, int inventory) {
this.price = price;
this.inventory = inventory;
}
public int getPrice() {
return price;
}
public int getInventory() {
return inventory;
}
#Override
public int compareTo(Farmer f1) {
if (f1.price != this.price) {
return this.price - f1.price;
} else if (f1.inventory != this.inventory) {
return f1.inventory - this.inventory;
} else {
return 0;
}
}
}
Java is an Object-Oriented language. Use it.
Your code keeps processing String lines, splitting and concatenating. That is slow.
Read your lines into objects containing the two integer values. Make the class implement Comparable, to sort by the two values, so you can call sort().
The processing is faster because you only parse the numbers once. The sorting is faster because you don't have to zero-pad the numbers, and you sort by integers, not string.
Since your lines consist of two integers separated by a single space, don't use split(). Use indexOf(' ') and call substring() twice. It's faster and less memory intensive.

Categories