Sorting doubles in java - java

import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader in = new BufferedReader(new FileReader(new File(args[0])));
String line;
while ((line = in.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line);
int len = st.countTokens();
Double[] seq = new Double[len];
for (int i = 0; i < len; i++)
seq[i] = Double.parseDouble(st.nextToken());
Arrays.sort(seq);
for (int i = 0; i < len; i++) {
if (i > 0) System.out.print(" ");
System.out.print(seq[i]);
} System.out.print("\n");
}
}
}
So I'm trying to solve this CodeEval problem (https://www.codeeval.com/open_challenges/91/) and my solution is not getting through all the test cases. I think my method of output is correct (spaces between numbers, trailing newline). I can't figure out what may be going on in the sorting or anywhere else.
The solution is apparently not correct when using floats either.

I also think this is a printing problem. The output seems to require exactly 3 decimal places on each number, based on the sample I/O. But, if you print out a double like 70.920 (one of the example inputs) it will display as 70.92.
double d = 70.920;
System.out.println(d);
System.out.printf("%.3f", d); // <-- try this
70.92
70.920
Notice how the second output is consistent with the format of the sample output whereas the first is not.

You may be sorting correctly but printing incorrectly. Decimal numbers are represented approximately. The runtime attempts to show them in the short format, but that is not guaranteed.
All the examples they gave should work, but who knows what the test suite does in the background.

I would use double not Double and I would only sort the values after reading the all, not after every line.
Perhaps some inputs have more than one line?

Related

Using Scanner and Arrays's to add BigInts

This is a project from school, but i'm only asking for help in the logic on one small part of it. I got most of it figured out.
I'm being given a file with lines of string integers, for example:
1234 123
12 153 23
1234
I am to read each line, compute the sum, and then go to the next one to produce this:
1357
188
1234
I'm stuck on the scanner part.
public static void doTheThing(Scanner input) {
int[] result = new int[MAX_DIGITS];
while(input.hasNextLine()) {
String line = input.nextLine();
Scanner linesc = new Scanner(line);
while(linesc.hasNext()) {
String currentLine = linesc.next();
int[] currentArray = convertArray(stringToArray(currentLine));
result = addInt(result, currentArray);
}
result = new int[MAX_DIGITS];
}
}
In a nutshell, I want to grab each big integer, put it an array of numbers, add them, and then i'll do the rest later.
What this is doing it's basically reading all the lines and adding everything and putting it into a single array.
What i'm stuck on is how do I read each line, add, reset the value to 0, and then read the next line? I've been at this for hours and i'm mind stumped.
Edit 01: I realize now that I should be using another scanner to read each line, but now i'm getting an error that looks like an infinite loop?
Edit 02: Ok, so after more hints and advice, I'm past that error, but now it's doing exactly what the original problem is.
Final Edit: Heh....fixed it. I was forgetting to reset the value to "0" before printing each value. So it makes sense that it was adding all of the values.
Yay....coding is fun....
hasNext method of the Scanner class can be used to check if there is any data available in stream or not. Accordingly, next method used to retrieve next continuous sequence of characters without white space characters. Here use of the hasNext method as condition of if doesn't make any sense as what you want is to check if the there are any numerical data left in the current line. You can use next(String pattern).
In addition, you can try this solution even though it is not optimal solution...
// In a loop
String line = input.nextLine(); //return entire line & descard newline character.
String naw[] = line.split(" "); //split line into sub strings.
/*naw contains numbers of the current line in form of string array.
Now you can perfom your logic after converting string to int.*/
I would also like to mention that it can easily & efficiently be done using java-8 streams.
An easier approach would be to abandon the Scanner altogether, let java.nio.io.Files to the reading for you and then just handle each line:
Files.lines(Paths.get("/path/to/my/file.txt"))
.map(s -> Arrays.stream(s.split("\\s+")).mapToInt(Integer::parseInt).sum())
.forEach(System.out::println);
If i were you i would be using the BufferedReader insted of the Scanner like this:
BufferedReader br = new BufferedReader(new FileReader("path"));
String line = "";
while((line = br.readLine()) != null)
{
int sum = 0;
String[] arr = line.split(" ");
for(String num : arr)
{
sum += Integer.parseInt(num);
}
System.out.println(sum);
}
Considering the level you're on, I think you should consider this solution. By using only the scanner, you can split the lines into an array of tokens, then iterate and sum the tokens by parsing them and validating that they're not empty.
import java.util.*;
class SumLines {
public static void main(String[] args) {
Scanner S = new Scanner(System.in);
while(S.hasNext()) {
String[] tokens = S.nextLine().split(" ");
int sum = 0;
for(int i = 0; i < tokens.length; i++) {
if(!tokens[i].equals("")) sum += Integer.parseInt(tokens[i]);
}
System.out.println(sum);
}
}
}

Separating an unknown amount of hyphens in java?

Good day, guys,
I'm working on a program which requires me to input a name (E.g Patrick-Connor-O'Neill). The name can be composed of as many names as possible, so not necessarily restricted to solely 3 as seen in the example above.But the point of the program is to return the initials back so in this case PCO. I'm writing to ask for a little clarification. I need to separate the names out from the hyphens first, right? Then I need to take the first character of the names and print that out?
Anyway, my question is basically how do I separate the string if I don't know how much is inputted? I get that if it's only like two terms I would do:
final String s = "Before-After";
final String before = s.split("-")[0]; // "Before"
I did attempt to do the code, and all I have so far is:
import java.util.Scanner;
public class main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String input = scan.nextLine();
String[] x = input.split("-");
int u =0;
for(String i : x) {
String y = input.split("-")[u];
u++;
}
}
}
I'm taking a crash course in programming, so easy concepts are hard for me.Thanks for reading!
You don't need to split it a second time. By doing String[] x = input.split("-"); you have an Array of Strings. Now you can iterate over them which you already do with the enhanced for loop. It should look like this
String[] x = input.split("-");
String initials = "";
for (String name : x) {
initials += name.charAt(0);
}
System.out.println(initials);
Here are some Java Docs for the used methods
String#split
String#charAt
Assignment operator +=
You can do it without splitting the string by using String.indexOf to find the next -; then just append the subsequent character to the initials:
String initials = "" + input.charAt(0);
int next = -1;
while (true) {
next = input.indexOf('-', next + 1);
if (next < 0) break;
initials += input.charAt(next + 1);
}
(There are lots of edge cases not handled here; omitted to get across the main point of the approach).
In your for-each loop append first character of all the elements of String array into an output String to get the initials:
String output = "";
for(String i : x) {
output = output + y.charAt(0);
}
This will help.
public static void main(String[] args) {
String output = "";
String input = "Patrick-Connor-O'Neil-Saint-Patricks-Day";
String[] brokenInput = input.split("-");
for (String temp : brokenInput) {
if (!temp.equals(""))
output = output + temp.charAt(0);
}
System.out.println(output);
}
You could totally try something like this (a little refactor of your code):
import java.util.Scanner;
public class main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String input = "";
System.out.println("What's your name?");
input = scan.nextLine();
String[] x = input.split("-");
int u =0;
for(String i : x) {
String y = input.split("-")[u];
u++;
System.out.println(y);
}
}
}
I think it's pretty easy and straightforward from here if you want to simply isolate the initials. If you are new to Java make sure you use a lot of System.out since it helps you a lot with debugging.
Good coding.
EDIT: You can use #Mohit Tyagi 's answer with mine to achieve the full thing if you are cheating :P
This might help
String test = "abs-bcd-cde-fgh-lik";
String[] splitArray = test.split("-");
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < splitArray.length; i++) {
stringBuffer.append(splitArray[i].charAt(0));
}
System.out.println(stringBuffer);
}
Using StringBuffer will save your memory as, if you use String a new object will get created every time you modify it.

Java, string difference algorithm

I would like to get a feedback about the code below. Is there any way to improve it's performance? Maybe you know input values that might print bad output? The idea of the code is to count unique characters from s2 that are not listed in s1.
Ideone.com URL.
The code:
class Combine {
public static void main(String[] args) throws IOException {
BufferedReader bi = new BufferedReader(new InputStreamReader(System.in));
String s1 = bi.readLine();
String s2 = bi.readLine();
String usedCharacters = "";
for(int i = 0; i < s2.length(); i++) {
String c = Character.toString(s2.charAt(i));
if(!usedCharacters.contains(c) && !s1.contains(c))
usedCharacters += c;
}
System.out.println(usedCharacters.length());
}
}
I think this is fairly well optimized but you should probably check for null, as it will fail if you pass it null values.
I think this performance is good enough and any improvements would not make a sensitive difference.
I think you should try to iterate over the larger or the smaller String (measure the time overhead) - that's where you can save some CPU time.
If your input is relatively small (eg typed by a user on the console) then I see no performance problem with your solution (apart from the null checks as suggested by another answer).
If the input is large, eg redirected files on the command line of megabytes or more then I think your solution will yield O(n^2) run time performance as it iterates though s2 and the contains method call will also iterate across the whole string.
An alternative algorithm would be to sort the two input strings and then iterate across them to count the differences. That would result in O(n log n) performance.
Didn't try it but here's an idea:
class Combine {
public static void main(String[] args) throws IOException {
BufferedReader bi = new BufferedReader(new InputStreamReader(System.in));
String s1 = bi.readLine();
String s2 = bi.readLine();
int count = 0;
for(char c : new HashSet<Char>(s2.toCharArray())) {
if(s1.contains(c)) count++
}
System.out.println(count);
}
}

Java: How come I can't output my sorted values from a csv file?

I have a program that reads from a csv file full of peoples last names, first names, and birth years, assigns them into a special class array, and then gets sorted according to their last name. I believe that my code is working, so all I have to do to verify this is output the list and see if indeed all of the people were sorted by their last name. However, I am having trouble finding the right syntax to do this.
Here is the code of my Main.java, where I think the issue must be.
package project_1_sorting;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main
{
public static void main(String[] args) throws IOException {
// open file input stream
BufferedReader reader = new BufferedReader(new FileReader(
"C:\\Users\\Owner\\Desktop\\Data 18k.csv")); // double check where this is trying to read it from
// read file line by line
String line = null;
Scanner scanner = null;
int index = 0;
Human[] pplArray = new Human[18000];
int i = 0;
while ((line = reader.readLine()) != null) {
Human ppl = new Human();
scanner = new Scanner(line);
scanner.useDelimiter(",");
while (scanner.hasNext()) {
String data = scanner.next();
if (index == 0)
ppl.setLastName(data);
else if (index == 1)
ppl.setFirstName(data);
else if (index == 2)
ppl.setBirthYear(data);
else
System.out.println("invalid data::" + data);
index++;
}
ppl.setKey(0); //change this for later things, you can use loop
ppl.setOrder(0); //change this to 1 if you want to invert the list of people
index = 0;
pplArray[i] = ppl;
i++;
System.out.println(pplArray);
}
//close reader
reader.close();
System.out.println(pplArray); // create
Selection_Sort selection = new Selection_Sort();
for (int j = 0; j < 18000; j++)
{
System.out.println(pplArray[j]);
}
}
}
So I was expecting this to output a giant list of all of my people from the csv file(ordered), with all of their info in the same format as they originally were, right. (one person per row, with 3 collumns for their 3 strings). However this is what I got instead:
run:
Test
17
true
0.142857
BUILD SUCCESSFUL (total time: 0 seconds)
I am not sure what the meaning of this is. It would seem that its doing something completely unrelated to what I am trying to do. This is the only project that I have open in NetBeans, so it must be generated from my functions, right? If anyone knows what this is all about, please let me know. If there is nothing else wrong with this Main.java, I can post my other .java files.
One thing I did notice was that, even when I commented out my selection sort function call, and all of the printline commands in this .java file, the same output was displayed on my screen.
Please let me know what you think.
You have a few issues
The statements
Selection_Sort selection = new Selection_Sort();
for (int i = 0; i < 18000; i++)
{
System.out.println(pplArray[i]);
}
should be in the main18k method rather than the class block
Then the variable i has already been used so you need to use a different variable name either of those places where its used
for (int j = 0; j < 18000; j++)
Lastly use main instead of main18k so the application has a valid entry point
You have not close the bracket properly.Also variable i is used twice in the main method.So change the variable name.
Remove bracket before line Selection_Sort selection = new Selection_Sort();
Change the variable i to j and code is as below :
for (int j = 0; j < 18000; j++)
{
System.out.println(pplArray[j]);
}

Interview Coding Java Sorting

Write a java program to read input from a file, and then sort the characters within each word. Once you have done that, sort all the resulting words in ascending order and finally followed by the sum of numeric values in the file.
Remove the special characters and stop words while processing the data
Measure the time taken to execute the code
Lets Say the content of file is: Sachin Tendulkar scored 18111 ODI runs and 14692 Test runs.
Output:achins adeklnrtu adn cdeors dio estt nrsu nrsu 32803
Time Taken: 3 milliseconds
My Code takes 15milliseconds to execute.....
please suggest me any fast way to solve this problem...........
Code:
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.*;
public class Sorting {
public static void main(String[] ags)throws Exception
{
long st=System.currentTimeMillis();
int v=0;
List ls=new ArrayList();
//To read data from file
BufferedReader in=new BufferedReader(
new FileReader("D:\\Bhive\\File.txt"));
String read=in.readLine().toLowerCase();
//Spliting the string based on spaces
String[] sp=read.replaceAll("\\.","").split(" ");
for(int i=0;i<sp.length;i++)
{
//Check for the array if it matches number
if(sp[i].matches("(\\d+)"))
//Adding the numbers
v+=Integer.parseInt(sp[i]);
else
{
//sorting the characters
char[] c=sp[i].toCharArray();
Arrays.sort(c);
String r=new String(c);
//Adding the resulting word into list
ls.add(r);
}
}
//Sorting the resulting words in ascending order
Collections.sort(ls);
//Appending the number in the end of the list
ls.add(v);
//Displaying the string using Iteartor
Iterator it=ls.iterator();
while(it.hasNext())
System.out.print(it.next()+" ");
long time=System.currentTimeMillis()-st;
System.out.println("\n Time Taken:"+time);
}
}
Use indexOf() to extract words from your string instead of split(" "). It improves performance.
See this thread: Performance of StringTokenizer class vs. split method in Java
Also, try to increase the size of the output, copy-paste the line Sachin Tendulkar scored 18111 ODI runs and 14692 Test runs. 50,000 times in the text file and measure the performance. That way, you will be able to see considerable time difference when you try different optimizations.
EDIT
Tested this code (used .indexOf())
long st = System.currentTimeMillis();
int v = 0;
List ls = new ArrayList();
// To read data from file
BufferedReader in = new BufferedReader(new FileReader("D:\\File.txt"));
String read = in.readLine().toLowerCase();
read.replaceAll("\\.", "");
int pos = 0, end;
while ((end = read.indexOf(' ', pos)) >= 0) {
String curString = read.substring(pos,end);
pos = end + 1;
// Check for the array if it matches number
try {
// Adding the numbers
v += Integer.parseInt(curString);
}
catch (NumberFormatException e) {
// sorting the characters
char[] c = curString.toCharArray();
Arrays.sort(c);
String r = new String(c);
// Adding the resulting word into TreeSet
ls.add(r);
}
}
//sorting the list
Collections.sort(ls);
//adding the number
list.add(v);
// Displaying the string using Iteartor
Iterator<String> it = ls.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
long time = System.currentTimeMillis() - st;
System.out.println("\n Time Taken: " + time + " ms");
Performance using 1 line in file
Your code: 3 ms
My code: 2 ms
Performance using 50K lines in file
Your code: 45 ms
My code: 32 ms
As you see, the difference is significant when the input size increases. Please test it on your machine and share results.
The only thing I see: the following line is needlessly expensive:
System.out.print(it.next()+" ");
That's because print is inefficient, due to all the flushing going on. Instead, construct the entire string using a string builder, and then reduce to one call of print.
I removed the list and read it using Arrays only, In my machine the code to 6 msec with your code, by using Arrays only it taking 4 to 5 msec. Run this code in your machine and let me know the time.
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.*;
public class Sorting {
public static void main(String[] ags)throws Exception
{
long st=System.currentTimeMillis();
int v=0;
//To read data from file
BufferedReader in=new BufferedReader(new FileReader("File.txt"));
String read=in.readLine().toLowerCase();
//Spliting the string based on spaces
String[] sp=read.replaceAll("\\.","").split(" ");
int j=0;
for(int i=0;i<sp.length;i++)
{
//Check for the array if it matches number
if(sp[i].matches("(\\d+)"))
//Adding the numbers
v+=Integer.parseInt(sp[i]);
else
{
//sorting the characters
char[] c=sp[i].toCharArray();
Arrays.sort(c);
read=new String(c);
sp[j]= read;
j++;
}
}
//Sorting the resulting words in ascending order
Arrays.sort(sp);
//Appending the number in the end of the list
//Displaying the string using Iteartor
for(int i=0;i<j; i++)
System.out.print(sp[i]+" ");
System.out.print(v);
st=System.currentTimeMillis()-st;
System.out.println("\n Time Taken:"+st);
}
}
I ran the same code using a PriorityQueue instead of a List. Also, as nes1983 suggested, building the output string first, instead of printing every word individually helps reduce the runtime.
My runtime after these modifications was definitely reduced.
I have modified the code like this further by including #Teja logic as well and resulted in 1 millisecond from 2 millisescond:
long st=System.currentTimeMillis();
BufferedReader in=new BufferedReader(new InputStreamReader(new FileInputStream("D:\\Bhive\\File.txt")));
String read= in.readLine().toLowerCase();
String[] sp=read.replaceAll("\\.","").split(" ");
int v=0;
int len = sp.length;
int j=0;
for(int i=0;i<len;i++)
{
if(isNum(sp[i]))
v+=Integer.parseInt(sp[i]);
else
{
char[] c=sp[i].toCharArray();
Arrays.sort(c);
String r=new String(c);
sp[j] = r;
j++;
}
}
Arrays.sort(sp, 0, len);
long time=System.currentTimeMillis()-st;
System.out.println("\n Time Taken:"+time);
for(int i=0;i<j; i++)
System.out.print(sp[i]+" ");
System.out.print(v);
Wrote small utility to perform for checking a string contains number instead of regular expression:
private static boolean isNum(String cs){
char [] s = cs.toCharArray();
for(char c : s)
{
if(Character.isDigit(c))
{
return true;
}
}
return false;
}
Calcluate time before calling System.out operation as this one is blocking operation.

Categories

Resources