String containing time (1H4M10S) converted to seconds - java

I want to convert a string that looks like this "5W3D10H5M10S" to seconds, the function would return "3319510", when having the previous string as an argument.
W = Week(s)
D = Day(s)
H = Hour(s)
M = Minute(s)
S = Second(s)
I've been thinking of ways to do this, but none of them will be efficient, if anyone could point me in the right direction that would be great.

You can parse it back with the help of a regular expression, see below an implementation with Java 7 :
String str = "5W3D10H5M10S";
String pat = "((?<week>\\d+)W)?((?<day>\\d+)D)?((?<hour>\\d+)H)?((?<min>\\d+)M)?((?<sec>\\d+)S)?";
Matcher m = Pattern.compile (pat).matcher(str);
if(m.matches()) {
int week = Integer.parseInt( m.group("week") );
int day = Integer.parseInt( m.group("day") );
//And so on ..
}

how about translate your string into an expression and let ScriptEngineManager do the calculation?
public void testIt() throws Exception {
final String in = "5W3D10H5M10S";
final String after = in.replaceAll("W", "*7D").
replaceAll("D", "*24H").
replaceAll("H", "*60M").
replaceAll("M", "*60+").
replaceAll("S", "");
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("js");
final Object result = engine.eval(after);
System.out.println("Result:" + String.valueOf(result));
}
output:
Result:3319510.0

You can do it with a regexp and a simple loop:
private static final int[] timeMul = new int[] {7, 24, 60, 60, 1};
private static final Pattern rx = Pattern.compile(
"(?:(\\d+)W)?(?:(\\d+)D)?(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?"
);
public static int getSeconds(String str) {
Matcher m = rx.matcher(str);
if (!m.find()) {
return -1;
}
int res = 0;
for (int i = 0 ; i != m.groupCount() ; i++) {
String g = m.group(i+1);
res += g == null ? 0 : Integer.parseInt(g);
res *= timeMul[i];
}
return res;
}
Link to ideone.

The easiest would be to simple loop through the text until it reaches a non numerical character then take a substring of the previous character location and get that section of text, parse it to int and multiply it by the amount needed according to the character.
Example:
public long getSeconds(String funnyFormat)
{
long seconds = 0;
int lastIndex = 0;
for(int i = 0;i<funnyFormat.length;i++) {
char cur = funnyFormat.charAt(i);
if(cur < '0' && cur > '9') {
//If it's not a Number
int seg = Integer.parseInt(funnyFormat.substring(lastIndex,i));
lastIndex = i+1;
switch(cur){
case 'H':
long += seg*3600;
break;
case 'M':
long += seg*60;
break;
case 'S':
long += seg;
break;
//And so on and so forth
}
}
}
}

You'll have to tweak this to take care of some boundary conditions and unexpected input...
long wdh(String fmt) {
long tot = 0;
int current = 0;
for (char c : fmt.toCharArray()) {
if (Character.isDigit(c)) {
current *= 10;
current += c - '0';
continue;
}
switch (c) {
case 'W': tot += WEEK_SECONDS * current; current = 0; continue;
case 'D': tot += DAY_SECONDS * current; current = 0; continue;
case 'H': tot += HOUR_SECONDS * current; current = 0; continue;
case 'M': tot += MINUTE_SECONDS * current; current = 0; continue;
case 'S': tot += current; break;
}
}
return tot;
}

EDIT: Little simplified(Less string manipulations)
DateFormat dateFormat = new SimpleDateFormat("d'D'HH'H'mm'M'ss'S'");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
String dateString = "5W3D10H5M10S";
String[] dateAndWeek = dateString.split("W");
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTime(dateFormat.parse(dateAndWeek[1]));
cal.add(Calendar.DATE, 1);
cal.add(Calendar.WEEK_OF_YEAR, Integer.parseInt(dateAndWeek[0]));
long dateSeconds = cal.getTimeInMillis()/1000;//<--3319510

Related

Modifying String in Java

I have a String , String a = newNumber + "*" + nn + "+" + difference;
the newNumber = 106 , nn = 3 and difference = 3.
so the output should be as follow ;
Output :
106*3+3
I would like to modify the String so that the output becomes (35*3+1)*3+3 and then with this new String I would like to modify it again so that it becomes ((11*3+2)*3+1)*3+3
Basically I just need to replace the newNumber which was 106 and kept changing to 11, as you can see I'm trying to modify only the newNumber and replacing it with another while keeping the entire String untouched , I'm just replacing and adding to it , how can this be achieved ?
The output should be like this,
Output :
106*3+3
(35*3+1)*3+3
((11*3+2)*3+1)*3+3
I'm solving an equation with steps , the formulas don't matter I'm just trying to figure out how can I modify the String by replacing the newNumber with a another number and adding new brackets to the equation.
I hope I wrote my problem in a way you would understand , I'd really appreciate the help.
I could not get to the same output which you have but here the code which try to solve this problem I think it might give you little help though which you could solve the problem.
Breaking the number until its prime number and adding the prime numbers to the result. Since we are replacing and appending with strings its better to use StringBuilder.
import java.io.PrintStream;
import java.util.Arrays;
public class StringSimplification {
public static PrintStream out = System.out;
public static final boolean prime[];
public static final int SIZE = 1000000;
static {
prime = new boolean[SIZE];
Arrays.fill(prime, true);
prime[0] = prime[1] = false;
//Sieve of Eratosthenes algorithm to find weather number is prime
for (int i = 2; i < SIZE; i++)
if (prime[i])
for (int j = i * 2; j < SIZE; j += i)
prime[j] = false;
}
//simplifies your String expression
public static String simplify(final String expression) {
StringBuilder result = new StringBuilder("");
String exp = "";
for (char ch : expression.toCharArray()) {
if (Character.isDigit(ch))
exp += ch;
else {
if (isNumber(exp)) {
String simplified = getExpression(Integer.parseInt(exp));
result.append(simplified+ch);
exp = "";//clearing exp
};
}
}
result.append(exp);
return result.toString();
}
//returns weather number is prime or not
static boolean isPrime(final int val) {
return prime[val];
}
static String getExpression(final int val) {
if (val == 0 || val == 1 || prime[val])
return "(" + val + ")";
int prev = 1;
int div = 1;
for (int i = 1; i < val; i++) {
if (val % i == 0) {
prev = i;
div = val / i;
}
}
return getExpression(prev) + "*" + getExpression(div);
}
//Check's weather the expression is number
public static boolean isNumber(final String s) {
for (var c : s.toCharArray())
if (!Character.isDigit(c))
return false;
return s.length() > 0;
}
public static void main(final String... $) {
out.println(simplify("106*3+3"));
out.println(simplify("1024*3+3"));
}
}
Output:
(53)*(2)*(3)+3
(2)*(2)*(2)*(2)*(2)*(2)*(2)*(2)*(2)*(2)*(3)+3
You can’t actually modify Strings, but you can use replaceFirst() like this:
s = s.replaceFirst("106", "(35*3+1)");
s = s.replaceFirst("35", "(11*3+2)");
etc
Strings in java are immutable. You will have to use StringBuilder or String Buffer
However if you insist then you may try(from what I understood of the pattern)
int num = 106;
String rep = "";
String S = "106*3+3";
String target;
int b = 1;
int largestfactor = 1;
System.out.println(S);
for (int i = num; i > 0; i--) {
for (int j = 1; j < (num - b); j++) {
if ((num - b) % j == 0)
largestfactor = j;
}
target = "" + num;
rep = "(" + largestfactor + "*" + (num - b) / largestfactor + ")" + "+" + b;
S = S.replace(target,rep);
System.out.println(S);
num = largestfactor;
b++;
if(b>num)
break;
}

Increment Alpha-Numeric values but restrict to 3 characters

The scenario is - I read the last line of a file, increment it by one and write it back.
The read and write has been done. I am finding it difficult to increment the alpha-numberic values as it has a few conditions.
The conditions are:
It should only be 3 characters long
Example : A01, A02.... A99, B01, B02.... B99..
Once Z99 is reached it should be AA1, AA2, AA3...AA9, .....
Then AB1, AB2,... AZ9
So basically while incrementing the value should not go AA10 which makes it 4 characters
What I am doing now is separating the alphabets and integers, incrementing it and concatenating them back.
The code so far:
String[] part = lastLine.split("(?<=\\D)(?=\\d)");
System.out.println(part[0]);
System.out.println(part[1]);
int numberOnly = Integer.parseInt(lastLine.replaceAll("[^0-9]", ""));
numberOnly++;
String lettersOnly = lastLine.replaceAll("[^A-Z]", "");
if (lettersOnly.length() > 1){
String lastLetter = lettersOnly.substring(lettersOnly.length() - 1);
if(lastLetter.equalsIgnoreCase("Z") && number.equalsIgnoreCase("9") ){
String notLastLetter = lettersOnly.substring(lettersOnly.length() - 2);
char d = lettersOnly.charAt(0);
d++;
System.out.println("Letters after increment more tan two : " +d);
lettersOnly = Character.toString(d) + "Z";
}
}
else{
}
System.out.println("Letters after increment : " +lettersOnly);
Any help would be greatly appreciated.
public class AlphaNumericCounter {
String[] part;
int counter; //Variable storing numeric part of counter
String alpha; //Variable storing Alpha part of counter
static String final_output = "A00"; // First Input considered as A00 and also the variable which will be store each count
static boolean continueIncrement = true; //For running the loop till we reach ZZ9
/* Def constructor */
public AlphaNumericCounter() {
}
/* Constructor called from main method with primary input A00 */
public AlphaNumericCounter(String number) {
part = number.split("(?<=\\D)(?=\\d)");
}
/* Function called each time from inside loop to generate next alphanumeric count */
public void increment() {
part = final_output.split("(?<=\\D)(?=\\d)");
counter = Integer.valueOf(part[1]) + 1;
alpha = part[0];
}
public String toString() {
if (alpha.length() == 1){
if (String.valueOf(counter).length() > 2){
if ((int)alpha.charAt(0) + 1 > 90/*If Z encountered*/){
alpha = "AA";
}else{
alpha = String.valueOf((char)((int)alpha.charAt(0) + 1));//Take Next Alphabet
}
counter = 1; //Reset counter to 1
}
}else{
//We have AA, AB ... ZZ format of alpha
if (String.valueOf(counter).length() > 1){
if ((int)alpha.charAt(0) + 1 > 90 && (int)alpha.charAt(1) + 1 > 90){
continueIncrement = false;
System.out.println("NO MORE COMBINATION AVAILABLE"); //We reached ZZ
return "";
}else if ((int)alpha.charAt(1) + 1 <= 90){
alpha = String.valueOf((char)((int)alpha.charAt(0))) + String.valueOf((char)((int)alpha.charAt(1) + 1));
counter = 1;
}else if ((int)alpha.charAt(1) + 1 > 90){
if ((int)alpha.charAt(0) + 1 <= 90){
alpha = String.valueOf((char)((int)alpha.charAt(0) + 1)) + "A";
counter = 1;
}
}
}
}
generateString();
return final_output;
}
private void generateString(){
int l1 = String.valueOf(counter).length();
int l2 = alpha.length();
final_output = alpha + (l2 == 1 && l1 == 1 ? "0" : "") + String.valueOf(counter);
}
public static void main(String[] args) {
AlphaNumericCounter lic = new AlphaNumericCounter(final_output);
while (continueIncrement){
lic.increment();
System.out.println(lic);
}
}
}
What about incrementing each "digit" separatly from right to left and handle overvlow to the next digit:
String number;//number - is your originally string
char[] digits = number.toCharArray();
boolean overflow = true;
for(int i = 2; i >= 0; i--){
if(overflow){
switch(digits[i]){
case 'Z':
digits[i] = '0';
overflow = true;
break;
case '9':
digits[i] = 'A';
overflow = false;
break;
default:
digits[i]++;
overflow = false;
}
}
}
if(overflow){
//handle ZZZ overflow here
}
String result = new String(digits);
A simple solution is to count in Base36
Try this:
class AlphaNumericIncrementer {
public static void main(String[] args) {
/*
When starting at '000' => We hit 'zzz' (i.e. Dead End) at 46,656
When starting at 'A00' => We hit 'zzz' (i.e. Dead End) at 33,696
*/
int index = 0;
String currentNumber = "000";
while (index < 46656) {
index++;
String incrementedNumber = base36Incrementer(currentNumber, 36);
currentNumber = incrementedNumber;
if (incrementedNumber.toCharArray().length != 3) {
System.out.println("We got intruder with length: " + incrementedNumber.toCharArray().length);
System.out.println("Our Intruder is: " + incrementedNumber);
break;
}
System.out.println(incrementedNumber);
}
System.out.println("Number of entries: " + index);
}
// The function that increments current string
public static String base36Incrementer(String v, int targetBase) {
String answer = Integer.toString(Integer.parseInt(v, targetBase) + 1, targetBase);
return String.format("%3s", answer).replace(' ', '0');
}
}

Unformat formatted String

I have a simple formatted String:
double d = 12.348678;
int i = 9876;
String s = "ABCD";
System.out.printf("%08.2f%5s%09d", d, s, i);
// %08.2f = '12.348678' -> '00012,35'
// %5s = 'ABCD' -> ' ABCD'
// %09d = '9876' -> '000009876'
// %08.2f%5s%09d = '00012,35 ABCD000009876'
When i know the pattern: %08.2f%5s%09d and String: 00012,35 ABCD000009876:
Can i "unformat" this String in some way?
eg. the expected result something like 3 tokens: '00012,35', ' ABCD', '000009876'
This is specific to your pattern. A general parser for a formatstring, (because what we call unformatting is parsing) would look much different.
public class Unformat {
public static Integer getWidth(Pattern pattern, String format) {
Matcher matcher = pattern.matcher(format);
if (matcher.find()) {
return Integer.valueOf(matcher.group(1));
}
return null;
}
public static String getResult(Pattern p, String format, String formatted,
Integer start, Integer width) {
width = getWidth(p, format);
if (width != null) {
String result = formatted.substring(start, start + width);
start += width;
return result;
}
return null;
}
public static void main(String[] args) {
String format = "%08.2f%5s%09d";
String formatted = "00012.35 ABCD000009876";
String[] formats = format.split("%");
List<String> result = new ArrayList<String>();
Integer start = 0;
Integer width = 0;
for (int j = 1; j < formats.length; j++) {
if (formats[j].endsWith("f")) {
Pattern p = Pattern.compile(".*([0-9])+\\..*f");
result.add(getResult(p, formats[j], formatted, start, width));
} else if (formats[j].endsWith("s")) {
Pattern p = Pattern.compile("([0-9])s");
result.add(getResult(p, formats[j], formatted, start, width));
} else if (formats[j].endsWith("d")) {
Pattern p = Pattern.compile("([0-9])d");
result.add(getResult(p, formats[j], formatted, start, width));
}
}
System.out.println(result);
}
}
Judging by your output format of "%08.2f%5s%09d", it seems comparable to this pattern
"([0-9]{5,}[\\.|,][0-9]{2,})(.{5,})([0-9]{9,})"
Try the following:
public static void main(String[] args) {
String data = "00012,35 ABCD000009876";
Matcher matcher = Pattern.compile("([0-9]{5,}[\\.|,][0-9]{2,})(.{5,})([0-9]{9,})").matcher(data);
List<String> matches = new ArrayList<>();
if (matcher.matches()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
matches.add(matcher.group(i));
}
}
System.out.println(matches);
}
Results:
[00012,35, ABCD, 000009876]
UPDATE
After seeing the comments, here's a generic example without using RegularExpressions as to not copy #bpgergo (+1 to you with generic RegularExpressions approach). Also added some logic in case the format ever exceeded the width of the data.
public static void main(String[] args) {
String data = "00012,35 ABCD000009876";
// Format exceeds width of data
String format = "%08.2f%5s%09d%9s";
String[] formatPieces = format.replaceFirst("^%", "").split("%");
List<String> matches = new ArrayList();
int index = 0;
for (String formatPiece : formatPieces) {
// Remove any argument indexes or flags
formatPiece = formatPiece.replaceAll("^([0-9]+\\$)|[\\+|-|,|<]", "");
int length = 0;
switch (formatPiece.charAt(formatPiece.length() - 1)) {
case 'f':
if (formatPiece.contains(".")) {
length = Integer.parseInt(formatPiece.split("\\.")[0]);
} else {
length = Integer.parseInt(formatPiece.substring(0, formatPiece.length() - 1));
}
break;
case 's':
length = Integer.parseInt(formatPiece.substring(0, formatPiece.length() - 1));
break;
case 'd':
length = Integer.parseInt(formatPiece.substring(0, formatPiece.length() - 1));
break;
}
if (index + length < data.length()) {
matches.add(data.substring(index, index + length));
} else {
// We've reached the end of the data and need to break from the loop
matches.add(data.substring(index));
break;
}
index += length;
}
System.out.println(matches);
}
Results:
[00012,35, ABCD, 000009876]
You can do something like this:
//Find the end of the first value,
//this value will always have 2 digits after the decimal point.
int index = val.indexOf(".") + 3;
String tooken1 = val.substring(0, index);
//Remove the first value from the original String
val = val.substring(index);
//get all values after the last non-numerical character.
String tooken3 = val.replaceAll(".+\\D", "");
//remove the previously extracted value from the remainder of the original String.
String tooken2 = val.replace(tooken3, "");
This will fail if the String value contains a number at the end and probably in some other cases.
As you know the pattern, it means that you are dealing with some kind of regular expression. Use them to utilize your needs.
Java has decent regular expression API for such tasks
Regular expressions can have capturing groups and each group would have a single "unformatted" part just as you want. All depends on regex you will use/create.
Easiest thing to do would be to parse the string using a regex with myString.replaceAll(). myString.split(",") may also be helpful for splitting your string into a string array

Compression algorithm in java

My goal is to write a program that compresses a string, for example:
input: hellooopppppp!
output:he2l3o6p!
Here is the code I have so far, but there are errors.
When I have the input: hellooo
my code outputs: hel2l3o
instead of: he213o
the 2 is being printed in the wrong spot, but I cannot figure out how to fix this.
Also, with an input of: hello
my code outputs: hel2l
instead of: he2lo
It skips the last letter in this case all together, and the 2 is also in the wrong place, an error from my first example.
Any help is much appreciated. Thanks so much!
public class compressionTime
{
public static void main(String [] args)
{
System.out.println ("Enter a string");
//read in user input
String userString = IO.readString();
//store length of string
int length = userString.length();
System.out.println(length);
int count;
String result = "";
for (int i=1; i<=length; i++)
{
char a = userString.charAt(i-1);
count = 1;
if (i-2 >= 0)
{
while (i<=length && userString.charAt(i-1) == userString.charAt(i-2))
{
count++;
i++;
}
System.out.print(count);
}
if (count==1)
result = result.concat(Character.toString(a));
else
result = result.concat(Integer.toString(count).concat(Character.toString(a)));
}
IO.outputStringAnswer(result);
}
}
I would
count from 0 as that is how indexes work in Java. Your code will be simpler.
would compare the current char to the next one. This will avoid printing the first character.
wouldn't compress ll as 2l as it is no smaller. Only sequences of at least 3 will help.
try to detect if a number 3 to 9 has been used and at least print an error.
use the debugger to step through the code to understand what it is doing and why it doesn't do what you think it should.
I am doing it this way. Very simple:
public static void compressString (String string) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < string.length(); i++) {
int count = 1;
while (i + 1 < string.length()
&& string.charAt(i) == string.charAt(i + 1)) {
count++;
i++;
}
if (count > 1) {
stringBuffer.append(count);
}
stringBuffer.append(string.charAt(i));
}
System.out.println("Compressed string: " + stringBuffer);
}
You can accomplish this using a nested for loops and do something simial to:
count = 0;
String results = "";
for(int i=0;i<userString.length();){
char begin = userString.charAt(i);
//System.out.println("begin is: "+begin);
for(int j=i+1; j<userString.length();j++){
char next = userString.charAt(j);
//System.out.println("next is: "+next);
if(begin == next){
count++;
}
else{
System.out.println("Breaking");
break;
}
}
i+= count+1;
if(count>0){
String add = begin + "";
int tempcount = count +1;
results+= tempcount + add;
}
else{
results+= begin;
}
count=0;
}
System.out.println(results);
I tested this output with Hello and the result was He2lo
also tested with hellooopppppp result he2l3o6p
If you don't understand how this works, you should learn regular expressions.
public String rleEncodeString(String in) {
StringBuilder out = new StringBuilder();
Pattern p = Pattern.compile("((\\w)\\2*)");
Matcher m = p.matcher(in);
while(m.find()) {
if(m.group(1).length() > 1) {
out.append(m.group(1).length());
}
out.append(m.group(2));
}
return out.toString();
}
Try something like this:
public static void main(String[] args) {
System.out.println("Enter a string:");
Scanner IO = new Scanner(System.in);
// read in user input
String userString = IO.nextLine() + "-";
int length = userString.length();
int count = 0;
String result = "";
char new_char;
for (int i = 0; i < length; i++) {
new_char = userString.charAt(i);
count++;
if (new_char != userString.charAt(i + 1)) {
if (count != 1) {
result = result.concat(Integer.toString(count + 1));
}
result = result.concat(Character.toString(new_char));
count = 0;
}
if (userString.charAt(i + 1) == '-')
break;
}
System.out.println(result);
}
The problem is that your code checks if the previous letter, not the next, is the same as the current.
Your for loops basically goes through each letter in the string, and if it is the same as the previous letter, it figures out how many of that letter there is and puts that number into the result string. However, for a word like "hello", it will check 'e' and 'l' (and notice that they are preceded by 'h' and 'e', receptively) and think that there is no repeat. It will then get to the next 'l', and then see that it is the same as the previous letter. It will put '2' in the result, but too late, resulting in "hel2l" instead of "he2lo".
To clean up and fix your code, I recommend the following to replace your for loop:
int count = 1;
String result = "";
for(int i=0;i<length;i++) {
if(i < userString.length()-1 && userString.charAt(i) == userString.charAt(i+1))
count++;
else {
if(count == 1)
result += userString.charAt(i);
else {
result = result + count + userString.charAt(i);
count = 1;
}
}
}
Comment if you need me to explain some of the changes. Some are necessary, others optional.
Here is the solution for the problem with better time complexity:
public static void compressString (String string) {
LinkedHashSet<String> charMap = new LinkedHashSet<String>();
HashMap<String, Integer> countMap = new HashMap<String, Integer>();
int count;
String key;
for (int i = 0; i < string.length(); i++) {
key = new String(string.charAt(i) + "");
charMap.add(key);
if(countMap.containsKey(key)) {
count = countMap.get(key);
countMap.put(key, count + 1);
}
else {
countMap.put(key, 1);
}
}
Iterator<String> iterator = charMap.iterator();
String resultStr = "";
while (iterator.hasNext()) {
key = iterator.next();
count = countMap.get(key);
if(count > 1) {
resultStr = resultStr + count + key;
}
else{
resultStr = resultStr + key;
}
}
System.out.println(resultStr);
}

In Java how do you convert a decimal number to base 36?

If I have a decimal number, how do I convert it to base 36 in Java?
Given a number i, use Integer.toString(i, 36).
See the documentation for Integer.toString
http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#toString(int,%20int)
toString
public static String toString(int i, int radix)
....
The following ASCII characters are used as digits:
0123456789abcdefghijklmnopqrstuvwxyz
What is radix? You're in luck for Base 36 (and it makes sense)
http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#MAX_RADIX
public static final int MAX_RADIX 36
The following can work for any base, not just 36. Simply replace the String contents of code.
Encode:
int num = 586403532;
String code = "0123456789abcdefghijklmnopqrstuvwxyz";
String text = "";
int j = (int)Math.ceil(Math.log(num)/Math.log(code.length()));
for(int i = 0; i < j; i++){
//i goes to log base code.length() of num (using change of base formula)
text += code.charAt(num%code.length());
num /= code.length();
}
Decode:
String text = "0vn4p9";
String code = "0123456789abcdefghijklmnopqrstuvwxyz";
int num = 0;
int j = text.length();
for(int i = 0; i < j; i++){
num += code.indexOf(text.charAt(0))*Math.pow(code.length(), i);
text = text.substring(1);
}
First you have to convert your number it into the internal number format of Java (which happens to be 2-based, but this does not really matter here), for example by Integer.parseInt() (if your number is an integer less than 2^31). Then you can convert it from int to the desired output format. The method Integer.toString(i, 36) does this by using 0123456789abcdefghijklmnopqrstuvwxyz as digits (the decimal digits 0-9 and lower case english letters in alphabetic order). If you want some other digits, you can either convert the result by replacing the "digits" (for example toUpperCase), or do the conversion yourself - it is no magic, simply a loop of taking the remainder modulo 36 and dividing by 36 (with a lookup of the right digit).
If your number is longer than what int offers you may want to use long (with Long) or BigInteger instead, they have similar radix-converters.
If your number has "digits after the point", it is a bit more difficult, as most (finite) base-X-numbers are not exactly representable as (finite) base-Y-numbers if (a power of) Y is not a multiple of X.
This code works:
public class Convert {
public static void main(String[] args) {
int num= 2147483647;
String text="ABCD1";
System.out.println("num: " + num + "=>" + base10ToBase36(num));
System.out.println("text: " +text + "=>" + base36ToBase10(text));
}
private static String codeBase36 = "0123456789abcdefghijklmnopqrstuvwxyz";
//"0123456789 abcdefghij klmnopqrst uvwxyz"
//"0123456789 0123456789 0123456789 012345"
private static String max36=base10ToBase36(Integer.MAX_VALUE);
public static String base10ToBase36(int inNum) {
if(inNum<0) {
throw new NumberFormatException("Value "+inNum +" to small");
}
int num = inNum;
String text = "";
int j = (int)Math.ceil(Math.log(num)/Math.log(codeBase36.length()));
for(int i = 0; i < j; i++){
text = codeBase36.charAt(num%codeBase36.length())+text;
num /= codeBase36.length();
}
return text;
}
public static int base36ToBase10(String in) {
String text = in.toLowerCase();
if(text.compareToIgnoreCase(max36)>0) {
throw new NumberFormatException("Value "+text+" to big");
}
if(!text.replaceAll("(\\W)","").equalsIgnoreCase(text)){
throw new NumberFormatException("Value "+text+" false format");
}
int num=0;
int j = text.length();
for(int i = 0; i < j; i++){
num += codeBase36.indexOf(text.charAt(text.length()-1))*Math.pow(codeBase36.length(), i);
text = text.substring(0,text.length()-1);
}
return num;
}
}
If you dont want to use Integer.toString(Num , base) , for instance, in my case which I needed a 64 bit long variable, you can use the following code:
Using Lists in JAVA facilitates this conversion
long toBeConverted=10000; // example, Initialized by 10000
List<Character> charArray = new ArrayList<Character>();
List<Character> charArrayFinal = new ArrayList<Character>();
int length=10; //Length of the output string
long base = 36;
while(toBeConverted!=0)
{
long rem = toBeConverted%base;
long quotient = toBeConverted/base;
if(rem<10)
rem+=48;
else
rem+=55;
charArray.add((char)rem);
toBeConverted=quotient;
}
// make the array in the reverse order
for(int i=length-1;i>=0;--i){
if(i>=charArray.size()){
charArrayFinal.add((char) 48); // sends 0 to fix the length of the output List
} else {
charArrayFinal.add(charArray.get(i));
}
}
Example:
(278197)36=5YNP
Maybe I'm late to the party, but this is the solution I was using for getting Calc/Excel cell names by their index:
public static void main(final String[] args) {
final String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
System.out.println(toCustomBase(0, base));
System.out.println(toCustomBase(2, base));
System.out.println(toCustomBase(25, base));
System.out.println(toCustomBase(26, base));
System.out.println(toCustomBase(51, base));
System.out.println(toCustomBase(52, base));
System.out.println(toCustomBase(520, base));
}
public static String toCustomBase(final int num, final String base) {
final int baseSize = base.length();
if(num < baseSize) {
return String.valueOf(base.charAt(num));
}
else {
return toCustomBase(num / baseSize - 1, base) + base.charAt(num % baseSize);
}
}
Results:
A
C
Z
AA
AZ
BA
TA
Basically the solution accepts any custom radix. The idea was commandeered from here.
Not sure if the above answers did help but noting 'decimal' and 'to base36' I assume you want to convert a numeric value to base36. And as long as the Long value of the raw figure is within (0 - Long.MAX_VALUE):
String someNumericString = "9223372036854";
Long l = Long.valueOf(someNumericString);
String bases36 = Long.toString(l, 36);
System.out.println("base36 value: "+bases36);
output: 39p5pkj5i
Here is a method to convert base 10 to any given base.
public char[] base10Converter(int number, int finalBase) {
int quo;
int rem;
char[] res = new char[1];
do {
rem = number % finalBase;
quo = number / finalBase;
res = Arrays.copyOf(res, res.length + 1);
if (rem < 10) {
//Converting ints using ASCII values
rem += 48;
res[res.length - 1] = (char) rem;
} else {
//Convert int > 9 to A, B, C..
rem += 55;
res[res.length - 1] = (char) rem;
}
number /= finalBase;
} while (quo != 0);
//Reverse array
char[] temp = new char[res.length];
for (int i = res.length - 1, j = 0; i > 0; i--) {
temp[j++] = res[i];
}
return temp;
}
I got this code from this website in JavaScript, and this is my version in java:
public static String customBase (int N, String base) {
int radix = base.length();
String returns = "";
int Q = (int) Math.floor(Math.abs(N));
int R = 0;
while (Q != 0) {
R = Q % radix;
returns = base.charAt(R) + returns;
Q /= radix;
}
if(N == 0) {
return String.valueOf(base.toCharArray()[0]);
}
return N < 0 ? "-" + returns : returns;
}
This supports negative numbers and custom bases.
Decimal Addon:
public static String customBase (double N, String base) {
String num = (String.valueOf(N));
String[] split = num.split("\\.");
if(split[0] == "" || split[1] == "") {
return "";
}
return customBase(Integer.parseInt(split[0]), base)+ "." + customBase(Integer.parseInt(split[1]), base);
}
This can be helpful to you.The operation being performed on the 4 digit alphanumeric String and decimal number below 1679615. You can Modify code accordingly.
char[] alpaNum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
String currentSeries = "";
int num = 481261;
String result = "";
String baseConversionStr = "";
boolean flag = true;
do
{
baseConversionStr = Integer.toString(num % 36) + baseConversionStr;
String position = "";
if(flag)
{
flag = false;
position = baseConversionStr;
}
else
{
position = Integer.toString(num % 36);
}
result += alpaNum[new Integer(position)];
num = num/36;
}
while (num > 0);
StringBuffer number = new StringBuffer(result).reverse();
String finalString = "";
if(number.length()==1)
{
finalString = "000"+articleNo;
}
else if(number.length()==2)
{
finalString = "00"+articleNo;
}
else if(number.length()==3)
{
finalString = "0"+articleNo;
}
currentSeries = finalString;

Categories