I'm working on solving an equation but I will like to use the constants to program my solution.
The method I'm working on is called decompose which decomposes the equation into constants. The problem is that when I split, an equation with a negative constant will yield an array with the absolute value of the constants. How can I achieve the minus sign while still using regex?
If the input is ax+by=c, the output should be {a,b,c}.
Helpful bonus: Is there a way to delete the empty elements that is created when I split. For example, if I type equation 2x+3y=6, I end up with a "raw" array that contains the elements {2,,3,,6}
Code:
public static int[] decompose(String s)
{
s = s.replaceAll(" ", "");
String[] termRaw = s.split("\\D"); //Splits the equation into constants *and* empty spaces.
ArrayList<Integer> constants = new ArrayList<Integer>(); //Values are placed into here if they are integers.
for(int k = 0 ; k < termRaw.length ; k++)
{
if(!(termRaw[k].equals("")))
{
constants.add(Integer.parseInt(termRaw[k]));
}
}
int[] ans = new int[constants.size()];
for(int k = 0 ; k < constants.size(); k++) //ArrayList to int[]
{
ans[k] = constants.get(k);
}
return ans;
}
The general strategy to this answer is to split the input equation by operator, then extract out the coefficients in a loop. However, there are several edge cases which need to be considered:
a plus symbol (+) is prefixed to every minus which does not appear either as the first term
after splitting, a coefficient of positive one is detected by seeing empty string
after splitting, a coefficient of negative one is detected by seeing a minus sign
String input = "-22x-77y+z=-88-10+33z-q";
input = input.replaceAll(" ", "") // remove whitespace
.replaceAll("=-", "-"); // remove equals sign
.replaceAll("(?<!^)-", "+-"); // replace - with +-, except at start of line
// input = -22x+-77y+z+-88+-10+33z+-
String[] termRaw = bozo.split("[\\+*/=]");
// termRaw contains [-22x, -77y, z, -88, -10, 33z, -]
ArrayList<Integer> constants = new ArrayList<Integer>();
// after splitting,
// termRaw contains [-22, -77, '', -88, -10, 33, '-']
for (int k=0 ; k < termRaw.length ; k++) {
termRaw[k] = termRaw[k].replaceAll("[a-zA-Z]", "");
if (termRaw[k].equals("")) {
constants.add(1);
}
else if (termRaw[k].equals("-")) {
constants.add(-1);
}
else {
constants.add(Integer.parseInt(termRaw[k]));
}
}
If you're using java8, then you can use this one line method:
public static int[] decompose(String s) {
return Arrays.stream(s.replaceAll("[^0-9]", " ").split("\\s+")).mapToInt(Integer::parseInt).toArray();
}
DEMO:
1. Output
[2, 3, 6]
2. Code
import java.util.*;
public class HelloWorld {
public static void main(String args[]) {
String s = "2x+3y=6";
int[] array = decompose(s);
System.out.println(Arrays.toString(array));
}
public static int[] decompose(String s) {
return Arrays.stream(s.replaceAll("[^0-9]", " ").split("\\s+")).mapToInt(Integer::parseInt).toArray();
}
}
Related
I want to print number of possible non-empty sequences of letters .
Eg.
String str="ABC";
Expected output is
A,B,C
AB,AC,BC,BA,CA,CB
ABC,ACB,BAC,BCA,CAB,CBA`
But i get the below output which is incorrect. How to fix my code
BB CC A AB ACC BC ABC AC B BBC CCC BCC C CBC CB
I have written the below code using Recurion
String tiles = "ABC";
Set<String> ans = new HashSet<>();
solve(tiles, 0, "", ans);
public static void solve(String tiles, int idx, String output, Set<String> ans) {
ans.add(output);
if (idx >= tiles.length()) {
return;
}
for (int i = idx; i < tiles.length(); i++) {
solve(tiles, idx + 1, output + tiles.charAt(i), ans);
}
}
This is how recursion tree would look like for str="AAB"
You need to ignore the first passing of the "" from output and then you need to ignore each letter you already passed through
public static void main(String[] args) {
String tiles = "ABC";
List<String> ans = new ArrayList<>();
solve(tiles, "", ans);
System.out.println(ans);
}
public static void solve(String tiles, String output, List<String> ans) {
if (!output.equals("")) ans.add(output);
for (int i = 0; i < tiles.length(); i++) {
String str = tiles.substring(0, i) + tiles.substring(i + 1);
solve(str, output + tiles.charAt(i), ans);
}
}
Output
[A, AB, ABC, AC, ACB, B, BA, BAC, BC, BCA, C, CA, CAB, CB, CBA]
you can try this
public class Permutation {
public static List<String> getPermutations(String str) {
Set<String> permutations = new HashSet<>();
permute(str, "", permutations);
return new ArrayList<>(permutations);
}
private static void permute(String string, String prefix, Set<String> permutations) {
if (string.length() == 0) {
permutations.add(prefix);
} else {
for (int i = 0; i < string.length(); i++) {
char charAt = string.charAt(i);
String remainingString = string.substring(0, i) + string.substring(i + 1);
permute(remainingString, prefix + charAt, permutations);
}
}
}
}
The "permute" method takes in 3 parameters: a string, a prefix string and a set of permutations.
The "permute" method takes in 3 parameters: a string, a prefix string and a set of permutations.
If the input string is not empty, it uses a for loop to iterate through the characters of the input string.
For each iteration, it gets the character at the current index, creates a new string by removing that character from the input string.
it then calls the permute method 3 times:
it then calls the permute method 3 times:
One with the original string and prefix
One with the remaining string and prefix
This way, the function explores all the possible permutations of the characters in the input string, including the option of not having one of the characters in the permutation and the permutation of positions, without including an empty string as an option.
Then you use like:
Permutation p = new Permutation();
List<String> permutations = p.getPermutations("abc");
Make 1 change:
Set<String> ans = new TreeSet<>(Comparators.comparing(String::length).thenComparing(s -> s));
It's a quite popular backtracking problem. You can find almost same problem here:
https://leetcode.com/problems/subsets/
The input are numbers instead of characters but the idea is the same.
You can switch to the solution tab and explore different answers:
https://leetcode.com/problems/subsets/solutions/
I have a program where I receive a long string in the format
characters$xxx,characters$xx,characters$xx, (....)
x is some digit of some integer with an arbitrary number of digits. The integer values are always contained within $ and ,.
I need to extract the integers into an integer array then print that array. The second part is easy, but how to extract those integers?
an example string: adsdfsh$1234,khjdfd$356,hsgadfsd$98,ghsdsk$4623,
the arraay should contain 1234, 356, 98, 4623
below is my basic logic
import java.util.Scanner;
class RandomStuff {
public static void main (String[]args){
Scanner keyboard = new Scanner(System.in);
String input = keyboard.next();
int count =0;
// counts number of $, because $ will always preceed an int in my string
for(int i=0;i<input.length();i++ ){
if (input.charAt(i)=='$')
count++;}
/* also I'm traversing the string twice here so my complexity is at least
o(2n) if someone knows how to reduce that, please tell me*/
int [] intlist = new int[count];
// fill the array
int arrayindex =0;
for (int i=0; i<input.length();i++){
if (input.charAt(i)=='$'){
/*insert all following characters as a single integer in intlist[arrayindex]
until we hit the character ','*/}
if (input.charAt(i)==','){
arrayindex++;
/*stop recording characters*/}
}
// i can print an array so I'll just omit the rest
keyboard.close();
}
You can use a regular expression with a positive lookbehind to find all consecutive sequences of digits preceded by a $ symbol. Matcher#results can be used to get all of the matches.
String str = "adsdfsh$1234,khjdfd$356,hsgadfsd$98,ghsdsk$4623";
int[] nums = Pattern.compile("(?<=\\$)\\d+").matcher(str).results()
.map(MatchResult::group)
.mapToInt(Integer::parseInt).toArray();
System.out.println(Arrays.toString(nums));
It can done like this
var digitStarts = new ArrayList<Integer>()
var digitsEnds = new ArrayList<Integer>()
// Get the start and end of each digit
for (int i=0; i<input.length();i++){
if(input[i] == '$' ) digitsStarts.add(i)
if(input[i] == ',') digitEnds.add(i)
}
// Get the digits as strings
var digitStrings = new ArrayList<String>()
for(int i=0;i<digitsStart.length; i++ ) {
digitsString.add(input.substring(digitsStarts[i]+1,digitEnds[i]))
}
// Convert to Int
var digits = new ArrayList<Int>
for(int i=0;i<digitString;i++) {
digits.add(Integer.valueOf(digitStrings[i]))
}
In a very simple way:
public static void main(String[] args) {
String str = "adsdfsh$1234,khjdfd$356,hsgadfsd$98,ghsdsk$4623";
String strArray[] = str.split(",");
int numbers[] = new int[strArray.length];
int j = 0;
for(String s : strArray) {
numbers[j++] = Integer.parseInt(s.substring(s.indexOf('$')+1));
}
for(j=0;j<numbers.length;j++)
System.out.print(numbers[j]+" ");
}
OUTPUT: 1234 356 98 4623
I want a code to generate all the subsets of strings of the given string.
I tried this on my own and came up with this :
public static void main(String[] args){
long startTime = System.nanoTime();
String text = "1234";
int n = text.length();
String k = "";
for(int i=0;i < Math.pow(2, n);i++){
k = Integer.toBinaryString(i);
while(k.length() != n){
k = "0"+k;
}
StringBuilder sb = new StringBuilder();
for(int j=0;j<k.length();j++){
if(k.charAt(j) == '1'){
sb.append(text.charAt(j));
}
}
// System.out.println(String.format("%04d",
// Integer.parseInt(k)));
System.out.println(sb.toString());
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println("Duration:" + duration);
}
But this is a horrible O(n^2) algorithm so I was looking for a better solution and found this:
public static void comb2(String s) {
comb2("", s);
}
private static void comb2(String prefix, String s) {
System.out.println(prefix);
for (int i = 0; i < s.length(); i++){
comb2(prefix + s.charAt(i), s.substring(i + 1));
}
}
// read in N from command line, and print all subsets among N elements
public static void main(String[] args) {
String alphabet = "1234";
comb2(alphabet);
System.out.println();
}
The output generated is :
1
12
123
1234
124
13
134
14
2
23
234
24
3
34
4
Although the code is working fine. I was debugging it to understand the logic. I get how 1, 12, 123, 1234 are being generated but after that is not so clear. Can tell me whats going on here?
What you need to understand is how the comb2 method works. Basically, it calls itself. This is called recursion.
When you call comb2("1234"), the result is a call to comb2("","1234").
comb2("","1234") prints "" (which has no effect), then starts a loop
through the end of the string ("234"). The first thing it does in
this loop is call comb2("1","234").
comb2("1", "234") prints "1", then starts a loop through the end of
the string ("234"). The first thing it does in this loop is call
comb2("12","34").
comb2("12", "34") prints "12", then starts a loop through the end of
the string ("34"). The first thing it does in this loop is call
comb2("123","4").
comb2("123", "4") prints "123", then starts a loop through the end of
the string ("4"). The first thing it does in this loop is call
comb2("1234","").
comb2("1234", "") prints "1234", then starts a loop through the end
of the string (""). Since there is nothing to do, it returns
immediately to its caller : comb2("123","4").
comb2("123", "4") now goes to the next step in its loop. Since there
is none, it returns.
comb2("12", "34") now goes to the next step in its loop. It calls
comb2("124","").
comb2("124", "") prints "124", then starts a loop through the end of
the string (""). There is nothing to do, so it returns immediately.
This is how you get from "1234" to "124". Hopefully, from there, you shoud be able to understand the whole execution.
The key point is comb2(prefix + s.charAt(i), s.substring(i + 1)), to understand it better please build an analogy from this statement with the cartesian product, I think this solves every thing. Indeed your'e creating all substrings starting the prefix.
This program should work correctly
public static void getAllSubStrings(char[] chars,int start, Set allSubStrings){
StringBuilder sb = new StringBuilder();
if(start==chars.length){
return;
}
for(int i=start;i<chars.length;i++){
sb.append(chars[i]);
allSubStrings.add(sb.toString());
}
getAllSubStrings(chars, start+1, allSubStrings);
}
public static void main(String[] args) {
Set s = new TreeSet();
getAllSubStrings("12345".toCharArray(), 0, s);
System.out.println(s);
}
Generated output is [1, 12, 123, 1234, 12345, 2, 23, 234, 2345, 3, 34, 345, 4, 45, 5]
From what I think this is still going to be O(n2) because it will run n+(n-1)+(n-2)... times which is n(n+1)/2 I don't think you can get better than that
Here's what a moment's noodling brought me:
import java.util.List;
import java.util.LinkedList;
public class subs {
static List<String> allInitialSubstrings(String s) {
List<String> r = new LinkedList<String>();
for (int i=0; i<s.length(); i++) {
r.add(s.substring(0, i+1));
}
return r;
}
static List<String> allSubstrings(String s) {
List<String> r = new LinkedList<String>();
for (int i=0; i<s.length(); i++) {
r.addAll(allInitialSubstrings(s.substring(i)));
}
return r;
}
public static void main(String ... args) {
System.out.println(allSubstrings(args[0]));
}
}
~ $ javac subs.java
~ $ java subs 12345
[1, 12, 123, 1234, 12345, 2, 23, 234, 2345, 3, 34, 345, 4, 45, 5]
If you want subsets instead of substrings, it's too much a pain in the neck for me to write it in an archaic language like Java, but here it is in the only-slightly elderly Python:
def allSubsets(s):
if len(s):
car = s[0]
cdr = allSubsets(s[1:])
return set([car + b for b in cdr]).union(cdr)
else:
return set([""])
allSubsets("12345")
Without any for loop, cleaner version with same logic would be:
public static void printSubSets(String s){
subSetsHelper(s, "");
}
private static void subSetsHelper(String s, String acc) {
if (s.equals("")){
System.out.println(acc);
return;
}
subSetsHelper(s.substring(1), acc + s.charAt(0)); // accumulate 1st character
subSetsHelper(s.substring(1), acc); // do not
}
printSubSets("abc");
abc
ab
ac
a
bc
b
c
""
Having problems trying to show every combination of a character of array without repeating letters.
public static String[] getAllLists(String[] elements, int lengthOfList)
{
//initialize our returned list with the number of elements calculated above
String[] allLists = new String[(int)Math.pow(elements.length, lengthOfList)];
//lists of length 1 are just the original elements
if(lengthOfList == 1) return elements;
else
{
//the recursion--get all lists of length 3, length 2, all the way up to 1
String[] allSublists = getAllLists(elements, lengthOfList - 1);
//append the sublists to each element
int arrayIndex = 0;
for(int i = 0; i < elements.length; i++)
{
for(int j = 0; j < allSublists.length; j++)
{
//add the newly appended combination to the list
allLists[arrayIndex] = elements[i] + allSublists[j];
arrayIndex++;
}
}
return allLists;
}
}
The above code works perfect but use's each letter more than once which cant be done in this case.
And i am stuck how to do this now.
Here's an example implementation. Essentially it takes a String and iterates over every character, putting that character at the front. It then recurses on the remaining characters. That structure removes your issue of repeated letters, because the input to the recursion has removed the character you've already used.
I also stored results in a set to remove semantic equivalences. The input 'aab' can switch char 0 and char 1 but still be 'aab.' I used a TreeSet to preserve ordering for easier verification of the output, but HashSet would be faster.
public static Set<String> permute(String chars)
{
// Use sets to eliminate semantic duplicates (aab is still aab even if you switch the two 'a's)
// Switch to HashSet for better performance
Set<String> set = new TreeSet<String>();
// Termination condition: only 1 permutation for a string of length 1
if (chars.length() == 1)
{
set.add(chars);
}
else
{
// Give each character a chance to be the first in the permuted string
for (int i=0; i<chars.length(); i++)
{
// Remove the character at index i from the string
String pre = chars.substring(0, i);
String post = chars.substring(i+1);
String remaining = pre+post;
// Recurse to find all the permutations of the remaining chars
for (String permutation : permute(remaining))
{
// Concatenate the first character with the permutations of the remaining chars
set.add(chars.charAt(i) + permutation);
}
}
}
return set;
}
Example run:
public static void main(String[] args)
{
for (String s : CharPermuter.permute("abca"))
{
System.out.println(s);
}
}
Generates:
aabc
aacb
abac
abca
acab
acba
baac
baca
bcaa
caab
caba
cbaa
i tried myself lot but can't get a solution so i'm asking help.
i have an string String input="---4--5-67--8-9---";
now i need to convert in into an string array which will look like:
String [][]output={{4},{5},{67},{8},{9}};
i tried with split() and
java.util.Arrays.toString("---4--5-67--8-9---".split("-+")
but can't find the desired answer. so what to do?
actually i need the value 4,5,67,8,9.but i'm not sure how to find them. i will treat the values as integer for further processing
String[] numbers = "---4--5-67--8-9---".split("-+");
String[][] result = new String[numbers.length][1];
for (int i = 0; i < numbers.length; i++) {
result[i][0] = numbers[i];
}
Update: to get rid of the initial empty value, you can get a substring of the input, like:
int startIdx = 0;
char[] chars = input.toCharArray();
for (int i = 0; i < chars.length; i ++) {
if (Character.isDigit(chars[i])) {
startIdx = i;
break;
}
}
input = input.substring(startIdx);
(or you can check them for not being empty (String.isEmpty()) when processing them later.)
First, here is the answer to your question. This code will generate a two-dimensional array where each element is an array consisting of a single numeric string.
final String input = "---4--5-67--8-9---";
// desired output: {{4},{5},{67},{8},{9}}
// First step: convert all non-digits to whitespace
// so we can cut it off using trim()
// then split based on white space
final String[] arrayOfStrings =
input.replaceAll("\\D+", " ").trim().split(" ");
// Now create the two-dimensional array with the correct size
final String[][] arrayOfArrays = new String[arrayOfStrings.length][];
// Loop over single-dimension array to initialize the two-dimensional one
for(int i = 0; i < arrayOfStrings.length; i++){
final String item = arrayOfStrings[i];
arrayOfArrays[i] = new String[] { item };
}
System.out.println(Arrays.deepToString(arrayOfArrays));
// Output: [[4], [5], [67], [8], [9]]
However, I think what you really need is an array of Integers or ints, so here is a revised solution:
final String input = "---4--5-67--8-9---";
// Convert all non-digits to whitespace
// so we can cut it off using trim()
// then split based on white space
final String[] arrayOfStrings =
input.replaceAll("\\D+", " ").trim().split(" ");
// Now create an array of Integers and assign the values from the string
final Integer[] arrayOfIntegers = new Integer[arrayOfStrings.length];
for(int i = 0; i < arrayOfStrings.length; i++){
arrayOfIntegers[i] = Integer.valueOf(arrayOfStrings[i]);
}
System.out.println(Arrays.toString(arrayOfIntegers));
// Output: [4, 5, 67, 8, 9]
// Or alternatively an array of ints
final int[] arrayOfInts = new int[arrayOfStrings.length];
for(int i = 0; i < arrayOfStrings.length; i++){
arrayOfInts[i] = Integer.parseInt(arrayOfStrings[i]);
}
System.out.println(Arrays.toString(arrayOfInts));
// Output: [4, 5, 67, 8, 9]
Whether you use the Integer or the int version really depends on whether you want to just do some math (int) or need an object reference (Integer).
String[] result = "---4--5-67--8-9---".split("-+");
int i;
for (i = 0; i < result.length; i++) {
if (result[i].length() > 0) {
System.out.println(result[i]);
}
}
gives me output:
4
5
67
8
9
public class split{
public static void main(String[] argv){
String str="---4--5-67--8-9---";
String[] str_a=str.split("-+");
}
}
This seems to working for me.
Using a regex pattern seems more natural in this case:
public class split {
public static int[] main(String input) {
ArrayList<String> list = new ArrayList() ;
Pattern pattern = Pattern.compile("[0-9]") ;
Matcher matcher = pattern.matcher(input) ;
String match = null ;
while( ( match = matcher.find() ) === true ) {
list.add(match) ;
}
String[] array = list.toArray( new String[ ( list.size() ) ]() ) ;
return array ;
}
}
String input="---4--5-67--8-9---";
Scanner scanner = new Scanner(input).useDelimiter("-+");
List<Integer> numbers = new ArrayList<Integer>();
while(scanner.hasNextInt()) {
numbers.add(scanner.nextInt());
}
Integer[] arrayOfNums = numbers.toArray(new Integer[]{});
System.out.println(Arrays.toString(arrayOfNums));
I thought the following is quite simple, although it uses List and Integer arrays, Its not that an overhead for small strings:
For simplicity, I am returning a single dimension array, but can be easily modified to return an array you want. But from your question, it seems that you just want a list of integers.
import java.util.*;
public class Test {
public static void main(String[] args) throws Throwable {
String input = "---4--5-67--8-9---";
System.out.println(split(input).length); // 5
}
public static Integer[] split(String input) {
String[] output = input.split("\\-+");
List<Integer> intList = new ArrayList<Integer>(output.length);
// iterate to remove empty elements
for(String o : output) {
if(o.length() > 0) {
intList.add(Integer.valueOf(o));
}
}
// convert to array (or could return the list itself
Integer[] ret = new Integer[intList.size()];
return intList.toArray(ret);
}
}
I might be late to the party but I figured I'd give the guava take on this.
String in = "---4--5-67--8-9---";
List<String> list = Lists.newArrayList(Splitter.on("-").omitEmptyStrings().trimResults().split(in));
System.out.println(list);
// prints [4, 5, 67, 8, 9]