I have been tasked to solve a question concerning the creation of a triple-ended queue with efficient random access, as outlined in this: https://open.kattis.com/problems/teque. I created a program based around using 2 very large arrays, one containing the front half of all stored integers so far and the other the back half, with both being of the same size or the front half containing at most 1 more element than the back half after every insertion operation. This should allow all insertion and retrieval operations to be of O(1) time complexity, but the code just keeps exceeding the given time limit. Can anyone tell me what is wrong with my code? Here it is:
import java.util.*;
import java.io.*;
public class Teque3 {
static int[] front = new int[1_000_000];
static int[] back = new int[1_000_000];
static int frontHead = 499_999;
static int backHead = 499_999;
static int frontSize = 0;
static int backSize = 0;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
for (int i = 0; i < n; i++) {
String[] line = br.readLine().split(" ");
if (line[0].equals("get")) {
int index = Integer.parseInt(line[1]);
if (index >= frontSize) System.out.println(back[backHead + index - frontSize]);
else System.out.println(front[frontHead + index]);
continue;
}
if (frontSize == backSize) {
if (line[0].equals("push_front")) {
frontHead--;
front[frontHead] = Integer.parseInt(line[1]);
frontSize++;
} else if (line[0].equals("push_back")) {
back[backHead + backSize] = Integer.parseInt(line[1]);
front[frontHead + frontSize] = back[backHead];
frontSize++;
backHead++;
} else if (line[0].equals("push_middle")) {
front[frontHead + frontSize] = Integer.parseInt(line[1]);
frontSize++;
}
} else {
if (line[0].equals("push_front")) {
frontHead--;
front[frontHead] = Integer.parseInt(line[1]);
backHead--;
back[backHead] = front[frontHead + frontSize];
backSize++;
} else if (line[0].equals("push_back")) {
back[backHead + backSize] = Integer.parseInt(line[1]);
backSize++;
} else if (line[0].equals("push_middle")) {
backHead--;
back[backHead] = Integer.parseInt(line[1]);
backSize++;
}
}
}
}
}
You could try to minimze IO-Operations: Collect your programm output. Instead of writing System.out.println better create a new StringBuilder to collect everything. In the end write all at once.
static StringBuilder result = new StringBuilder();
...
private static void result(int value) {
result.append(value).append("\n");
}
...
if (index >= frontSize) result(back[backHead + index - frontSize]);
else result(front[frontHead + index]);
...
System.out.println(result);
Decouple read from parse and process: Create one thread for reading the operations. But the operations in a Queue. Start another thread for the process.
Related
I am trying to create a program in Java that calculates the average cost of winning the lottery and saves that average to reference when it runs again (my goal is to be able to create a more accurate outcome every time i run it). The average successfully saves to my txt file, but when I run the program it uses 0 as the previous average every time. Any help is greatly appreciated! Thanks!
(Number of times it runs can be changed by changing the 'runs' variable)
public class WinningTheLottery
{
public static final int SIZE = 5;
public static void main(String[] args)
{
int[] winningNums = new int[SIZE];
int[] guessNums = new int[SIZE];
int spent, runs = 1;
double oldAvg = 0;
double newAvg;
int totalSpent = 0;
NumberFormat currency = NumberFormat.getCurrencyInstance();
try
{
Scanner fileScanner = new Scanner(new File("average.txt"));
PrintWriter fileWriter = new PrintWriter(new File("average.txt"));
while (fileScanner.hasNextDouble())
{
oldAvg = fileScanner.nextDouble();
}
for (int i = 0; i < runs; i++)
{
spent = 0;
randomlyAssignedNumbers(winningNums);
// Arrays.toString(nameOfArray) => built in method to print an array
System.out.println("\n[" + (i+1) + "] Todays winning numbers:\n" + Arrays.toString(winningNums).replace("[", "").replace("]", ""));
do
{
randomlyAssignedNumbers(guessNums);
spent++;
} while (howManyCorrect(winningNums, guessNums) < 5);
System.out.println("After spending " + currency.format(spent) + ", you won the Fantasy 5 lottery $75,000 prize!");
totalSpent += spent;
}
newAvg = ((totalSpent/runs) +oldAvg)/2;
fileWriter.println(newAvg);
System.out.println("\nAverage Cost to win the Lottery: " + currency.format(newAvg)
+ "\n(Previous Average: " + currency.format(oldAvg) + ")");
fileScanner.close();
fileWriter.close();
}
catch(IOException e)
{
System.out.println(e.getMessage());
}
}
public static void randomlyAssignedNumbers(int[] anyArray)
{
Random rng = new Random();
for (int i = 0; i < anyArray.length; i++)
{
anyArray[i] = rng.nextInt(36) + 1;
}
}
public static int howManyCorrect(int[] a1, int[] a2)
{
if (a1.length != a2.length)
return -1;
int count = 0;
for (int i = 0; i < a1.length; i++)
{
if (a1[i] == a2[i])
count++;
}
return count;
}
}
Your code is opening the file in overwrite mode, default of many programming languages, before scanner can read the content, thus deleting the content before fileScanner.hasNextDouble() read. Move your PrintWriter instantiation after Scanner read, and it will work.
Note: To open the file in append mode, which I don't think you need here. But in Java you use new FileWriter("average.txt", true) and then wrap a PrintWriter around it.
Try not constructing the PrintWriter until after you read the previous value. As noted in the Javadoc the file will be truncated by creating the PrintWriter.
So, I made this code almost work, but I want to use insertion sort on the array and for the output to display results sorted by product ID only by insertion sort. Each product ID should have the same corresponding number of units. The units should not be sorted independently. The only order would be by product ID is what I'm basically implying.
import java.util.*;
import java.io.*;
class newversion {
public static int [][] table; // the output table
public static int numOfRows; //number of rows used up in the table
public static int lookfor(int productID){
int location = -1; //-1 an error
for(int i = 0; i < numOfRows; i++){
if (table[i][0] == productID){
location = i;
}
}
return location;
}
/*
here is my modified bubble sort code. I based it on this, but done differently:
http://stackoverflow.com/questions/23283655/bubble-sort-on-2d-array-java
public static void swap(int int1, int int2, int[] array) {
if(int1 == int2){
return;
}
else{
int temp = int2;
array[int2] = array[int1];
array[int2] = temp;
}
}
but it didn't work and I had to try something else
*/
public static boolean contains(int productID){
if (lookfor(productID) == -1){
return false;
}
return true;
}
public static void main(String[] args) {
File file = null;
Scanner scanner = null;
try{
file = new File("data.csv");
scanner = new Scanner( file );
}
catch(Exception e){
System.out.println("Error opening file!");
System.exit(1);
}
//citation of idea for sorting method in 2D array: http://stackoverflow.com/questions/23283655/bubble-sort-on-2d-array-java
//I'm using bubble sort on a 2D array
//this is his code
/*
private static void bubblesort(Integer[] array) {
for (int i = 0; i < array.length; i++) {
for(int j = 0; j < array.length - 1; j++) {
if(array[j].compareTo(array[j+1]) > 0) {
swap(j, j+1, array);
}
}
}
}
private static void swap(Integer int1, Integer int2, Integer[] array) {
if(int1 == int2)return;
Integer temp = new Integer(array[int2]);
array[index2] = array[int1];
array[int1] = temp;
}
*/
//here's my idea for bubble sort on a 2D array
/*
for (int i = 0; i < numOfRows; i++){
for(int j = 0; j < numOfRows - 1; j++) {
if(table[j][0].compareTo(array[j+1][0]) > 0) {
swap(j, j+1, table);
}
}
//this didn't work well either
//Now, I have to try another for-loop
*/
//Count the number of lines in the file
int size_of_file = 0;
while (scanner.hasNextLine()){
scanner.nextLine();
size_of_file++;
}
table = new int[size_of_file][2];
//reset scanner
try{
file = new File("data.csv");
scanner = new Scanner( file );
}
catch(Exception e){
System.out.println("Error opening file!");
System.exit(1);
}
//save the title
String titleLine = scanner.nextLine();
System.out.println(titleLine);
//for each line in the file, store and total it.
numOfRows=0;
while (scanner.hasNextLine()){
String ln = scanner.nextLine();
String[] row = ln.split(",");
System.out.println(row[0] + ", " + row[1]);
if (contains(Integer.parseInt(row[0]))){
//This is the location in the table where the product id exists already.
int location = lookfor(Integer.parseInt(row[0]));
//add the units to what we have in the table
table[location][1] += Integer.parseInt(row[1]);
}
else{
table[numOfRows][0]= Integer.parseInt(row[0]);
table[numOfRows][1]= Integer.parseInt(row[1]);
numOfRows++;
}
}
//output
try{
PrintWriter output = new PrintWriter("output.csv");
output.println(titleLine);
for(int i=0;i<numOfRows;i++){
output.println(table[i][0] + "," + table[i][1]);
}
output.close();
}
catch(Exception e){
System.out.println("Error writing file");
}
}
}
I want to understand how to use FileReader better. I read a little bit about it here:
https://www.caveofprogramming.com/java/java-file-reading-and-writing-files-in-java.html
https://bytes.com/topic/java/answers/585814-reading-data-into-array-file
Although I don't think I understand from that how to store it into an array. Could someone explain how I can store values from FileReader class into an array? I want it in a 2D array where the number of rows is just however many product IDs I have and there is always 2 columns.
Excel File to read from:
Product ID Units
10002 4
10004 6
10008 2
10010 3
10010 3
output I get right now:
Product ID Units
10002 20
10004 72
10008 12
10010 37
10007 28
20003 42
30019 56
30020 29
10006 36
20005 32
etc.
I apologize if this update should be posted as a different question. Let me know so I can go by community standards. The piece of output I posted, you'll notice isn't sorted by productID. That's the last thing I want to do. Other than that, it basically works. I am apologizing in case someone wants to vote me down for not posting the answer, since technically it would be the same answer to the initial question. If this update should be a different thread, again, let me know and I'll make the edit.
been working on this program for a while and I think I've made much more progress. My java skills are not very good, but I think I'm close. Everything should compile without issue except for my "public void run" in my worker class. The program prompts the user for how many threads they want and then parses through a text file of random numbers to find all the prime numbers. My issue seems to be in the algorithm for the prime numbers. How do I write the algorithm so it parses the data down and finds the prime numbers?
I have posted the entire program below, but please see the worker class towards the bottom. Any help would be greatly appreciated in solving this issue. Thank you.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class PrimeNumbers{
public static void main(String[] args) throws IOException {
int[] numbers = new int[100000];
int count;
int index = 0;
String datafile = "dataset529.txt"; //string which contains datafile
String line; //current line of text file
try (BufferedReader br = new BufferedReader(new FileReader(datafile))) { //reads in the datafile
while ((line = br.readLine()) != null) { //reads through each line
numbers[index++] = Integer.parseInt(line); //pulls out the number of each line and puts it in numberset[]
}
}
System.out.println("How many threads would you like to use?");
Scanner scan = new Scanner(System.in);
int z = scan.nextInt();
Thread[] threads = new Thread[z]; //creates threads as per user
worker[] finder = new worker[z]; //assigns finder to each thread created
int range = numbers.length / z; //breaks up each worker into a section depending on thread count.
for (count = 0; count < z; count++) {
int startAt = count * range;
int endAt = startAt + range;
finder[count] = new worker(startAt, endAt, numbers);
}
for (count = 0; count < z; count++) { //moves to next thread
threads[count] = new Thread(finder[count]);
threads[count].start();
}
boolean processing = false;
do {
processing = false;
for (Thread t : threads) {
if (t.isAlive()) {
processing = true;
break;
}
}
} while (processing);
for (worker worker : finder) {
System.out.println("Max of thread is: " + worker.getPrime());
}
}
public static class worker implements Runnable {
private int start;
private int stop;
private int numberset[];
public worker(int start, int stop, int[] numberset) {
this.start = start;
this.stop = stop;
this.numberset = numberset;
}
#Override
public void run() {
for (int x = start; x < stop; x++) {
if (numberset[]%3 && != 1 && != 2 && !=3)
return prime
}
}
public int getPrime() {
return true
}
}
}
I've been working on getting this program to work. I'm having a little trouble getting the program to read the files I have created, census2000 and census2010. These contain the 50 states and their population in 2000 and 2010. I believe that the rest of my program is correct. I was told to use methods to find the smallest population, largest population and the average. Here is two lines from the 2000 file:
Alabama 4447100
Alaska 626932
Here is my program:
public static void main(String[] args) throws IOException {
String state = "";
int population = 0;
int p = 0, s = 0, pop = 0, stat = 0, populate = 0, sum = 0;
File f = new File("census2000.txt");
Scanner infile = new Scanner(f);
infile.useDelimiter("[\t|,|\n|\r]+");
while (infile.hasNext()) {
checksmall(p, s);
checklargest(pop, stat);
checkAverage(populate, sum);
population = infile.nextInt();
state = infile.next("/t");
System.out.println(state + "has" + population + "people");
}
System.out.println(state + "has smallest population of" + population);
prw.close();
}
public static boolean checksmall(int p, int s) {
boolean returnValue;
if (p < s) {
returnValue = true;
} else {
returnValue = false;
}
return (returnValue);
}
public static boolean checklargest(int pop, int stat) {
boolean returnVal;
if (pop > stat) {
returnVal = true;
} else {
returnVal = false;
}
return (returnVal);
}
public static int checkAverage(int populate, int sum) {
int retVal;
retVal = populate + sum;
return (retVal);
}
}
What am I doing wrong?
I believe the problem is here:
state = infile.next("/t");
I think what you're trying to do is skip a tab in the file and read the state? You could do that by reading in the line and then splitting the line using \t as the delimiter.
String line;
while (infile.hasNextLine()){
line = infile.nextLine();
String data[] = line.split("\\s+");
state = data[0];
population = Integer.parseInt(data[1]);
}
edit: also as the other answer points out, you're attempting to perform functions on the file's data before it's read.
You need to be calling checksmall, checklargest and checkAverage after/while the file is loaded.
I am having simple code of paralellizing QuickSort algorithm in Java, in run method I everytime create two seperate new threads for parallelizing processing of Array elements. But as it encounters join() statements for both created threads, threads never backs and halts on joins(), seems join() never releases them.
Below is the code.
class StartJoinQuickSort implements Runnable
{
private int m_Low, m_High;
private int[] m_Array = null;
private final static int NR_OF_VALUES = 10; // TOTAL_NO_VALUES
private int PivotElement;
private static Random m_random = new Random( );
public StartJoinQuickSort(int[] a_Array,int a_Low,int a_High)
{
this.m_Array = a_Array;
this.m_Low = a_Low;
this.m_High = a_High;
}
private void SwapArrayElements(int a_i,int a_j)
{
int temp = this.m_Array[a_i];
this.m_Array[a_i] = this.m_Array[a_j];
this.m_Array[a_j] = temp;
}// end of SwapArrayElements
private static int nextRandomFunctionValue(int aStart, int aEnd)
{
if ( aStart > aEnd )
{
throw new IllegalArgumentException("Start cannot exceed End.");
}
//get the range, casting to long to avoid overflow problems
long range = (long)aEnd - (long)aStart + 1;
// compute a fraction of the range, 0 <= frac < range
long fraction = (long)(range * m_random.nextDouble());
int randomNumber = (int)(fraction + aStart);
return randomNumber;
}// end of nextRandomFunctionValue
private static int[] GetArrayWithRandomValues()
{
int[] ArrayToBePopulatedWithRandomValues = new int[NR_OF_VALUES];
for(int index =0; index<NR_OF_VALUES;index++)
{
int RandomValue = StartJoinQuickSort.nextRandomFunctionValue(0,NR_OF_VALUES);
ArrayToBePopulatedWithRandomValues[index] = RandomValue;
}//end of for
return ArrayToBePopulatedWithRandomValues;
}//end of GetArrayWithRandomValues
private int middleIndex(int left, int right)
{
return left + (right - left) / 2;
}
public int Partition(int a_Start,int a_end)
{
// System.out.println("Partition ..thId : " + Thread.currentThread().getId());
int pivotIndex = 0;
int i = a_Start;
int j = a_end;
try
{
pivotIndex = middleIndex(a_Start , a_end);
this.PivotElement = this.m_Array[pivotIndex];
do
{
while(this.m_Array[i] < PivotElement )
i++;
if(j>0)
{
try
{
while( this.m_Array[j] > PivotElement )
j--;
}
catch(Exception ex){System.out.println(" j : " + j);}
}//end of if
if(i<=j)
{
SwapArrayElements(i,j);
// System.out.println("Swap .." + + Thread.currentThread().getId());
i++;
j--;
}//end of if
}while(i<=j);
}
catch(Exception except)
{
System.out.println("exception in Partition " + except);
}
return j;
}
public void run()
{
//System.out.println("in run..");
//System.out.println("after PARTITION");
StartJoinQuickSort oStartQuickSort_1 = null;
StartJoinQuickSort oStartQuickSort_2 = null;
if(this.m_Low < this.m_High )
{
int Index = Partition(this.m_Low,this.m_High);
Thread thPart_1 = new Thread ( new StartJoinQuickSort( this.m_Array,this.m_Low,Index ) );
Thread thPart_2 = new Thread ( new StartJoinQuickSort( this.m_Array,Index + 1,this.m_High ) );
thPart_1.start(); thPart_2.start();
//}//end of if
//if( Index + 1 < this.m_High)
//{
try
{
thPart_1.join(); thPart_2.join();
}catch (InterruptedException e) { e.printStackTrace();}
}
}//end of run
Regards
Usman
Hmmm, it is never a good idea to implement a recursive algorithm in parallel like this. You will end up creating a huge number of threads (exponential at every level) and will eventually oversubscribe the system.
The best idea is to have a cutoff point, which let's say is equal to the number of available cores. Then when the current level of recursion has a number of branches equal to the cutoff point switch to a sequential quicksort. Some very rough pseudocode of the flow:
parallel_quicksort(level, interval) {
// compute subintervals interval1, interval2
if(level < cutoff) {
spawn1: parallel_quicksort(level + 1, interval1);
spawn2: parallel_quicksort(level + 1, interval2);
join1();
join2();
} else {
quicksort(interval1);
quicksort(interval2);
}
}
Also have a look over this implementation to see if you've missed something: http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/quick/quicken.htm
What happens if you have e.g. low=0, high=1? If your Partition returns 1, you'll have an infinite loop of threads, right?
join() blocks if your thread doesn't finish. You need to determine why your threads are not finishing. Can you try debugging your program with a debugger?
Thanks all for your kind suggestions and advices.
I myself detected the problem. it was with Partition function which was not working fine, it was having some problems, I choose another one and it worked fine for me..
New Partition procedure is :
public int Partition(int[] a_Array, int a_Left, int a_Right)
{
// chose middle value of range for our pivot
int pivotValue = a_Array[middleIndex(a_Left, a_Right)];
--a_Left;
++a_Right;
while (true)
{
do
++a_Left;
while (a_Array[a_Left] < pivotValue);
do
--a_Right;
while (a_Array[a_Right] > pivotValue);
if (a_Left < a_Right)
SwapArrayElements(a_Left,a_Right);
else
{
return a_Right;
}
}
}