Split more complicated String to get the numbers in Java - java

I have a given String that represents the age in format:
"YY yr MM mo" or
"Y yr MM mo" or
"YY yr M mo" or
"Y yr M mo"
where YY/Y represent years (example: 5 or 44) and MM/M represent months (example: 2 or 11). Just to be clear, I give example of a String pAge = "11 yr 5 mo" or String pAge = "4 yr 10 mo".
Now I'd like to split this String and print it only as a numbers in a two separate text fields that represents years and months in age.
To get years I writing a function:
String arr[] = pAge.split(" ", 2);
return arr[0];
And another function to get months:
int i = pAge.indexOf("yr", pAge.indexOf(" ") + 1);
int k = pAge.indexOf(" ", pAge.indexOf(" ") + 4);
String s = pAge.substring(i, k);
return s.substring(s.lastIndexOf(" ") + 1);
So, first method looks nice and it's easy but is there is any simpler way to write the second function? Both are working well and giving a correct output.

All the 4 cases given by you are the same. All of them have 4 parts delimited by a space.
This means that you can use .split() for all 4 cases:
String[] tokens = pAge.split(" ");
int years = Integer.parseInt(tokens[0]); //get first token
int months = Integer.parseInt(tokens[2]); //get third token

How about this untested pseudo code:
String tokens[] = pAge.split(" ");
if (tokens.length != 4 || tokens[1] != "yr" || tokens[3] != "mo")
throw new SyntaxError("pAge is not 'N yr N mo'");
String years = tokens[0];
String month = tokens[2];

Related

How to split a string into 2 equal parts in Java

I want to divide a string like this:
String = "Titanic";
into two strings of equal length, and if it isn't divisible by 2 it will have 1 letter or extra on first or second part. like this
//if dividle by 2
Str1 = "BikG";
Str2 = "amer";
//if it isnt dividle by 2
Str1 = "Tita";
Str2 = "nic";
You can do it for example like this:
String base = "somestring";
int half = base.length() % 2 == 0 ? base.length()/2 : base.length()/2 + 1;
String first = base.substring(0, half);
String second = base.substring(half);
Simply when n is the string's length, if n is divisible by 2, split the string in n/2, otherwise split in n/2 + 1 so that first substring is one character longer than second.
What do you do to divide an odd number e.g. 15 with the same requirement?
You store the result of 15 / 2 into an int variable say
int half = 15 / 2
which gives you 7. As per your requirement, you need to add 1 to half to make the first half (i.e. 8) and the remaining half will be 15 - 8 = 7.
On the other hand, in case of an even number, you simply divide it by 2 to have two halves.
You have to apply the same logic in the case of a String as well. Given below is a demo:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int half;
String str1 = "Titanic";
half = str1.length() / 2;
String str1Part1 = str1.substring(0, half + 1);
String str1Part2 = str1.substring(half + 1);
System.out.println(str1Part1 + ", " + str1Part2);
String str2 = "HelloWorld";
half = str2.length() / 2;
String str2Part1 = str2.substring(0, half);
String str2Part2 = str2.substring(half);
System.out.println(str2Part1 + ", " + str2Part2);
Scanner in = new Scanner(System.in);
do {
System.out.print("Enter a string: ");
String str = in.nextLine();
half = str.length() / 2;
System.out.println(str.length() % 2 == 1 ? str.substring(0, half + 1) + ", " + str.substring(half + 1)
: str.substring(0, half) + ", " + str.substring(half));
System.out.print("Enter Y to continue or any input to exit: ");
} while (in.nextLine().toUpperCase().equals("Y"));
}
}
A sample run:
Tita, nic
Hello, World
Enter a string: Arvind
Arv, ind
Would you like to continue? [Y/N]: y
Enter a string: Kumar
Kum, ar
Would you like to continue? [Y/N]: Y
Enter a string: Avinash
Avin, ash
Would you like to continue? [Y/N]: n
Note:
% is a modulo operator.
Check String substring​(int beginIndex, int endIndex) and String substring​(int beginIndex) to learn more about substring functions of String.
Check https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html to learn about the ternary operator.
You could use String.substring() for this purpose:
String s = "Titanic";
int half = (s.length()+1)/2;
String part1 = s.substring(0, half);
String part2 = s.substring(half);
System.out.println(part1); // Prints: Tita
System.out.println(part2); // Prints: nic
Here (s.length()+1)/2 will auto-truncate 0.5 if it occurs because the division is between ints.

Sum 2 string numbers [duplicate]

This question already has answers here:
How can I find the sum of two numbers which are in String variables?
(10 answers)
Closed 4 years ago.
I've looked it up, but couldn't get a real answer to that. So I want to know how to sum up 2 string numbers together.
for example:
String a = "8";
String b = "1";
I want to sum both of them to "9". Is that possible?
Thanks.
edit - that is the code Im trying to use:
String num = Integer.toString(i);
String doubleNumber = Integer.toString(i * i);
int length = doubleNumber.length();
String firstNumber;
String secondNumber;
for (int q = 0; q < length; q++) {
firstNumber = doubleNumber.substring(0, Math.min(doubleNumber.length(), q+1));
secondNumber = doubleNumber.substring(q+1, Math.min(doubleNumber.length(), doubleNumber.length()));
String result = String.valueOf(Integer.parseInt(firstNumber) + Integer.parseInt(secondNumber));
if(num.equals(result)) {
isKaprekar = true;
}
}
edit 2 - I have no idea how, but I opened another class, pasted the same code, and it just magically worked. It makes 0 sense, cause its the same project, everything is the same, but it works now, so I don't care. Thanks everyone for the help!
There is a method called Integer#parseInt(String) which returns an int representation of a given String (if possible):
String a = "8";
String b = "1";
int sum = Integer.parseInt(a) + Integer.parseInt(b);
If you want to change it back to a String, use String#valueOf(int):
String s = String.valueOf(sum);
I'd parse them to ints, add them, and then convert the result back to a string:
String result = String.valueOf(Integer.parseInt(a) + Integer.parseInt(b));
You need to convert both to Integers:
String a = "8";
String b = "1";
int sum = Integer.parseInt(a, 10) + Integer.parseInt(b, 10);
The second argument of Integer.parseInt() is the radix, which tells which number base to use. You can leave this argument out altogether and it will default to using a radix of 10:
int sum = Integer.parseInt(a) + Integer.parseInt(b);
If you want to convert them back to a string, just pass the value into String.valueOf():
String sumString = String.valueOf(sum);
Do this:
String a = "8";
String b = "1";
String sum = String.valueOf(Integer.parseInt(a)
+Integer.parseInt(b));
//printing sum
System.out.println(sum);
Parse the string to int using Integer.parseInt(string)and add them as normal integers.
For example :
String result = String.valueOf(Integer.parseInt(a) + Integer.parseInt(b));
should give you the desired string value as "9"

How to convert a location in Degrees Minutes Seconds represented as a String to Double

My app lets users search a location and one of the queries I got was
"78°14'09"N 15°29'29"E"
Obviously the user wants to go to this location.
First how do I check if this string fits the decimal format correctly. Then how do I convert it to double format?
double latitude = convertToDouble("78°14'09"N")
I searched here on stackoverflow but they are all looking for the opposite: double to decimal.
78°14'09"N 15°29'29"E
First how do I check if this string fits the decimal format correctly. Then how do I convert it to double format?
The string is not in decimal (degrees) format. It is in degrees, minutes, and seconds, which is more or less the opposite of decimal degrees format. I therefore interpret you to mean that you want to test whether the string is in valid D/M/S format, and if so, to convert it to decimal degrees, represented as a pair of doubles.
This is mostly a parsing problem, and regular expressions are often useful for simple parsing problems such as this one. A suitable regular expression can both check the format and capture the numeric parts that you need to extract. Here is one way to create such a pattern:
private final static Pattern DMS_PATTERN = Pattern.compile(
"(-?)([0-9]{1,2})°([0-5]?[0-9])'([0-5]?[0-9])\"([NS])\\s*" +
"(-?)([0-1]?[0-9]{1,2})°([0-5]?[0-9])'([0-5]?[0-9])\"([EW])");
That's a bit dense, I acknowledge. If you are not familiar with regular expressions then this is no place for a complete explanation; the API docs for Pattern provide an overview, and you can find tutorials in many places. If you find that your input matches this pattern, then not only have you verified the format, but you have also parsed out the correct pieces for the conversion to decimal degrees.
The basic formula is decimal = degrees + minutes / 60 + seconds / 3600. You have the additional complication that coordinates' direction from the equator / prime meridian might be expressed either via N/S, E/W or by signed N, E, or by a combination of both. The above pattern accommodates all of those alternatives.
Putting it all together, you might do something like this:
private double toDouble(Matcher m, int offset) {
int sign = "".equals(m.group(1 + offset)) ? 1 : -1;
double degrees = Double.parseDouble(m.group(2 + offset));
double minutes = Double.parseDouble(m.group(3 + offset));
double seconds = Double.parseDouble(m.group(4 + offset));
int direction = "NE".contains(m.group(5 + offset)) ? 1 : -1;
return sign * direction * (degrees + minutes / 60 + seconds / 3600);
}
public double[] convert(String dms) {
Matcher m = DMS_PATTERN.matcher(dms.trim());
if (m.matches()) {
double latitude = toDouble(m, 0);
double longitude = toDouble(m, 5);
if ((Math.abs(latitude) > 90) || (Math.abs(longitude) > 180)) {
throw new NumberFormatException("Invalid latitude or longitude");
}
return new double[] { latitude, longitude };
} else {
throw new NumberFormatException(
"Malformed degrees/minutes/seconds/direction coordinates");
}
}
The convert() method is the main one; it returns the coordinates as an array of two doubles, representing the coordinates in decimal degrees north and east of the intersection of the equator with the prime meridian. Latitudes south of the equator are represented as negative, as are longitudes west of the prime meridian. A NumberFormatException is thrown if the input does not match the pattern, or if the latitude or longitude apparently represented is invalid (the magnitude of the longitude cannot exceed 180°; that of the latitude cannot exceed 90°).
You won't be able to parse that into a double without removing the non number chars but,
String string = "78°14'09"N";
Double number = 0;
try{
number = Double.parseDouble(string);
//do something..
}catch (NumberFormatException e){
//do something.. can't be parsed
}
If you first remove any characters from the string that are not alphanumeric, then something along these lines will work. This code compiles.
public class HelloWorld{
public static void main(String []args){
String input = "78 14'09 N 15 29'29 E".replaceAll("[^A-Za-z0-9]", " ");
String[] array = input.split(" ");
int nDegree = Integer.parseInt(array[0]);
int nMinute = Integer.parseInt(array[1]);
int nSecond = Integer.parseInt(array[2]);
int eDegree = Integer.parseInt(array[4]);
int eMinute = Integer.parseInt(array[5]);
int eSecond = Integer.parseInt(array[6]);
double nDegrees = nDegree + (double) nMinute/60 + (double) nSecond/3600;
double eDegrees = eDegree + (double) eMinute/60 + (double) eSecond/3600;
String nResult = "Decimal = N " + Double.toString(nDegrees).substring(0,10);
String eResult = "Decimal = E " + Double.toString(eDegrees).substring(0,10);
System.out.println(nResult);
System.out.println(eResult);
}
}
Output:
Decimal = N 78.2358333
Decimal = E 15.4913888
The problem is that Java can't store the degrees ° character as part of a String, or internal quotes (the minute character). If you can find a way to remove them from the string before inputting the data, then this will work.
I don't have a solution for handling the degrees symbol, but you could use an escape symbol \" to allow the use of a quotation mark within a string.
So I've used a regex with capturing groups to grab each of the numbers and the N/S/E/W. After capturing each individually it's just a matter of doing a bit of dividing to get the numbers and then formatting them however you'd like. For example I went with 5 digits of precision here.
public static void main(String[] args) {
String coords = "78°14'09N 15°29'29E";
String[] decimalCoords = degreesToDecimal(coords);
System.out.println(decimalCoords[0]);
System.out.println(decimalCoords[1]);
}
public static String[] degreesToDecimal(String degMinSec) {
String[] result = new String[2];
Pattern p = Pattern.compile("(\\d+).*?(\\d+).*?(\\d+).*?([N|S|E|W]).*?(\\d+).*?(\\d+).*?(\\d+).*?([N|S|E|W]).*?");
Matcher m = p.matcher(degMinSec);
if (m.find()) {
int degLat = Integer.parseInt(m.group(1));
int minLat = Integer.parseInt(m.group(2));
int secLat = Integer.parseInt(m.group(3));
String dirLat = m.group(4);
int degLon = Integer.parseInt(m.group(5));
int minLon = Integer.parseInt(m.group(6));
int secLon = Integer.parseInt(m.group(7));
String dirLon = m.group(8);
DecimalFormat formatter = new DecimalFormat("#.#####", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
formatter.setRoundingMode(RoundingMode.DOWN);
result[0] = formatter.format(degLat + minLat / 60.0 + secLat / 3600.0) + " " + dirLat;
result[1] = formatter.format(degLon + minLon / 60.0 + secLon / 3600.0) + " " + dirLon;
}
return result;
}
There is no error handling here, it's just a basic example of how you could make this work with your input.

Java String Split to get individual data from a large string

I have the following data which is stored as a big string.
"John Chips Monday \n"
"Tom Pizza Tuesday\n"
"Jerry IceCream Wednesday\n"
"Jennifer Coffee Thursday\n"
Now I wish to split this string so I can get individual data from this string and place each data in an array for example.
each element of names array stores the names seen above like names[0] = john, names[1] = Tom etc.
each element of food array stores the foods seen above like food[0] = chips, food[1] = pizza.
I have tried doing this
John + "\t" + Chips + "-" + Monday + "\n"
Tom + "\t" + Pizza + "-" + Tuesday+ "\n"
Jerry + "\t" + IceCream + "-" + Wednesday+ "\n"
Jennifer + "\t" + Coffee + "-" + Thursday+ "\n"
String nameCol[] = data.split("\\t");
String foodCol[] = data.split("-");
The output I get is nearly there but wrong as it contains data that I don't want in the array for example the output for first array is
nameCol[0] = John
nameCol[1] = Chips -
nameCol[2] = Monday
Element 0 contains john but the other elements contain the parts I don't want.
I tried for a limit but this did not work
String nameCol[] = data.split("\\t",1);
String foodCol[] = data.split("-",1);
This will work:
String yourLine = "John Chips Monday\n"; // Read your line in here
String[] resultCol = yourLine.split(" ");
resultCol[2] = resultCol[2].split("\\n")[0];
System.out.println( resultCol[2] );
The first split on the string will give you "John", "Chips" and "Monday\n". The second split takes "Monday\n" from the array and splits it. Returning "Monday" back into the final index of the array resultCol[2]. From here you can simply assign each element in the array to the arrays you require.
Don't use them separately, use the delimiters together, like : String dataArr\[\] = data.split("\t\n",1);
Then iterate through the String[]:
for (int i = 0; i < dataArr.length; i+=2) {
String name = dataArr[i];
String food = dataArr[i+1];
// ... do whatever you want with them.
}
Or, you could also try the similar Pattern-Matcher approach
You should:
use Lists for each column, (Lists can increase their size dynamically, while arrays have fixed size)
iterate over each line,
split it on whitespace (or any separator you are using)
and add column[0] to list of names, column[1] to list of food and so on with other columns.
OR if you know that each line has only three words you could simply use Scanner and iterate over words instead of lines with split.
while(scanner.hasNext()){
listOfNames.add(scanner.next());
listOfFood.add(scanner.next());
listOfDays.add(scanner.next());
}
Try this,
String str="John" + "\t" + "Chips" + "\t" + "Monday" + "-" + "Test"+"\n"+"chet";
String st1= str.replaceAll("(\\t)|(-)|(\n)"," ");
String []st=st1.split(" ");
for(String s : st)
System.out.println(s);
From your data, I assume that you are reading this values from a files. If you know how many lines there are, you could use 3 arrays, each for every type of data that needs to be retrived. If you don't know the size, you could go with 3 ArrayLists. Your problem is that after making the split, you didn't put them in the correct arrays. The following code assumes that you already have all the data in one String.
final String values[] = data.split("\\n");
final ArrayList<String> names = new ArrayList<String>();
final ArrayList<String> foods = new ArrayList<String>();
final ArrayList<String> days = new ArrayList<String>();
for (String line : values) {
String[] split = line.trim().split("[ ]+");
names.add(split[0]);
foods.add(split[1]);
days.add(split[2]);
}
Another thing that you must consider is to check if the data always has 3 values on a "line", or else further error checking is needed.
If your string is always going to be "[name] [food] [day]", then you could do:
String[] names = new String[allData.length]; //A list of names
String[] food = new String[allData.length]; //A list of food
String[] day = new String[allData.length]; //A list of days
for(int i = 0 ; i < allData.length ; i++)
{
String[] contents = allData[i].split(" "); //Or use a similar delimiter.
names[i] = contents[0];
food[i] = contents[1];
day[i] = contents[2];
}
Try this code
String s = "John Chips Monday \n Tom Pizza Tuesday \n Jerry IceCream Wednesday \n Jennifer Coffee Thursday \n";
String split[] = s.split("\n");
String names[] = new String[split.length];
String foods[] = new String[split.length];
String days[] = new String[split.length];
for (int i = 0; i < split.length; i++) {
String split1[] = split[i].trim().split(" ");
names[i]=split1[0];
foods[i]=split1[1];
days[i]=split1[2];
System.out.println("name=" + names[i] + ",food=" + foods[i] + ",day=" + days[i]);
}

recursive function returning a string of moves

Hey everyone I started doing recursion and I have to say its confusing me.
Currently I'm working on the Towers of Hanoi:
public static String hanoi(int n, int startPole, int endPole) {
String ret = new String();
if (n == 0){
return "";
}
int intermediatePole = 6 - startPole - endPole;
String add3 = hanoi(n-1, startPole, intermediatePole);
String add = startPole + "->" + endPole + "\n";
String add2 = hanoi(n-1, intermediatePole,endPole );
return add + add3 + add2;
}
So pretty much what's breaking my brain is - Who does one return the string of moves such that you get from a call of hanoi(2, 1, 3), you get a output like so, mine only returns one loop of the recursive call
1 - 3
1 - 2
3 - 2
1 - 3
2 - 1
2 - 3
1 - 3
Try it with return add3 + add + add2;. If your code's output is tried on a physical tower, it doesn't work.
The reason that you are only seeing "one loop of the recurisve call" is that the output show is actually for hanoi(3,1,3), not 2,1,3.

Categories

Resources