I have a number like this:
1234567890123
and want to format it for example like this
12 34567 89012 3
or maybe like this
1-234 567-890 1 23
How can I achive that? I tried this
DecimalFormat decimalFormat = new DecimalFormat("00 00000 00000 0");
System.out.println(decimalFormat.format(1234567890123L));
But this doesn't work.
I need a way to specify a pattern that can contain any separator character.
import java.text.ParseException;
import javax.swing.text.MaskFormatter;
import org.junit.jupiter.api.Test;
public class FormatTest {
#Test
void testNumberFormat() throws ParseException {
final String format = "#-### ###-### # ##";
final String number = "1234567890123";
MaskFormatter maskFormatter = new MaskFormatter(format);
maskFormatter.setValueContainsLiteralCharacters(false);
System.out.println(maskFormatter.valueToString(number));
}
}
That is not possible with DecimalFormatter and NumberFormatter. But you can use a trick with String and regular expression:
Long.toString(number)
.replaceAll("(\\d{2})(\\d{5})(\\d{5})(\\d)", "$1 $2 $3 $4");
If your format is dynamic, you could do something like this:
#Test
void simon() {
final var input = 1234567890123L;
assertEquals("12 34567 89012 3", formatMyNumber(input, "{2} {5} {5} {1}"));
assertEquals("12-34567-89012-3", formatMyNumber(input, "{2}-{5}-{5}-{1}"));
assertEquals("12_34567_89012_3", formatMyNumber(input, "{2}_{5}_{5}_{1}"));
assertEquals("1 23456 7", formatMyNumber(1234567, "{1} {5} {1}"));
assertEquals("1 2345 6", formatMyNumber(123456, "{1} {4} {1}"));
assertEquals("123.45.6", formatMyNumber(123456, "{3}.{2}.{1}"));
}
private String formatMyNumber(final long number, final String format) {
return Long.toString(number).replaceAll(createRegEx(format), createReplacement(format));
}
private String createRegEx(final String format) {
final var separator = getSeparator(format);
return format.replaceAll("\\{", "(\\\\d{")
.replaceAll("}" + Pattern.quote(separator), "}\\)")
.replaceAll("}$", "}\\)"); // could be integrated in above regex
}
private String getSeparator(final String format) {
final var begin = format.indexOf("}");
final var end = format.indexOf("{", begin);
return format.substring(begin + 1, end);
}
private String createReplacement(final String format) {
final var separator = getSeparator(format);
var replacement = format.replaceAll("^\\{\\d", "\\$X")
.replaceAll("}" + Pattern.quote(separator) + "\\{\\d", separator + "\\$X")
.replaceAll("}$", "");
var counter = 1;
while (replacement.contains("X")) {
replacement = replacement.replaceFirst("X", Integer.toString(counter++));
}
return replacement;
}
It's not my best piece of work but works with dynamic format strings.
Here's something to get you started. Feel free to modify the code to meet your needs.
public class ArbitraryFormat {
public static void main(String[] args) {
ArbitraryFormat arbitraryFormat = new ArbitraryFormat("00 00000 00000 0");
System.out.println(arbitraryFormat.format(1234567890123L));
System.out.println(arbitraryFormat.format(123));
}
private int zeroCount;
private String formatter;
public ArbitraryFormat(String formatter) {
this.formatter = formatter;
this.zeroCount = countZeros(formatter);
}
public String format(long value) {
String tempFormatter = "%" + zeroCount + "s";
String temp = String.format(tempFormatter, value);
StringBuilder builder = new StringBuilder();
int tempIndex = 0;
for (int index = 0; index < formatter.length(); index++) {
if (formatter.charAt(index) == '0') {
builder.append(temp.charAt(tempIndex++));
} else {
builder.append(formatter.charAt(index));
}
}
return builder.toString();
}
private int countZeros(String formatter) {
int count = 0;
int index = 0;
while (index < formatter.length()) {
int pos = formatter.indexOf('0', index);
if (pos >= 0) {
count++;
index = pos + 1;
} else {
index = formatter.length();
}
}
return count;
}
}
You can define your own formatter like this.
public class MyFormat extends NumberFormat {
final String format;
public MyFormat(String format) {
this.format = format;
}
#Override
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
throw new UnsupportedOperationException();
}
#Override
public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
toAppendTo.append(number);
for (int i = toAppendTo.length() - 1, j = format.length() - 1; i >= 0 && j >= 0; --i, --j) {
char fch = format.charAt(j);
if (fch != '*') {
toAppendTo.insert(i + 1, fch);
--j;
}
}
return toAppendTo;
}
#Override
public java.lang.Number parse(String source, ParsePosition parsePosition) {
throw new UnsupportedOperationException();
}
}
And
public static void main(String[] args) throws ParseException {
long number = 1234567890123L;
MyFormat mf1 = new MyFormat("* ***** ***** *");
MyFormat mf2 = new MyFormat("*-*** ***-*** * **");
System.out.println(mf1.format(number));
System.out.println(mf2.format(number));
}
output:
12 34567 89012 3
1-234 567-890 1 23
Thanks to #McPringle I finally implemented this solution:
public class MaskFormatter {
private char[] separators;
public String formatNumber(Number number, String pattern) {
if (number == null) {
return "";
} else {
separators = pattern.replace("0", "").toCharArray();
String string = number.toString();
String regex = createRegex(pattern);
String replacement = createReplacement(pattern);
return string.replaceAll(regex, replacement);
}
}
private String createRegex(String pattern) {
String[] parts = pattern.split("[" + createPatternFromSeparators() + "]");
StringBuilder sb = new StringBuilder();
for (String part : parts) {
sb.append("(\\d{").append(part.length()).append("})");
}
return sb.toString();
}
private String createReplacement(String pattern) {
String[] parts = pattern.split("[" + createPatternFromSeparators() + "]");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
if (i > 0) {
char separator = separators[i - 1];
sb.append(separator);
}
sb.append("$").append(i + 1);
}
return sb.toString();
}
private String createPatternFromSeparators() {
Set<String> set = new HashSet<>();
for (char separator : separators) {
set.add(String.valueOf(separator));
}
return String.join("", set);
}
}
You can also use String.replaceAll(). Like the following example.
long value = 1234567890123L;
String str = String.valueOf(value);
//12 34567 89012 3
String str1 = str.replaceAll("^(.{2})(.{5})(.{5})(.{1})$", "$1 $2 $3 $4");
System.out.println(str1); //Prints: 12 34567 89012 3
//1-234 567-890 1 23
String str2 = str.replaceAll("^(.{1})(.{3})(.{3})(.{3})(.{1})(.{2})$", "$1-$2 $3-$4 $5 $6");
System.out.println(str2); //Prints: 1-234 567-890 1 23
Related
The characters in a sentence should be reversed and not the words
I have tried the below code
public class ReverseWords {
public static void main(String[] args) {
ReverseWords obj = new ReverseWords();
obj.reverseWordInMyString("It Costs 25000rs for 1 LCD Projector");
obj.reverseWordInMyString("8990.33 ");
}
public void reverseWordInMyString(String str)
{
String[] words = str.split(" ");
String reversedString = "";
for (int i = 0; i < words.length; i++)
{
String word = words[i];
String reverseWord = "";
boolean numeric = true;
try {
Double num = Double.parseDouble(word);
} catch (NumberFormatException e) {
numeric = false;
}
if(!numeric) {
for (int j = word.length()-1; j >= 0; j--)
{
reverseWord = reverseWord + word.charAt(j);
}
reversedString = reversedString + reverseWord + " ";
}
else {
reversedString = reversedString + word + " ";
}
}
System.out.println(str);
System.out.println(reversedString);
}
}
The output which I am getting is : tI stsoC sr00052 rof 1 DCL rotcejorP
The Expected output is :tI stsoC 25000sr rof 1 DCL rotcejorP
This should do it.
String str = "It Costs 25000rs for 1 LCD Projector";
StringBuilder sb = new StringBuilder(str);
Matcher m = Pattern.compile("([A-Za-z]+)").matcher(str);
StringBuilder temp = new StringBuilder();
while (m.find()) {
String rev = temp.append(m.group(1)).reverse().toString();
sb.replace(m.start(), m.end(), rev);
temp.setLength(0);
}
String reversed = sb.toString();
System.out.println(reversed);
import java.util.Arrays;
import java.util.stream.Collectors;
public class ReverseWords {
public static void main(String[] args) {
String a = "It Costs 25000rs for 1 LCD Projector";
String output = Arrays.stream(a.split(" "))
.map(s -> s.matches(".*\\d.*") ? reverseWithNumbers(s) : reverse(s))
.collect(Collectors.joining(" "));
System.out.println(output);
}
public static String reverseWithNumbers(String input) {
return Arrays.stream(input.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)"))
.map(s -> s.matches(".*\\d.*") ? s : reverse(s))
.collect(Collectors.joining(""));
}
public static String reverse(String input) {
return new StringBuilder().append(input).reverse().toString();
}
}
I don't like this solution, since I don't like while-loops in general, but it seems to be the cleanest way to do this char-by-char (please tell me how it can be improved). It also should be the most efficient solution. I understood the problem as "sequences of alphabetical chars should be reversed".
public class ReverseWords {
private static void reverse(char[] a, int left, int right) {
right --;
while (left < right) {
char temp = a[left];
a[left] = a[right];
a[right] = temp;
left++;
right--;
}
}
public static void main(String[] args) {
char[] a = "It Costs 25000rs for 1 LCD Projector".toCharArray();
int i = 0;
while (i < a.length) {
if (!Character.isAlphabetic(a[i])) {
i++;
continue;
}
int j = i + 1;
while (j < a.length && Character.isAlphabetic(a[j])) {
j++;
}
reverse(a, i, j);
i = j;
}
System.out.println(new String(a));
}
}
How about using regex? Matching on something like [a-zA-Z]*[^(\d*)] will isolate your Alpha characters without matching with your digits. Depending on the requirements of the project, that statement may have to be modified slightly, but should get you on the right track.
Is there something I am doing wrong here? When printed I get "*" and I need to get "-32". I am parsing each individual word and returning the last word.
public static void main(String[] args) {
System.out.println(stringParse("3 - 5 * 2 / -32"));
}
public static String stringParse(String string) {
String[] word = new String[countWords(string)];
string = string + " ";
for (int i = 0; i <= countWords(string); i++) {
int space = string.indexOf(" ");
word[i] = string.substring(0, space);
string = string.substring(space+1);
}
return word[countWords(string)];
}
public static int countWords(String string) {
int wordCount = 0;
if (string.length() != 0) {
wordCount = 1;
}
for (int i = 0; i <= string.length()-1; i++){
if (string.substring(i,i+1).equals(" ")) {
wordCount++;
}
}
return wordCount;
}
You could instead split the string by white space using "\\s+" and return the last element of that array. This will return the last word.
public static String stringParse(String s){
return s.split("\\s+")[s.split("\\s+").length-1];
}
In this case you can use regular expressions too :
public static void main(String[] args) {
System.out.println(stringParse("3 - 5 * 2 / -32"));
}
public static String stringParse(String string) {
String found = null;
Matcher m = Pattern.compile("\\s((\\W?)\\w+)$", Pattern.CASE_INSENSITIVE)
.matcher(string);
while (m.find()) {found = m.group();}
return found;
}
Given a string in Java, how can I obtain a new string where all adjacent sequences of digits are reversed?
My code:
import static java.lang.System.*;
public class P2
{
public static void main(String[] args)
{
if(args.length < 1)
{
err.printf("Usage: java -ea P2 String [...]\n");
exit(1);
}
String[] norm = new String[args.length];
for(int i = 0; i<norm.length;i++)
{
norm[i] = args[i];
}
}
public String invertDigits(String[] norm)
{
}
}
And as an example, this is what it should do:
Inputs: 1234 abc9876cba a123 312asd a12b34c56d
1234 -> 4321
abc9876cba -> abc6789cba
a123 -> a321
312asd -> 213asd
a12b34c56d -> a21b43c65d
Although the question is heavily downvoted, the proposed problem seems clear now. I chose to solve it using a regular expression match in a recursive function.
private static String reverseDigits(String s) {
// the pattern will match a sequence of 1 or more digits
Matcher matcher = Pattern.compile("\\d+").matcher(s);
// fetch the position of the next sequence of digits
if (!matcher.find()) {
return s; // no more digits
}
// keep everything before the number
String pre = s.substring(0, matcher.start());
// take the number and reverse it
String number = matcher.group();
number = new StringBuilder(number).reverse().toString();
// continue with the rest of the string, then concat!
return pre + number + reverseDigits(s.substring(matcher.end()));
}
And here's the iterative approach.
private static String reverseDigits(String s) {
//if (s.isEmpty()) return s;
String res = "";
int base = 0;
Matcher matcher = Pattern.compile("\\d+").matcher(s);
while (!matcher.hitEnd()) {
if (!matcher.find()) {
return res + s.substring(base);
}
String pre = s.substring(base, matcher.start());
base = matcher.end();
String number = matcher.group();
number = new StringBuilder(number).reverse().toString();
res += pre + number;
}
return res;
}
String str = "1234";
//indexes
int i = 0, j = str.length()-1;
// find digits (if any)
while (!Character.isDigit(str.charAt(i)) && i < str.length()) {
i++;
}
while (!Character.isDigit(str.charAt(j)) && j >= 0) {
j--;
}
// while we havent searched all the digits
while (i < j) {
// switch digits
str = str.substring(0, i) + str.charAt(j) + str.substring(i + 1, j) + str.charAt(i) + str.substring(j + 1);
i++;
j--;
// find the next digits
while (!Character.isDigit(str.charAt(i)) && i < str.length()) {
i++;
}
while (!Character.isDigit(str.charAt(j)) && j >= 0) {
j--;
}
}
System.out.println(str);
Another dynamic approach without using regex classes:
public static String reverseOnlyNumbers(String s) {
StringBuilder digits = new StringBuilder();
StringBuilder result = new StringBuilder();
boolean start = false;
for (int i = 0; i < s.length(); i++) {
Character c = s.charAt(i);
if (Character.isDigit(c)) {
start = true;
digits.append(c);
}else {
start = false;
if (digits.length() > 0) {
result.append(digits.reverse().toString());
digits = new StringBuilder();
}
result.append(c);
}
}
return start ? result.append(digits.reverse()).toString() : result.toString();
}
i have two strings s1 and s2 and i would like to sort s2 based on the order of appearance of letters in s1 and if other alphabets are left in s2 sort them alphabetically.
Assume i have the following;
String s1 = "war";
String s2 = "Its awesome being a programmer";
output: waaarrrIbeeeeggimmmnoopsst.
I have written a code to do that already though buut i was wondering if its possible using the comparator/comparable interface to solve it.
Listed below is my code snippet.
public class Sort {
private static String a = "war";
private static String b = "Its awesome being a programmer";
static List<Character> list = new ArrayList<>();
static public void main(String[] args) {
Character s;
Character x;
System.out.println("String to be sorted: '" + b + "'");
System.out.println("Key for sort: '" + a + "'");
/*
* put all the string in a list
*/
for (int i = 0; i < b.length(); i++) {
s = b.charAt(i);
if (s != ' ') {
list.add(s);
}
}
/*
* compare individual chac in key with individaul char in string to sort
*/
StringBuilder sb = new StringBuilder();
for (int j = 0; j < a.length(); j++) {
x = a.charAt(j);
for (int k = 0; k < b.length(); k++) {
s = b.charAt(k);
if (x == s) {
sb.append(s);
list.remove(x);
}
}
}
/*
* check if list is empty if not, sort and append the rest to the stringbuilder
*/
if (!list.isEmpty()) {
Collections.sort(list);
for (char c : list) {
sb.append(c);
}
}
System.out.println("Sorted version of string: '" + sb.toString() + "'");
}
}
private static String a = "war";
private static String b = "Its awesome being a programmer".replace(" ","");
private static String answer = "waaarrrIbeeeeggimmmnoopsst";
public static void main(String[] args) {
List<String> characters = new ArrayList<String>(b.length());
for (int i=0;i<b.length();i++){
characters.add(String.valueOf(b.charAt(i)));
}
Collections.sort(characters,new CompareIt(a));
String sortedString = listToString(characters);
System.out.println(sortedString);
System.out.println(answer);
System.out.println(answer.equals(sortedString));
}
private static String listToString(List<String> listOfStrings){
StringBuilder builder = new StringBuilder();
for (String str : listOfStrings){
builder.append(str);
}
return builder.toString();
}
private static class CompareIt implements Comparator<String>{
private final String source;
public CompareIt(String source) {
super();
this.source = source;
}
public int compare(String o1, String o2) {
int i1 = source.indexOf(o1);
int i2 = source.indexOf(o2);
if (i1==-1 && i2!=-1){
return 1;
} else if (i1!=-1 && i2==-1){
return -1;
} else if (i1!=-1 && i2!=-1){
return i1 > i2 ? 1:-1;
} else {
return o1.compareTo(o2);
}
}
}
This seems to work.
EDITED: To include sysout that result matches expected answer provided in question.
EDIT2: Typo with final indexed comparison I had ? 1:0 instead of 1:-1.
public static void main(String[] args) {
String s1 = "war";
String s2 = "Its awesome being a programmer";
String result = "";
for (int i = 0; i < s1.length(); i++) {
int len = s2.length()
- s2.replace(String.valueOf(s1.charAt(i)), "").length();
s2 = s2.replace(String.valueOf(s1.charAt(i)), "").replace(" ", "");
for (int j = 0; j < len; j++)
result = result + String.valueOf(s1.charAt(i));
}
char[] remaining = s2.toCharArray();
Arrays.sort(remaining);
for (Character c : remaining)
result = result + String.valueOf(c);
System.out.println(result);
}
Try this: I tried without using any interface.
Output:
waaarrrIbeeeeggimmmnoopsst
public static Comparator<Character> compareOn(final String key) {
return new Comparator<Character>() {
public int compare(Character c1, Character c2) {
final int indexInKey1 = key.indexOf(c1);
final int indexInKey2 = key.indexOf(c2);
final int result;
if (indexInKey1 == -1 && indexInKey2 == -1) {
result = c1.compareTo(c2); //fall back to natural ordering
} else {
if (indexInKey1 == -1) {
result = 1;
} else if (indexInKey2 == -1) {
result = -1;
} else {
result = indexInKey1 - indexInKey2;
}
}
return result;
}
};
}
public static void main(String[] args) {
final String a = "war";
final String b = "Its awesome being a programmer";
final List<Character> chars = new ArrayList<Character>();
for (char c: b.toCharArray()) {
if (c != ' ') {
chars.add(c);
}
}
Collections.sort(chars, compareOn(a));
System.out.println(chars);
}
I'm suppose to replace a "L" in a string every time it is found in the string HELLO WORLD, with "x". and the x is to increased every occurrence of L.
input: "HELLO WORLD"
output: "HExxxO WORxxxD"
use only String methods: .length; .indexOf; .substring
and .concat (or +).
EDIT
Here's my try:
public static String replace(String input,String pattern) {
String result = " ";
int stringLength;
int patternIndex;
while (input !=null) {
patternIndex = input.indexOf(pattern);
stringLength = input.length();
}
return result;
}
i only find the index of the pattern and the length of the string having problem with replacing the character.
First: sane solution:
StringBuilder sb = new StringBuilder();
StringBuilder r = new StringBuilder();
for( char c : "HELLO LAZY LIMBO WORLD" .toCharArray() ) {
if( c == 'L' ) {
sb.append(r.append('x'));
} else {
sb.append( c );
}
}
return sb.toString() );
Then modified to meed the criteria of only using valid methods .length; .indexOf; .substring and .concat (or +) ( removing toCharArray(); and StringBuilder )
public static String replace( String input ){
String replacement = "";
int iot = -1;
while( ( iot = input.indexOf('L')) > -1 ) {
input = input.substring(0,iot) +
( replacement+='x' ) +
input.substring(iot+1);
}
return input;
}
That one look like a for loop. Let's change it!
With only two statements ( declr and a for loop ):
public static String replace( String in ){
String x = "";
for( int i = 0; ( i = in.indexOf('L',i)) > -1 ;
in = in.substring(0,i++) + ( x=x+'x' ) + in.substring(i) );
return in;
}
Yields:
HExxxO xxxAZY xxxxIMBO WOxxxxxR
Now, that's! a for loop. I almost make Java look like perl.
static String xform(String helloWorld) {
if (helloWorld.intern() != "HELLO WORLD")
throw new IllegalArgumentException("bad World");
return "HExxxO WORxxxD";
}
and here is a very special version for the ones w/o sense of humor: the special edition - loplez&funless
public class TheLoop {
public static void main(String[] args) throws Throwable{
System.out.println(xForm2("Hello World -L".toUpperCase(),0));
}
static String xForm2(String s,int k){
return k<-1?"x"+xForm2(s,k+1):(k==-1?"":("L".equals(s.substring(0,1))?xForm2(s,-(k+1)-1) :s.substring(0,1))+(s.length()==1?"":xForm2(s.substring(1), "L".equals(s.substring(0,1))?k+1:k)));
}
}
200 bounty if anyone manages to write the function in a single line (single semicolon) and uglier than this
String x_ify(String input) {
String output = "";
int start = 0;
int count = 0;
int nextL;
while ((nextL = input.indexOf('L', start)) >= 0) {
if (nextL > start) {
output = output + input.substring(start, nextL);
}
++count;
for (int i = 0; i < count; ++i) {
output = output + "x";
}
start = nextL + 1;
}
if (start < input.length()) {
output += input.substring(start);
}
return output;
}
char charToReplace = 'l';
String str = " Hello World";
char newChar = 'x';
String newString = "x";
StringBuilder result = new StringBuilder();
for (int index = 0; index < str.length(); index++) {
if (str.charAt(index) == charToReplace) {
result.append(newString);
newString += newChar;
} else {
result.append(str.charAt(index));
}
}
System.out.println(result);
Note: it can be optimized
A bodyless one-liner for statement, specially for bestsss:
public static String replace(String s) {
for (String x=""; s.indexOf('L') > -1 ; s = s.substring(0,s.indexOf('L')) + ( x=x+'x' ) + s.substring(s.indexOf('L')+1) );
return s;
}
Although not using the standard functions you mentioned but this is an alternate way:
public static void first()
{
String input = "HELLO WORLD";
String X = "";
int numofL = input.length() - input.replaceAll("L+", "").length();
for(int i=0;i<numofL;i++)
X += "x";
String output = input.replaceAll("L+", X);
System.out.println(output);
}
public static void main(String[] args) {
String input = "HELLO WORLD";
String output = "";
String repl = "x";
int idx, start = 0;
while ((idx = input.indexOf('L', start)) > 0) {
output += input.substring(start, idx);
output += repl;
start = idx + 1;
repl += "x";
}
if (start < input.length()) {
output += input.substring(start);
}
System.out.println(output);
}
public class Main {
public static void main(String[] args) {
System.out.println(replace("hello world", "x"));
}
public static String replace(String in, String xs) {
return in.indexOf("l") != -1 ? replace(in.substring(0, in.indexOf("l")) + xs + in.substring(in.indexOf("l") + 1), xs + "x") : in;
}
}
public class ReplaceChar {
public static void replaceChar(String s, StringBuilder sb, int depth){
int i = s.indexOf('L');
if(i==-1){
return;
}
else
sb.append(s.substring(0,i));
for(int j=depth;j>0;j--){
sb.append('x');
}
replaceChar(s.substring(i+1),sb,++depth);
}
public static void main(String[] args){
StringBuilder sb = new StringBuilder();
System.out.println("main "+sb);
replaceChar("HELLO WORLD",sb,1);
}
}