Confusing Behavior with Array Initialization -- Processing (Java) - java

I'm encountering some confusing behavior when trying to create an array of certain length. The length is obtained by a file read in the function getTermNums. When I try to create an array of this size, my code runs in a strange order, my i values are skewed, and the code generally doesn't run as intended. When I instead create an array of a set integer amount, the code runs as intended without error.
double[] terms;
int numTerms = getNumTerms(lines[0]);
terms = new double[numTerms];
int i = 1;
for (i = 1; i<terms.length; i++){
//terms[i] = calculateTerm(T, lines[i]);
}
the above code runs incorrectly.
double[] terms;
int numTerms = getNumTerms(lines[0]);
int myNum = 200;
terms = new double[myNum];
int i = 1;
for (i = 1; i<terms.length; i++){
//terms[i] = calculateTerm(T, lines[i]);
the above code runs correctly
int getNumTerms(String line){
int i = 60;
int j = 0;
char[] word;
word = new char[4];
int numTerms;
int numTermLen = 0;
while(new String(word).compareTo("TERM") != 0){
for (j=0; j<4; j++){
word[j] = line.charAt(i + j);
}
i++;
}
j = i - 3;
while( new Character(line.charAt(j)).equals(' ') == false){
numTermLen++;
j--;
}
j++;
println("i in here: ", i);
numTerms = Integer.parseInt(line.substring(j, j + numTermLen));
return numTerms;
}
this is the function that I'm calling to read the numterms for the size of the array in the first example that doesn't work correctly.
When I use the function call to set the size of array terms[], i starts at some value like 380, and the iteration through array lines[] begins somewhere in the middle of the array.
When I use the integer myNum to set the size of array terms[], i starts at 1, and the iteration through array lines[] begins at the first line, as intended.
Any explanation is appreciated! I'm new to coding in java and am confused by the source of this error.
Thanks in advance.

Without seeing the text it's tiresome to deduct where in your getNumTerms the error occurs.
You can make use of String's indexOf() to find the index of "TERM" and substring() to extract the String containing the integer value.
As far as I understand the ideal string would have "TERM" followed by an integer then a space character. If these items are found and the value fits within 32 bits you should be able to use something like this:
String line = "LINE START TERM-1238847 LINE END";
int getTerm(String line){
int result = Integer.MAX_VALUE;
final String SEARCH_TOKEN = "TERM";
// look for TERM token and remember index
int termIndex = line.indexOf(SEARCH_TOKEN);
// handle not found
if(termIndex < 0){
System.err.println("error: " + SEARCH_TOKEN + " not found in line");
return result;
}
// move index by the size of the token
termIndex += SEARCH_TOKEN.length();
int spaceIndex = line.indexOf(' ',termIndex);
if(spaceIndex < 0){
System.err.println("error: no SPACE found after " + SEARCH_TOKEN);
return result;
}
// chop string extracing between token end and first space encountered
String intString = line.substring(termIndex,spaceIndex);
// try to parse int handling error
try{
result = Integer.parseInt(intString);
}catch(Exception e){
System.err.println("error parsing integer from string " + intString);
e.printStackTrace();
}
return result;
}
System.out.println("parsed integer: " + getTerm(line));

Related

The content of an array is suspiciously doubled

I have been building an app that simulates the way a printer works. While designing the app, I have created the method below that splits a String content depending on the number of pages required. All the function seems to process the data correctly but I don't know why the method keeps doubling the content of an array it's supposed to return. Here's the method.
public ArrayList<String> splitContentIntoPages(){
int startPosition = 0;
int endIndexCalc = 0;
for(int i=0; i<getPages(); i++){
if((getContent().length() - endIndexCalc) >= getSize().getCapacity()){
System.out.println("Start " + startPosition);
endIndexCalc = startPosition + (getSize().getCapacity());
this.pagesContent.add(getContent().substring(startPosition, endIndexCalc));
startPosition += getSize().getCapacity();
System.out.println("End " + endIndexCalc);
}else{
this.pagesContent.add(getContent().substring(startPosition));
}
}
System.out.println("Size of the array " + this.pagesContent.size() + " getPages() " + getPages() + "");
for(int i=0; i<this.pagesContent.size(); i++){
System.out.println("The content :" + this.pagesContent.get(i));
}
return this.pagesContent;
}
I need some fresher eye on the issue. I have spent too much time on that trying to understand what's wrong. Thanks a lot guys!
Here's the version without debugs
public ArrayList<String> splitContentIntoPages(){
int startPosition = 0;
int endIndexCalc = 0;
for(int i=0; i<getPages(); i++){
if((getContent().length() - endIndexCalc) >= getSize().getCapacity()){
endIndexCalc = startPosition + (getSize().getCapacity());
this.pagesContent.add(getContent().substring(startPosition, endIndexCalc));
startPosition += getSize().getCapacity();
}else{
this.pagesContent.add(getContent().substring(startPosition));
}
}
return this.pagesContent;
}
this is the test entry extraxt. Basically the method aboe is processing the string of chars
that's the outcome. Basically, the string is supposed to be split into the number of pages - in this case 2. However, the array that is holding the split element of the strings holds 4 pieces of strings instead of two. It's all doubled. And I have no idea why
Either clear this.pagesContent at the beginning of splitContentIntoPages() or create new ArrayList<String> newA = new ArrayList<String>() at the beginning, add everythig to this new arrayList and at the end of splitContentIntoPages() do this.pagesContent = newA

Separating the int values based on the occurrance of sequence of the values in java?

i have an integer values as:
1299129912
i want to store it as
12
12
12
in the int v1,v2,v3;
i.e.,when ever 9909 occurs we need to separate the values individually. Is it possible in java. If so please anyone help me.
here is the code I'm trying
int l = 1299129912;
Pattern p = Pattern.compile("99");
Matcher m1 = p.matcher(l);
if (m1.matches()) {
System.out.println("\n");
}
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method matcher(CharSequence) in the type Pattern is not applicable for the arguments (int)
I suppose you already have the value as a String since 1234990912349909 is more that Integer.MAX_VALUE. Then you can split the string into String[] and do whatever you want with the separate values. E.g. call parseInt on each element.
String[] values = myIntString.split("9909");
for (String value: values) {
int v = Integer.parseInt(value);
}
Yes, it is very possible in java. Just convert the integer to a string and replace the 9909 with a space.
Example:
String s="1234990912349909";
s=s.replaceAll("9909","");
int a=Integer.parseInt(s);
System.out.println(a);
//output would be 12341234
If you know you are always going to have 3 integers named v1, v2, and v3 the following would work:
String[] numbers = l.toString().split("99");
int v1 = Integer.parseInt(numbers[0]);
int v2 = Integer.parseInt(numbers[0]);
int v3 = Integer.parseInt(numbers[0]);
However if you don't know in advance then it might be better to do it like this:
String[] numbers = l.toString().split("99");
int[] v = new int[numbers.length];
for (int i = 0; i < numbers.length; i++)
v[i] = Integer.parseInt(numbers[i]);
I found out this is the easiest way to show you how you can resolve your issue:
I included clear comments on every important step. Please check this:
int num = 1239012390;
// Convert int into a string
String str = String.valueOf(num);
// What separates the values
String toBremoved = "90";
String str1 = "";
// Declare a String array to store the final results
String[] finalStrings = new String[2];
// i will be used as an index
int i = 0;
do {
// Finds and separates the first value into another string
finalStrings[i] = str.substring(0, str.indexOf(toBremoved));
// removes the first number from the original string
str = str.replaceFirst(finalStrings[i], "");
// Remove the next separating value
str = str.replaceFirst(str.substring(str.indexOf(toBremoved), str.indexOf(toBremoved) + toBremoved.length()), "");
// increments the index
i++;
} while (str.indexOf(toBremoved) > 0); // keeps going for a new iteration if there is still a separating string on the original string
// Printing the array of strings - just for testing
System.out.println("String Array:");
for (String finalString : finalStrings) {
System.out.println(finalString);
}
// If you want to convert the values into ints you can do a standard for loop like this
// Lets store the results into an int array
int [] intResults = new int [finalStrings.length];
for (int j = 0; j < intResults.length; j++) {
intResults[j] = Integer.valueOf(finalStrings[j]);
}
// empty line to separate results
System.out.println();
// Printing the array of ints
System.out.println("int Array:");
for (int intResult : intResults) {
System.out.println(intResult);
}
Or in a simplified and more accurate way:
(you can use the example above if you need to understand how it can be done the long way)
int num = 1239012390;
String [] numbers = String.valueOf(num).split("90");
int num1 = Integer.parseInt(numbers[0]);
int num2 = Integer.parseInt(numbers[1]);
System.out.println("1st -> " + num1);
System.out.println("2nd -> " + num2);

Java - Reverse String null error

The input is meant to appear like this, example.
\n
Kazan R
\n
6789
\n
Nzk462
\n
However the output I receive looks like this
kzn462nullnzk
Why is this? and How can i solve it?
private void btnGenerateActionPerformed(java.awt.event.ActionEvent evt) {
secondname = JOptionPane.showInputDialog("Enter your surname:");
firstname = JOptionPane.showInputDialog("Enter your firstname:");
idno = JOptionPane.showInputDialog("Enter your idno:");
nametag = firstname.substring(0, 1);
initials = secondname + " " + nametag;
int randnum;
do {
randnum = (int) (Math.random() * 900) + 100;
} while (randnum % 2 != 0);
code = secondname.replaceAll("[aeiou || AEIOU](?!\\b)", "")+randnum ;
txaDisplay.append(initials + '\n' + idno.substring(6,10) + '\n' + code);
int length = secondname.length();
for (int i = length - 1; i >= 0; i--) {
reverse = reverse + secondname.charAt(i);
}
String end = reverse + code;
txaDisplay.append( reverse);
Why don't you use
new StringBuilder(secondname).reverse().toString()
to reverse your String? It's better, simple and more maintanable.
Get the character array from your source string
Create a new char array of same length
Start iterating from 0 to (sourceStringLength-1)
In each iteration, get the last character
from the end in your source array and populate in your new array
Create a new string from this new array
String source = "abcdefg";
char[] chars = source.toCharArray();
char[] reverseChars = new char[source.length()];
int len = source.length();
for(int i= 0; i < len; i++){
reverseChars[i] = chars[len-1-i];
}
String reverse = new String(reverseChars);
System.out.println(reverse);
Since You don't want to use StringBuilder/StringBuffer.
Try this
String reversedString="";
for(int i=inputString.length-1;i>=0;){
reversedString+=inputString.charAt(i--);
}
I think the problem is your definition of reverse, maybe you have something like:
String reverse;
Then you don't initialize your "reverse" so when your program makes the first concatenation in your loop, it looks like this:
reverse = null + secondname.charAt(i);
The null value is converted to a string so it can be visible in the output.
I hope this information helps you.
Good Luck.

Unable to convert to Int from String

I am working on a solution to the TSP problem. I have generated all the permutations of the String "123456", however, I need to convert this into an ArrayList of Integer like this [1,2,3,4,5,6]...[6,5,4,3,2,1]. I then store this into an ArrayList of ArrayLists. Once there I will be able to compare all of the cities that need to be traveled to.
When I run my code, I have a method to generate the permutation, then a method to change that permutation into an ArrayList of Integer. When I convert them, I get the exception java.lang.NumberFormatException: For input string: "". I don't know of any other way to get the String to Integer
Here is my code.
public static String permute(String begin, String string){
if(string.length() == 0){
stringToIntArray(begin+string);
return begin + string + " ";
}
else{
String result = "";
for(int i = 0; i < string.length(); ++i){
String newString = string.substring(0, i) + string.substring(i+1, string.length());;
result += permute(begin + string.charAt(i), newString);
}
stringToIntArray(result);
return result;
}
}
public static void stringToIntArray(String s){
ArrayList<Integer> perm = new ArrayList<Integer>();
String [] change = s.split("");
for(int i = 0; i < 7; ++i){
int integer = Integer.parseInt(change[i]);
System.out.println(integer);
}
}
public static void main(String[] args) {
permute("", "123456");
}
These lines
String [] change = s.split("");
for(int i = 0; i < 7; ++i){
int integer = Integer.parseInt(change[i]);
System.out.println(integer);
}
Given a String like "12345", when you split it on nothing, it will separate every character. Giving you an array with ["","1","2","3","4","5"]. Since the empty String "" is not a Number, you will get the NumberFormatException. You could change your index i to start at 1 so as to ignore that first empty String.
The split method, when splitting on "", produces an empty string as the first element of the array, so you need to start iterating from i = 1.
Also, it would be safer to stop the iteration at change.length to make sure you process all characters when there are more than 6, and don't go out of bounds if there are fewer.
String [] change = s.split("");
for(int i = 1; i < change.length; ++i){ // ignore first element
int integer = Integer.parseInt(change[i]);
System.out.println(integer);
}

Optimizing Project Euler #22

Thanks in advance.
I just solved Project Euler #22, a problem involving reading about 5,000 lines of text out of a file and determining the value of a specific name, based on the sum of that Strings characters, and its position alphabetically.
However, the code takes about 5-10 seconds to run, which is a bit annoying. What is the best way to optimize this code? I'm currently using a Scanner to read the file into a String. Is there another, more efficient way to do this? (I tried using a BufferedReader, but that was even slower)
public static int P22(){
String s = null;
try{
//create a new Scanner to read file
Scanner in = new Scanner(new File("names.txt"));
while(in.hasNext()){
//add the next line to the string
s+=in.next();
}
}catch(Exception e){
}
//this just filters out the quotation marks surrounding all the names
String r = "";
for(int i = 0;i<s.length();i++){
if(s.charAt(i) != '"'){
r += s.charAt(i);
}
}
//splits the string into an array, using the commas separating each name
String text[] = r.split(",");
Arrays.sort(text);
int solution = 0;
//go through each string in the array, summing its characters
for(int i = 0;i<text.length;i++){
int sum = 0;
String name = text[i];
for(int j = 0;j<name.length();j++){
sum += (int)name.charAt(j)-64;
}
solution += sum*(i+1);
}
return solution;
}
If you're going to use Scanner, why not use it for what it's supposed to do (tokenisation)?
Scanner in = new Scanner(new File("names.txt")).useDelimiter("[\",]+");
ArrayList<String> text = new ArrayList<String>();
while (in.hasNext()) {
text.add(in.next());
}
Collections.sort(text);
You do not need to strip quotes, or split on commas - Scanner does it all for you.
This snippet, including java startup time, executes in 0.625s (user time) on my machine. I suspect it should be a bit faster than what you were doing.
EDIT OP asked what the string passed to useDelimiter was. It's a regular expression. When you strip out the escaping required by Java to include a quote character into a string, it's [",]+ - and the meaning is:
[...] character class: match any of these characters, so
[",] match a quote or a comma
...+ one or more occurence modifier, so
[",]+ match one or more of quotes or commas
Sequences that would match this pattern include:
"
,
,,,,
""",,,",","
and indeed ",", what was what we were going after here.
I suggest you to run your code with profiler. It allows you to understand, what part is really slow (IO/computations etc). If IO is slow, check for NIO: http://docs.oracle.com/javase/1.4.2/docs/guide/nio/.
Appending strings in a loop with '+', like you do here:
/* That's actually not the problem since there is only one line. */
while(in.hasNext()){
//add the next line to the string
s+=in.next();
}
is slow, because it has to create a new string and copy everything around in each iteration. Try using a StringBuilder,
StringBuilder sb = new StringBuilder();
while(in.hasNext()){
sb.append(in.next());
}
s = sb.toString();
But, you shouldn't really read the file contents into a String, you should create a String[] or an ArrayList<String> from the file contents directly,
int names = 5000; // use the correct number of lines in the file!
String[] sa = new String[names];
for(int i = 0; i < names; ++i){
sa[i] = in.next();
}
However, upon checking, it turns out that the file does not contain about 5000 lines, rather, it is all on a single line, so your big problem is actually
/* This one is the problem! */
String r = "";
for(int i = 0;i<s.length();i++){
if(s.charAt(i) != '"'){
r += s.charAt(i);
}
}
Use a StringBuilder for that. Or, make your Scanner read until the next ',' and read directly into an ArrayList<String> and just remove the double quotes from each single name in the ArrayList.
5+ seconds is quite slow for this problem. My entire web application (600 Java classes) compiles in four seconds. The root of your problem is probably the allocation of a new String for every character in the file: r += s.charAt(i)
To really speed this up, you should not use Strings at all. Get the file size, and read the whole thing into a byte array in a single I/O call:
public class Names {
private byte[] data;
private class Name implements Comparable<Name> {
private int start; // index into data
private int length;
public Name(int start, int length) { ...; }
public int compareTo(Name arg0) {
...
}
public int score()
}
public Names(File file) throws Exception {
data = new byte[(int) file.length()];
new FileInputStream(file).read(data, 0, data.length);
}
public int score() {
SortedSet<Name> names = new ...
for (int i = 0; i < data.length; ++i) {
// find limits of each name, add to the set
}
// Calculate total score...
}
}
Depending on the application, StreamTokenizer is often measurably faster than Scanner. Examples comparing the two may be found here and here.
Addendum: Euler Project 22 includes deriving a kind of checksum of the characters in each token encountered. Rather than traversing the token twice, a custom analyzer could combine the recognition and calculation. The result would be stored in a SortedMap<String, Integer> for later iteration in finding the grand total.
An obtuse solution which may find interesting.
long start = System.nanoTime();
long sum = 0;
int runs = 10000;
for (int r = 0; r < runs; r++) {
FileChannel channel = new FileInputStream("names.txt").getChannel();
ByteBuffer bb = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
TLongArrayList values = new TLongArrayList();
long wordId = 0;
int shift = 63;
while (true) {
int b = bb.remaining() < 1 ? ',' : bb.get();
if (b == ',') {
values.add(wordId);
wordId = 0;
shift = 63;
if (bb.remaining() < 1) break;
} else if (b >= 'A' && b <= 'Z') {
shift -= 5;
long n = b - 'A' + 1;
wordId = (wordId | (n << shift)) + n;
} else if (b != '"') {
throw new AssertionError("Unexpected ch '" + (char) b + "'");
}
}
values.sort();
sum = 0;
for (int i = 0; i < values.size(); i++) {
long wordSum = values.get(i) & ((1 << 8) - 1);
sum += (i + 1) * wordSum;
}
}
long time = System.nanoTime() - start;
System.out.printf("%d took %.3f ms%n", sum, time / 1e6);
prints
XXXXXXX took 27.817 ms.

Categories

Resources