Java detect first level "if" conditions in a string with regex - java

I'm trying to detect first level "if" conditions in a piece of text.
Example text:
if (a == 5) {
method1();
method2()
}
if (a == 6) {
method1();
if (a < 2) {
method3();
}
}
if (a >= 8 && a <= 13) {
method5(a);
int[] b = new int[a];
for(int i = 0; i < a; i++) {
if (i == 0) {
b[i] = i * 4;
continue;
}
b[i] = i * 2;
}
method4(b);
}
if (a > 16) {
method6();
}
This is what I got so far:
public class HelloWorld
{
public static void main(String[] args)
{
String text = "if (a == 5) {\n\tmethod1();\n\tmethod2()\n}\nif (a == 6) {\n\tmethod1();\n\tif (a < 2) {\n\t\tmethod3();\n\t}\n}\nif (a >= 8 && a <= 13) {\n\tmethod5(a);\n\tint[] b = new int[a];\n\tfor(int i = 0; i < a; i++) {\n\t\tif (i == 0) {\n\t\t\tb[i] = i * 4;\n\t\t\tcontinue;\n\t\t}\n\t\tb[i] = i * 2;\n\t}\n\tmethod4(b);\n}\nif (a > 16) {\n\tmethod6();\n}";
for(String line : text.split("if (.*) \\{")) {
System.out.println("Line: " + line);
}
}
}
Output:
Line:
Line:
method1();
method2()
}
Line:
method1();
Line:
method3();
}
}
Line:
method5(a);
int[] b = new int[a];
for(int i = 0; i < a; i++) {
Line:
b[i] = i * 4;
continue;
}
b[i] = i * 2;
}
method4(b);
}
Line:
method6();
}
It also prints nested ifs. I only want the first level ones. And the if will disappear when printing the line. I want the if to show too.
I basically want to group all first level ifs into one string. Can some one help me with this?

Since that you have to deal with nested brackets, the appropriate regex will be hard to maintain as described here in SO How to match string within parentheses (nested) in Java?
My solution is:
Do some preprocessing to replace the nested brackets
Capture the if content using regex
Finally, postprocessing to hand over the real brackets
package demo;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Parser {
private static final char OPENED_BRACKET = '{';
private static final char CLOSED_BRACKET = '}';
private static final String OPENED_BRACKET_REPLACOR = "##OPENED_BRACKET_REPLACOR##";
private static final String CLOSED_BRACKET_REPLACOR = "##CLOSED_BRACKET_REPLACOR##";
private static final String REGEX = "\\{((.|\\n|\r|\t)*?)\\}";
private static final Pattern PATTERN = Pattern.compile(REGEX);
public String preprocessing(String origin) {
StringBuilder replaced = new StringBuilder();
int opened = 0;
for(int index = 0 ; index < origin.length() ; index++) {
char current_char = origin.charAt(index);
String processed = Character.toString(current_char);
if(current_char == OPENED_BRACKET) {
if(opened++ > 0) {
processed = OPENED_BRACKET_REPLACOR;
}
}
else if(current_char == CLOSED_BRACKET) {
if(--opened > 0) {
processed = CLOSED_BRACKET_REPLACOR;
}
}
replaced.append(processed);
}
return replaced.toString();
}
public List<String> extract(String source) {
final Matcher matcher = PATTERN.matcher(source);
List<String> list = new ArrayList<>();
while(matcher.find()) {
list.add(matcher.group(1));
}
return list;
}
public List<String> postprocessing(List<String> source) {
List<String> result = new ArrayList<>();
for(String src: source) {
result.add(src.replaceAll(OPENED_BRACKET_REPLACOR, Character.toString(OPENED_BRACKET))
.replaceAll(CLOSED_BRACKET_REPLACOR, Character.toString(CLOSED_BRACKET)));
}
return result;
}
public static void main(String[] args) {
Parser parser = new Parser();
String code = "if (a == 6) { method1(); if (a < 2) { method3(); } }if (a == 5) { method1();\n\r" +
" method2() }";
String preprocessed = parser.preprocessing(code);
List<String> extracted = parser.extract(preprocessed);
List<String> postprocessed = parser.postprocessing(extracted);
for(String ifContent: postprocessed) {
System.out.println("Line: " + ifContent);
}
}
}
Will ouptput:
Line: method1(); if (a < 2) { method3(); }
Line: method1();
method2()

Related

Find the first non repeating character in a string

I m writing a method to find the first non repeating character in a string. I saw this method in a previous stackoverflow question
public static char findFirstNonRepChar(String input){
char currentChar = '\0';
int len = input.length();
for(int i=0;i<len;i++){
currentChar = input.charAt(i);
if((i!=0) && (currentChar!=input.charAt(i-1)) && (i==input.lastIndexOf(currentChar))){
return currentChar;
}
}
return currentChar;
}
I came up with a solution using a hashtable where I have two for loops (not nested) where I interate through the string in one loop writing down each occurance of a letter (for example in apple, a would have 1, p would have 2, etc.) then in the second loop I interate through the hashtable to see which one has a count of 1 first. What is the benefit to the above method over what I came up with? I am new to Java does having two loops (not nested) hinder time complexity. Both these algorithms should have O(n) right? Is there another faster, less space complexity algorithm for this question than these two solutions?
public class FirstNonRepeatCharFromString {
public static void main(String[] args) {
String s = "java";
for(Character ch:s.toCharArray()) {
if(s.indexOf(ch) == s.lastIndexOf(ch)) {
System.out.println("First non repeat character = " + ch);
break;
}
}
}
}
As you asked if your code is from O(n) or not, I think it's not, because in the for loop, you are calling lastIndexOf and it's worst case is O(n). So it is from O(n^2).
About your second question: having two loops which are not nested, also makes it from O(n).
If assuming non unicode characters in your input String, and Uppercase or Lowercase characters are assumed to be different, the following would do it with o(n) and supports all ASCII codes from 0 to 255:
public static Character getFirstNotRepeatedChar(String input) {
byte[] flags = new byte[256]; //all is initialized by 0
for (int i = 0; i < input.length(); i++) { // O(n)
flags[(int)input.charAt(i)]++ ;
}
for (int i = 0; i < input.length(); i++) { // O(n)
if(flags[(int)input.charAt(i)] > 0)
return input.charAt(i);
}
return null;
}
Thanks to Konstantinos Chalkias hint about the overflow, if your input string has more than 127 occurrence of a certain character, you can change the type of flags array from byte[] to int[] or long[] to prevent the overflow of byte type.
Hope it would be helpful.
The algorithm you showed is slow: it looks for each character in the string, it basically means that for each character you spend your time checking the string twice!! Huge time loss.
The best naive O(n) solution basically holds all the characters in order of insertion (so the first can be found) and maps a mutable integer to them. When we're done, analyzing, we go through all the entries and return the first character that was registered and has a count of 1.
There are no restrictions on the characters you can use. And AtomicInteger is available with import java.util.concurrent.atomic.AtomicInteger.
Using Java 8:
public static char findFirstNonRepChar(String string) {
Map<Integer,Long> characters = string.chars().boxed()
.collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()));
return (char)(int)characters.entrySet().stream()
.filter(e -> e.getValue() == 1L)
.findFirst()
.map(Map.Entry::getKey)
.orElseThrow(() -> new RuntimeException("No unrepeated character"));
}
Non Java 8 equivalent:
public static char findFirstNonRepChar(String string) {
Map<Character, AtomicInteger> characters = new LinkedHashMap<>(); // preserves order of insertion.
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
AtomicInteger n = characters.get(c);
if (n == null) {
n = new AtomicInteger(0);
characters.put(c, n);
}
n.incrementAndGet();
}
for (Map.Entry<Character, AtomicInteger> entry: characters.entries()) {
if (entry.getValue().get() == 1) {
return entry.getKey();
}
}
throw new RuntimeException("No unrepeated character");
}
import java.util.LinkedHashMap;
import java.util.Map;
public class getFirstNonRep {
public static char get(String s) throws Exception {
if (s.length() == 0) {
System.out.println("Fail");
System.exit(0);
} else {
Map<Character, Integer> m = new LinkedHashMap<Character, Integer>();
for (int i = 0; i < s.length(); i++) {
if (m.containsKey(s.charAt(i))) {
m.put(s.charAt(i), m.get(s.charAt(i)) + 1);
} else {
m.put(s.charAt(i), 1);
}
}
for (Map.Entry<Character, Integer> hm : m.entrySet()) {
if (hm.getValue() == 1) {
return hm.getKey();
}
}
}
return 0;
}
public static void main(String[] args) throws Exception {
System.out.print(get("Youssef Zaky"));
}
}
This solution takes less space and less time, since we iterate the string only one time.
Works for any type of characters.
String charHolder; // Holds
String testString = "8uiuiti080t8xt8t";
char testChar = ' ';
int count = 0;
for (int i=0; i <= testString.length()-1; i++) {
testChar = testString.charAt(i);
for (int j=0; j < testString.length()-1; j++) {
if (testChar == testString.charAt(j)) {
count++;
}
}
if (count == 1) { break; };
count = 0;
}
System.out.println("The first not repeating character is " + testChar);
I accumulated all possible methods with string length 25'500 symbols:
private static String getFirstUniqueChar(String line) {
String result1 = null, result2 = null, result3 = null, result4 = null, result5 = null;
int length = line.length();
long start = System.currentTimeMillis();
Map<Character, Integer> chars = new LinkedHashMap<Character, Integer>();
char[] charArray1 = line.toCharArray();
for (int i = 0; i < length; i++) {
char currentChar = charArray1[i];
chars.put(currentChar, chars.containsKey(currentChar) ? chars.get(currentChar) + 1 : 1);
}
for (Map.Entry<Character, Integer> entry : chars.entrySet()) {
if (entry.getValue() == 1) {
result1 = entry.getKey().toString();
break;
}
}
long end = System.currentTimeMillis();
System.out.println("1st test:\n result: " + result1 + "\n time: " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
String current = Character.toString(line.charAt(i));
String left = line.substring(0, i);
if (!left.contains(current)) {
String right = line.substring(i + 1);
if (!right.contains(current)) {
result2 = current;
break;
}
}
}
end = System.currentTimeMillis();
System.out.println("2nd test:\n result: " + result2 + "\n time: " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
char currentChar = line.charAt(i);
if (line.indexOf(currentChar) == line.lastIndexOf(currentChar)) {
result3 = Character.toString(currentChar);
break;
}
}
end = System.currentTimeMillis();
System.out.println("3rd test:\n result: " + result3 + "\n time: " + (end - start));
start = System.currentTimeMillis();
char[] charArray4 = line.toCharArray();
for (int i = 0; i < length; i++) {
char currentChar = charArray4[i];
int count = 0;
for (int j = 0; j < length; j++) {
if (currentChar == charArray4[j] && i != j) {
count++;
break;
}
}
if (count == 0) {
result4 = Character.toString(currentChar);
break;
}
}
end = System.currentTimeMillis();
System.out.println("4th test:\n result: " + result4 + "\n time: " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
char currentChar = line.charAt(i);
int count = 0;
for (int j = 0; j < length; j++) {
if (currentChar == line.charAt(j) && i != j) {
count++;
break;
}
}
if (count == 0) {
result5 = Character.toString(currentChar);
break;
}
}
end = System.currentTimeMillis();
System.out.println("5th test:\n result: " + result5 + "\n time: " + (end - start));
return result1;
}
And time results (5 times):
1st test:
result: g
time: 13, 12, 12, 12, 14
2nd test:
result: g
time: 55, 56, 59, 70, 59
3rd test:
result: g
time: 2, 3, 2, 2, 3
4th test:
result: g
time: 3, 3, 2, 3, 3
5th test:
result: g
time: 6, 5, 5, 5, 6
public static char NonReapitingCharacter(String str) {
Set<Character> s = new HashSet();
char ch = '\u0000';
for (char c : str.toCharArray()) {
if (s.add(c)) {
if (c == ch) {
break;
} else {
ch = c;
}
}
}
return ch;
}
Okay I misread the question initially so here's a new solution. I believe is this O(n). The contains(Object) of HashSet is O(1), so we can take advantage of that and avoid a second loop. Essentially if we've never seen a specific char before, we add it to the validChars as a potential candidate to be returned. The second we see it again however, we add it to the trash can of invalidChars. This prevents that char from being added again. At the end of the loop (you have to loop at least once no matter what you do), you'll have a validChars hashset with n amount of elements. If none are there, then it will return null from the Character class. This has a distinct advantage as the char class has no good way to return a 'bad' result so to speak.
public static Character findNonRepeatingChar(String x)
{
HashSet<Character> validChars = new HashSet<>();
HashSet<Character> invalidChars = new HashSet<>();
char[] array = x.toCharArray();
for (char c : array)
{
if (validChars.contains(c))
{
validChars.remove(c);
invalidChars.add(c);
}
else if (!validChars.contains(c) && !invalidChars.contains(c))
{
validChars.add(c);
}
}
return (!validChars.isEmpty() ? validChars.iterator().next() : null);
}
If you are only interested for characters in the range a-z (lowercase as OP requested in comments), you can use this method that requires a minimum extra storage of two bits per character Vs a HashMap approach.
/*
* It works for lowercase a-z
* you can scale it to add more characters
* eg use 128 Vs 26 for ASCII or 256 for extended ASCII
*/
public static char getFirstNotRepeatedChar(String input) {
boolean[] charsExist = new boolean[26];
boolean[] charsNonUnique = new boolean[26];
for (int i = 0; i < input.length(); i++) {
int index = 'z' - input.charAt(i);
if (!charsExist[index]) {
charsExist[index] = true;
} else {
charsNonUnique[index] = true;
}
}
for (int i = 0; i < input.length(); i++) {
if (!charsNonUnique['z' - input.charAt(i)])
return input.charAt(i);
}
return '?'; //example return of no character found
}
In case of two loops (not nested) the time complexity would be O(n).
The second solution mentioned in the question can be implemented as:
We can use string characters as keys to a map and maintain their count. Following is the algorithm.
1.Scan the string from left to right and construct the count map.
2.Again, scan the string from left to right and check for count of each character from the map, if you find an element who’s count is 1, return it.
package com.java.teasers.samples;
import java.util.Map;
import java.util.HashMap;
public class NonRepeatCharacter {
public static void main(String[] args) {
String yourString = "Hi this is javateasers";//change it with your string
Map<Character, Integer> characterMap = new HashMap<Character, Integer>();
//Step 1 of the Algorithm
for (int i = 0; i < yourString.length(); i++) {
Character character = yourString.charAt(i);
//check if character is already present
if(null != characterMap.get(character)){
//in case it is already there increment the count by 1.
characterMap.put(character, characterMap.get(character) + 1);
}
//in case it is for the first time. Put 1 to the count
else
characterMap.put(character, 1);
}
//Step 2 of the Algorithm
for (int i = 0; i < yourString.length(); i++) {
Character character = yourString.charAt(i);
int count = characterMap.get(character);
if(count == 1){
System.out.println("character is:" + character);
break;
}
}
}
}
public char firstNonRepeatedChar(String input) {
char out = 0;
int length = input.length();
for (int i = 0; i < length; i++) {
String sub1 = input.substring(0, i);
String sub2 = input.substring(i + 1);
if (!(sub1.contains(input.charAt(i) + "") || sub2.contains(input
.charAt(i) + ""))) {
out = input.charAt(i);
break;
}
}
return out;
}
Since LinkedHashMap keeps the order of insertion
package com.company;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] argh) {
Scanner sc = new Scanner(System.in);
String l = sc.nextLine();
System.out.println(firstCharNoRepeated(l));
}
private static String firstCharNoRepeated(String l) {
Map<String, Integer> chars = new LinkedHashMap();
for(int i=0; i < l.length(); i++) {
String c = String.valueOf(l.charAt(i));
if(!chars.containsKey(c)){
chars.put(c, i);
} else {
chars.remove(c);
}
}
return chars.keySet().iterator().next();
}
}
Few lines of code, works for me.
public class FirstNonRepeatingCharacter {
final static String string = "cascade";
public static void main(String[] args) {
char[] charArr = string.toCharArray();
for (int i = 0; charArr.length > i; i++) {
int count = 0;
for (int j = 0; charArr.length > j; j++) {
if (charArr[i] == charArr[j]) {
count++;
}
}
if (count == 1){
System.out.println("First Non Repeating Character is: " + charArr[i]);
break;
}
}
}
}
Constraint for this solution:
O(n) time complexity. My solution is O(2n), follow Time Complexity analysis,O(2n) => O(n)
import java.util.HashMap;
public class FindFirstNonDuplicateCharacter {
public static void main(String args[]) {
System.out.println(findFirstNonDuplicateCharacter("abacbcefd"));
}
private static char findFirstNonDuplicateCharacter(String s) {
HashMap<Character, Integer> chDupCount = new HashMap<Character, Integer>();
char[] charArr = s.toCharArray();
for (char ch: charArr) { //first loop, make the tables and counted duplication by key O(n)
if (!chDupCount.containsKey(ch)) {
chDupCount.put(ch,1);
continue;
}
int dupCount = chDupCount.get(ch)+1;
chDupCount.replace(ch, dupCount);
}
char res = '-';
for(char ch: charArr) { //second loop, get the first duplicate by count number, O(2n)
// System.out.println("key: " + ch+", value: " + chDupCount.get(ch));
if (chDupCount.get(ch) == 1) {
res = ch;
break;
}
}
return res;
}
}
Hope it help
char firstNotRepeatingCharacter(String s) {
for(int i=0; i< s.length(); i++){
if(i == s.lastIndexOf(s.charAt(i)) && i == s.indexOf(s.charAt(i))){
return s.charAt(i);
}
}
return '_';
}
String a = "sampapl";
char ar[] = a.toCharArray();
int dya[] = new int[256];
for (int i = 0; i < dya.length; i++) {
dya[i] = -1;
}
for (int i = 0; i < ar.length; i++) {
if (dya[ar[i]] != -1) {
System.out.println(ar[i]);
break;
} else {
dya[ar[i]] = ar[i];
}
}
This is solution in python:
input_str = "interesting"
#input_str = "aabbcc"
#input_str = "aaaapaabbcccq"
def firstNonRepeating(param):
counts = {}
for i in range(0, len(param)):
# Store count and index repectively
if param[i] in counts:
counts[param[i]][0] += 1
else:
counts[param[i]] = [1, i]
result_index = len(param) - 1
for x in counts:
if counts[x][0] == 1 and result_index > counts[x][1]:
result_index = counts[x][1]
return result_index
result_index = firstNonRepeating(input_str)
if result_index == len(input_str)-1:
print("no such character found")
else:
print("first non repeating charater found: " + input_str[result_index])
Output:
first non repeating charater found: r
import java.util.*;
public class Main {
public static void main(String[] args) {
String str1 = "gibblegabbler";
System.out.println("The given string is: " + str1);
for (int i = 0; i < str1.length(); i++) {
boolean unique = true;
for (int j = 0; j < str1.length(); j++) {
if (i != j && str1.charAt(i) == str1.charAt(j)) {
unique = false;
break;
}
}
if (unique) {
System.out.println("The first non repeated character in String is: " + str1.charAt(i));
break;
}
}
}
}
public class GFG {
public static void main(String[] args) {
String s = "mmjjjjmmn";
for (char c : s.toCharArray()) {
if (s.indexOf(c) == s.lastIndexOf(c)) {
System.out.println("First non repeated is:" + c);
break;
}
}
}
output = n
Non Repeated Character String in Java
public class NonRepeatedCharacter {
public static void main(String[] args) {
String s = "ffeeddbbaaclck";
for (int i = 0; i < s.length(); i++) {
boolean unique = true;
for (int j = 0; j < s.length(); j++) {
if (i != j && s.charAt(i) == s.charAt(j)) {
unique = false;
break;
}
}
if (unique) {
System.out.println("First non repeated characted in String \""
+ s + "\" is:" + s.charAt(i));
break;
}
}
}
}
Output:
First non repeated characted in String "ffeeddbbaaclck" is:l
For More Details
In this coding i use length of string to find the first non repeating letter.
package com.string.assingment3;
import java.util.Scanner;
public class FirstNonRepetedChar {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Enter a String : ");
String str = in.next();
char[] ch = str.toCharArray();
int length = ch.length;
int x = length;
for(int i=0;i<length;i++) {
x = length-i;
for(int j=i+1;j<length;j++) {
if(ch[i]!=ch[j]) {
x--;
}//if
}//inner for
if(x==1) {
System.out.println(ch[i]);
break;
}
else {
continue;
}
}//outer for
}
}// develope by NDM
In Kotlin
fun firstNonRepeating(string: String): Char?{
//Get a copy of the string
var copy = string
//Slice string into chars then convert them to string
string.map { it.toString() }.forEach {
//Replace first occurrance of that character and check if it still has it
if (copy.replaceFirst(it,"").contains(it))
//If it has the given character remove it
copy = copy.replace(it,"")
}
//Return null if there is no non-repeating character
if (copy.isEmpty())
return null
//Get the first character from what left of that string
return copy.first()
}
https://pl.kotl.in/KzL-veYNZ
public static void firstNonRepeatFirstChar(String str) {
System.out.println("The given string is: " + str);
for (int i = 0; i < str.length(); i++) {
boolean unique = true;
for (int j = 0; j < str.length(); j++) {
if (i != j && str.charAt(i) == str.charAt(j)) {
unique = false;
break;
}
}
if (unique) {
System.out.println("The first non repeated character in String is: " + str.charAt(i));
break;
}
}
}
Using Set with single for loop
public static Character firstNonRepeatedCharacter(String str) {
Character result = null;
if (str != null) {
Set<Character> set = new HashSet<>();
for (char c : str.toCharArray()) {
if (set.add(c) && result == null) {
result = c;
} else if (result != null && c == result) {
result = null;
}
}
}
return result;
}
You can achieve this in single traversal of String using LinkedHashSet as follows:
public static Character getFirstNonRepeatingCharacter(String str) {
Set<Character> result = new LinkedHashSet<>(256);
for (int i = 0; i< str.length(); ++i) {
if(!result.add(str.charAt(i))) {
result.remove(str.charAt(i));
}
}
if(result.iterator().hasNext()) {
return result.iterator().next();
}
return null;
}
For Java;
char firstNotRepeatingCharacter(String s) {
HashSet<String> hs = new HashSet<>();
StringBuilder sb =new StringBuilder(s);
for (int i = 0; i<s.length(); i++){
char c = sb.charAt(i);
if(s.indexOf(c) == i && s.indexOf(c, i+1) == -1 ) {
return c;
}
}
return '_';
}
public class FirstNonRepeatingChar {
public static void main(String[] args) {
String s = "hello world i am here";
s.chars().boxed()
.collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()))
.entrySet().stream().filter(e -> e.getValue() == 1).findFirst().ifPresent(e->System.out.println(e.getKey()));
}
}
package looping.concepts;
import java.util.Scanner;
public class Line {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter name: ");
String a = sc.nextLine();
int i = 0;
int j = 0;
for (i = 0; i < a.length(); i++) {
char ch = a.charAt(i);
int counter = 0;
// boolean repeat = false;
for (j = 0; j < a.length(); j++) {
if (ch == a.charAt(j)) {
counter++;
}
}
if (counter == 1) {
System.out.print(ch);
}
else
{
System.out.print("There is no non repeated character");
break;
}
}
}
}
import java.util.Scanner;
public class NonRepaeated1
{
public static void main(String args[])
{
String str;
char non_repeat=0;
int len,i,j,count=0;
Scanner s = new Scanner(System.in);
str = s.nextLine();
len = str.length();
for(i=0;i<len;i++)
{
non_repeat=str.charAt(i);
count=1;
for(j=0;j<len;j++)
{
if(i!=j)
{
if(str.charAt(i) == str.charAt(j))
{
count=0;
break;
}
}
}
if(count==1)
break;
}
if(count == 1)
System.out.print("The non repeated character is : " + non_repeat);
}
}
package com.test.util;
public class StringNoRepeat {
public static void main(String args[]) {
String st = "234123nljnsdfsdf41l";
String strOrig=st;
int i=0;
int j=0;
String st1="";
Character ch=' ';
boolean fnd=false;
for (i=0;i<strOrig.length(); i++) {
ch=strOrig.charAt(i);
st1 = ch.toString();
if (i==0)
st = strOrig.substring(1,strOrig.length());
else if (i == strOrig.length()-1)
st=strOrig.substring(0, strOrig.length()-1);
else
st=strOrig.substring(0, i)+strOrig.substring(i+1,strOrig.length());
if (st.indexOf(st1) == -1) {
fnd=true;
j=i;
break;
}
}
if (!fnd)
System.out.println("The first no non repeated character");
else
System.out.println("The first non repeated character is " +strOrig.charAt(j));
}
}

How do I reverse the order of only the digits in a string?

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();
}

How to show all combinations of IP address that can be created from a string of numbers?

I need to format the input string into IP address format, so I have the following code;however,the numbers are fixed and I am not sure how to generated different values for a single input.
Other constraints would be to make sure no group of numbers is more than 255, but in this case I just want to put them in four separate groups and each group must have 1 to 3 members.
Vimal's question: From provided string 19216801, I think you cant identify exact ip. It can be 192.168.0.1 or 19.216.80.1 or any other combination.
Answer: I am not looking for any specific IP I just need to show all the possible combinations.
Sample formats
Some of the combinations would be as following
Expected result | number of input characters
1.1.1.1 4
....
1.1.1.2 5
1.1.2.1
1.2.1.1
2.1.1.1
....
1.1.1.3 6
1.1.3.1
1.3.1.1
3.1.1.1
....
2.2.2.1 7
2.2.1.2
....
2.2.2.2 8
3.2.2.1
1.2.2.3
....
2.2.2.3 9
3.3.2.1
1.2.3.3
....
3.3.3.1 10
3.3.1.3
3.1.3.3
1.3.3.3
....
3.3.3.2 11
3.3.2.3
3.2.3.3
....
3.3.3.3 12
Code
String number = "19216801";
if (number.length() == 4) {
StringBuilder sb = new StringBuilder(number)
.insert(1, ".")
.insert(1, ".")
.insert(1, ".")
.insert(1, ".");
String output = sb.toString();
System.out.println(output);
}
if (number.length() == 8) {
StringBuilder sb = new StringBuilder(number)
.insert(2, ".")
.insert(2, ".")
.insert(2, ".")
.insert(2, ".");
String output = sb.toString();
System.out.println(output);
}
if (number.length() == 12) {
StringBuilder sb = new StringBuilder(number)
.insert(3, ".")
.insert(3, ".")
.insert(3, ".")
.insert(3, ".");
String output = sb.toString();
System.out.println(output);
}
Rephrase task in next way.
imagine that ip part can have zero digit so ... is valid
then we have number.length() - 3 elements and need to put 3 dot in any position
let a, b, c be length of part
first part can be any length for(int a = 0; a < l; a++)
second one must be shorter for(int b = 0; b < l-a; b++)
same with third, total length must be l. so l>=a+b+c is constraint. c
put points in it places.
first poin just after first part (don't forget tat at first step we cut one digit from each part).
second is after first part, first dot and second part ((a +1) + 1 + (b+1))
third one the same. skip first part (a+1), dot (+1), second part (+b+1), second dot (+1) and third part (c+1) = a+b+c+5
String number = "19216801";
int l = number.length() - 3;
for(int a = 0; a < l; a++) {
for(int b = 0; b < l-a; b++){
for(int c = 0; c <l-a-b; c++){
StringBuilder sb = new StringBuilder(number);
sb.insert(a+1, ".");
sb.insert(a+b+3, ".");
sb.insert(a+b+c+5, ".");
System.out.println(sb);
}
}
}
It pretty difficult to explain, most of code come from background of my mind i just write it.
Without further information you have to rely on conjecture to form an IP address from a variable length string.
You should disallow that and ensure that your string is 12 characters long.
Once you've formed a candidate IP address though, you can validate it using the following regular expression (using String.matches)
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
public class IPAddress {
static Queue<List<StringBuilder>> queue=new LinkedList<List<StringBuilder>>();
static int count =0;
public static void main(String[] args) {
// TODO Auto-generated method stub
try(Scanner reader=new Scanner(System.in)){
String str=reader.nextLine();
if(init(str)==-1)
System.out.println("IPAddress cannot be formed");
ipAddress();
}
}
private static void ipAddress() {
// TODO Auto-generated method stub
int noOfGroups=4;
int group=noOfGroups-1;
int countInOneLevel=1, childCount=0;
while(!queue.isEmpty() && countInOneLevel>0 && group>0){
List<StringBuilder> list=queue.poll();
countInOneLevel--;
StringBuilder currentGroup=list.get(group);
StringBuilder prevGroup=list.get(group-1);
while(currentGroup.length()>1){
prevGroup.append(currentGroup.charAt(0));
currentGroup=currentGroup.deleteCharAt(0);
if(makeIPAdress(list, group)==1 ){
childCount++;
}
}
if(countInOneLevel==0){//current level complete
countInOneLevel=childCount;
group--;
childCount=0;
}
}
System.out.println("No. of possible IPAddress: "+count);
}
private static int init(String str) {
// TODO Auto-generated method stub
int length=str.length();
if(length<4 || length>12)
return -1;
StringBuilder strgroup[]= new StringBuilder[4];
int groups=4;
for(int i=0;i<groups-1;i++){
strgroup[i]=new StringBuilder(str.substring(i,i+1));
}
strgroup[groups-1]=new StringBuilder(str.substring(3,length));
List<StringBuilder> list=new ArrayList<StringBuilder>();
for(int i=0;i<groups;i++){
list.add(strgroup[i]);
}
return makeIPAdress(list,groups-1);
}
private static int makeIPAdress(List<StringBuilder> list, int i) {
// TODO Auto-generated method stub
if(isValidIPAdress(list)){
List<StringBuilder> list1=new ArrayList<StringBuilder>();
for(int k=0;k<4;k++){
StringBuilder s=new StringBuilder(list.get(k).toString());
list1.add(s);
}
queue.offer(list1);
display(list);
count++;
return 1;
}
for(int group=i;group>0;group--){
StringBuilder currentGroup=list.get(group);
StringBuilder prevGroup=list.get(group-1);
int num=Integer.parseInt(currentGroup.toString());
while(num<0|| num>255){
prevGroup.append(currentGroup.charAt(0));
currentGroup=currentGroup.deleteCharAt(0);
num=Integer.parseInt(currentGroup.toString());
}
}
StringBuilder firstGroup=list.get(0);
int num=Integer.parseInt(firstGroup.toString());
if(num>=0 && num<=255){
List<StringBuilder> list1=new ArrayList<StringBuilder>();
for(int k=0;k<4;k++){
StringBuilder s=new StringBuilder(list.get(k).toString());
list1.add(s);
}
queue.offer(list1);
display(list);
count++;
return 1;
}
return -1;
}
private static boolean isValidIPAdress(List<StringBuilder> list) {
// TODO Auto-generated method stub
for(int group=0;group<4;group++){
int num=Integer.parseInt(list.get(group).toString());
if(num<0 || num>255)
return false;
}
return true;
}
private static void display(List<StringBuilder> list) {
// TODO Auto-generated method stub
Iterator<StringBuilder> i=list.iterator();
while(i.hasNext()){
StringBuilder s=i.next();
if(!i.hasNext())
System.out.print(s);
else
System.out.print(s+".");
}
System.out.println();
}
}
Sample Input:
2252555
Sample Output:
2.25.25.55
2.25.255.5
2.252.55.5
225.25.5.5
22.52.55.5
225.2.55.5
No. of possible IPAddress: 6
Here is a recursive solution:
public static void main(String[] args){
System.out.println(findIPs("1234567", 3));
}
public static List<String> findIPs(String s,int dots){
List<String> ips = new ArrayList<>();
for(int i =1 ;i<=3 && i < s.length(); i++){
String cip = s.substring(0,i);
if(Integer.parseInt(cip) < 256){
if(dots == 1){
if( Integer.parseInt(s.substring(i)) < 256) {
ips.add(cip + "." + s.substring(i));
}
}else {
for (String ip : findIPs(s.substring(i), dots - 1)) {
ips.add(cip + "." + ip);
}
}
}
}
return ips;
}
Here is the solution to resolve the wrong ips issue of one of the above solutions
private static List<String> ips = new ArrayList<>();
public static void main(String[] args) {
Date d = new Date();
System.out.println(posIps("19216801"));
System.out.println(new Date().getTime() - d.getTime());
}
private static List<String> posIps(String number) {
int l = number.length() - 3;
for (int a = 0; a < 3 && a < l; a++) {
for (int b = 0; b < 3 && b < l - a; b++) {
for (int c = 0; c < 3 && c < l - a - b; c++) {
StringBuilder sb = new StringBuilder(number);
if (Integer.parseInt(sb.substring(0, a + 1 )) < 256
&& Integer.parseInt(sb.substring(a + 1, a + b + 2)) < 256
&& Integer.parseInt(sb.substring(a + b + 2, a + b + c + 3)) < 256
&& Integer.parseInt(sb.substring(a + b + c + 3)) < 256) {
sb.insert(a + 1, ".");
sb.insert(a + b + 3, ".");
sb.insert(a + b + c + 5, ".");
ips.add(sb.toString());
}
}
}
}
return ips;
}
This code works fine, check it.
public static void main(String[] args) {
String input = "121212111";
for (String ipAddress : generatePossibleIpAddresses(input, 3)) {
System.out.println(ipAddress);
}
}
public static ArrayList<String> generatePossibleIpAddresses(String ipAddress, int dot) {
ArrayList<String> list = new ArrayList<String>();
if (ipAddress == null || ipAddress.length() == 0) {
return list;
}
if (dot == 0) {
int i = Integer.parseInt(ipAddress);
if (i < 256) {
list.add(ipAddress);
}
return list;
}
for (int i = 1; i <= 3; i++) {
int num = Integer.parseInt(ipAddress.substring(0, i));
if (num < 256) {
for (String str : generatePossibleIpAddresses(ipAddress.substring(i), dot - 1)) {
list.add(num + "." + str);
}
}
}
return list;
}
private static String getValidIp(List<Integer> combination, String ip) {
int from = 0;
int to = 0;
String finalIp = "";
for (int digit : combination) {
to += digit;
String ipPart = ip.substring(from, to);
if (!isValidIp(ipPart)) {
return null;
}
finalIp += ipPart + ".";
from = to;
}
return finalIp.replaceAll(".$", "");
}
public static List<List<Integer>> getOptions(String ip) {
List<Integer> baseOption = Arrays.asList(1, 2, 3);
List<List<Integer>> options = new ArrayList<>();
baseOption.forEach(i -> {
baseOption.forEach(i2 -> {
baseOption.forEach(i3 -> {
baseOption.forEach(i4 -> {
if (isRelevantOption(ip, i + i2 + i3 + i4)) {
options.add(Arrays.asList(i, i2, i3, i4));
}
});
});
});
});
return options;
}
private static boolean isRelevantOption(String ip, int sum) {
return ip.length() == sum;
}
private static boolean isValidIp(String ip) {
return Integer.parseInt(ip) < 256;
}
public static List<String> GetAllValidIpAddress(String ip) {
if (ip.length() > 12) {
System.out.println("IP is not valid");
}
List<List<Integer>> options = getOptions(ip);
return options.stream().map(c -> getValidIp(c, ip)).filter(Objects::nonNull).collect(Collectors.toList());
}
public static void main(String args[]) {
GetAllValidIpAddress("2562547").forEach(ip -> System.out.println(ip));
}

Counting distinct words V2 [duplicate]

This question already has an answer here:
Counting distinct words with Threads
(1 answer)
Closed 9 years ago.
I've asked this question before ( Counting distinct words with Threads ) and made the code more appropriate. As described in first question I need to count the distinct words from a file.
De-Bug shows that all my words are stored and sorted correctly, but the issue now is an infinite "while" loop in the Test class that keeps on going after reading all the words (De-bug really helped to figure out some points...).
I'm testing the code on a small file now with no more than 10 words.
DataSet class has been modified mostly.
I need some advice how to get out of the loop.
Test looks like this:
package test;
import java.io.File;
import java.io.IOException;
import junit.framework.Assert;
import junit.framework.TestCase;
import main.DataSet;
import main.WordReader;
public class Test extends TestCase
{
public void test2() throws IOException
{
File words = new File("resources" + File.separator + "test2.txt");
if (!words.exists())
{
System.out.println("File [" + words.getAbsolutePath()
+ "] does not exist");
Assert.fail();
}
WordReader wr = new WordReader(words);
DataSet ds = new DataSet();
String nextWord = wr.readNext();
// This is the loop
while (nextWord != "" && nextWord != null)
{
if (!ds.member(nextWord))
{
ds.insert(nextWord);
}
nextWord = wr.readNext();
}
wr.close();
System.out.println(ds.toString());
System.out.println(words.toString() + " contains " + ds.getLength()
+ " distinct words");
}
}
Here is my updated DataSet class, especially member() method, I'm still not sure about it because at some point I used to get a NullPointerExeption (don't know why...):
package main;
import sort.Sort;
public class DataSet
{
private String[] data;
private static final int DEFAULT_VALUE = 200;
private int nextIndex;
private Sort bubble;
public DataSet(int initialCapacity)
{
data = new String[initialCapacity];
nextIndex = 0;
bubble = new Sort();
}
public DataSet()
{
this(DEFAULT_VALUE);
nextIndex = 0;
bubble = new Sort();
}
public void insert(String value)
{
if (nextIndex < data.length)
{
data[nextIndex] = value;
nextIndex++;
bubble.bubble_sort(data, nextIndex);
}
else
{
expandCapacity();
insert(value);
}
}
public int getLength()
{
return nextIndex + 1;
}
public boolean member(String value)
{
for (int i = 0; i < data.length; i++)
{
if (data[i] != null && nextIndex != 10)
{
if (data[i].equals(value))
return true;
}
}
return false;
}
private void expandCapacity()
{
String[] larger = new String[data.length * 2];
for (int i = 0; i < data.length; i++)
{
data = larger;
}
}
}
WordReader class didn't change much. ArrayList was replaced with simple array, storing method also has been modified:
package main;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class WordReader
{
private File file;
private String[] words;
private int nextFreeIndex;
private BufferedReader in;
private int DEFAULT_SIZE = 200;
private String word;
public WordReader(File file) throws IOException
{
words = new String[DEFAULT_SIZE];
in = new BufferedReader(new FileReader(file));
nextFreeIndex = 0;
}
public void expand()
{
String[] newArray = new String[words.length * 2];
// System.arraycopy(words, 0, newArray, 0, words.length);
for (int i = 0; i < words.length; i++)
newArray[i] = words[i];
words = newArray;
}
public void read() throws IOException
{
}
public String readNext() throws IOException
{
char nextCharacter = (char) in.read();
while (in.ready())
{
while (isWhiteSpace(nextCharacter) || !isCharacter(nextCharacter))
{
// word = "";
nextCharacter = (char) in.read();
if (!in.ready())
{
break;
}
}
word = "";
while (isCharacter(nextCharacter))
{
word += nextCharacter;
nextCharacter = (char) in.read();
}
storeWord(word);
return word;
}
return word;
}
private void storeWord(String word)
{
if (nextFreeIndex < words.length)
{
words[nextFreeIndex] = word;
nextFreeIndex++;
}
else
{
expand();
storeWord(word);
}
}
private boolean isWhiteSpace(char next)
{
if ((next == ' ') || (next == '\t') || (next == '\n'))
{
return true;
}
return false;
}
private boolean isCharacter(char next)
{
if ((next >= 'a') && (next <= 'z'))
{
return true;
}
if ((next >= 'A') && (next <= 'Z'))
{
return true;
}
return false;
}
public boolean fileExists()
{
return file.exists();
}
public boolean fileReadable()
{
return file.canRead();
}
public Object wordsLength()
{
return words.length;
}
public void close() throws IOException
{
in.close();
}
public String[] getWords()
{
return words;
}
}
And Bubble Sort class for has been changed for strings:
package sort;
public class Sort
{
public void bubble_sort(String a[], int length)
{
for (int j = 0; j < length; j++)
{
for (int i = j + 1; i < length; i++)
{
if (a[i].compareTo(a[j]) < 0)
{
String t = a[j];
a[j] = a[i];
a[i] = t;
}
}
}
}
}
I suppose the method that actually blocks is the WordReader.readNext(). My suggestion there is that you use Scanner instead of BufferedReader, it is more suitable for parsing a file into words.
Your readNext() method could be redone as such (where scan is a Scanner):
public String readNext() {
if (scan.hasNext()) {
String word = scan.next();
if (!word.matches("[A-Za-z]+"))
word = "";
storeWord(word);
return word;
}
return null;
}
This will have the same functionality as your code (without using isCharacter() or isWhitespace() - the regex (inside matches())checks that a word contains only characters. The isWhitespace() functionality is built-in in next() method which separates words. The added functionality is that it returns null when there are no more words in the file.
You'll have to change your while-loop in Test class for this to work properly or you will get a NullPointerException - just switch the two conditions in the loop definition (always check for null before, or the first will give a NPE either way and the null-check is useless).
To make a Scanner, you can use a BufferedReader as a parameter or the File directly as well, as such:
Scanner scan = new Scanner(file);

generating list of small ascii strings

I want to create a generator class, in java, to produce the next smallest unique ascii string, where the resultant string must begin with an a-Z, and each subsequent letter can be a-Z or 0-9.
The strings are being used to minify variables in a javascript file.
Any suggestions on a tool out there which does this or some rough code as to how you'd implement?
If you need to use a different selection of characters you can use
public static void main(String... ignored) {
String prev = "";
for (int i = 0; i < 40000000; i++) {
String s = asId(i);
if (s.length() > prev.length())
System.out.print(prev + "\n" + s + " to ");
prev = s;
}
}
static char[] CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
public static String asId(long number) {
StringBuilder sb = new StringBuilder();
long div = number < 52 ? 1 : 52;
while (div <= number / 62) div *= 62;
while (div > 0) {
sb.append(CHARS[((int) (number / div % 62))]);
div /= 62;
}
return sb.toString();
}
prints
0 to Z
10 to ZZ
100 to ZZZ
1000 to
You can use the following in Java.
public static String asId(long number) {
return (char) ('a' + number % 26)
+ (number >= 26 ? Long.toString(number / 26, 36) : "");
}
If you concerned about negative numbers you can use.
public static String asId(long number) {
long lowBit = number & 1;
long highBits = number >>> 1;
return (char) ('a' + highBits % 13 + lowBit)
+ (number >= 26 ? Long.toString(highBits / 13, 36) : "");
}
Here are some ideas (not fully tested!!!)
import java.lang.*;
import java.util.*;
public class Test
{
static class VariablesIterator implements Iterator<String>
{
private List<Character> characters = new ArrayList<Character>();
private List<Integer> indices = new ArrayList<Integer>();
public VariablesIterator(String start)
{
char[] cs = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
for (char c : cs)
{
characters.add(c);
}
for (int i = 0; i < start.length(); ++i)
{
indices.add(characters.indexOf(start.charAt(i)));
}
}
public boolean hasNext()
{
return true;
}
public String next()
{
String current = "";
for (int i = 0; i < indices.size(); ++i)
{
current += characters.get(indices.get(i));
}
Integer last = indices.get(indices.size() - 1);
if (indices.size() != 1 && last != 2*26 + 10 - 1 || indices.size() == 1 && last != 2*26 - 1)
{
indices.set(indices.size() - 1, last + 1);
}
else
{
indices.add(0);
}
return current;
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
static class Variables implements Iterable<String>
{
public Iterator<String> iterator()
{
return new VariablesIterator("a");
}
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
for (String variable : new Variables())
{
System.out.println(variable);
in.nextLine();
}
}
}

Categories