Search code examples
javachemistry

Parsing a string that represents a chemical reaction and verify if the reaction is possible


I have to write a program that takes a user's chemical equation as an input, like 12 CO2 + 6 H2O -> 2 C6H12O6 + 12 O2, and watch if the amount of Atoms is on both sites the same. Is there any way to calculate and parse this easily?

For example:

12 CO2 + 6 H2O -> 2 C6H12O6 + 12 O2

12*2+6*2 -> 2*6+2*12+2*6+12*2

In this case there should be the Output "false".

This is my code but it's actually is only to try out something:

public static void main(String[] args) {
    Scanner s = new Scanner(System.in);
    List<String> list = new ArrayList<String>();
    String input = "";
    while (!(input.equals("end"))) {
        input = s.nextLine();
        list.add(input);
    }
    list.remove(list.size() - 1);
    for (int i = 0; i < list.size(); i++) {
        int before = 0;
        int after = 0;
        String string = list.get(i);
        string = besserUmwandeln(string);
        System.out.println(string);
    }
}

public static String besserUmwandeln(String string) {
    string = string.replace("-", "");
    string = string.trim().replaceAll(("\\s+"), " ");
    string = string.replace(' ', '*');
    StringBuilder builder = new StringBuilder(string);
    System.out.println(string);
    for (int k = 0; k < builder.length(); k++) {
        if (Character.isUpperCase(builder.charAt(k))) {
            builder.setCharAt(k, ':');
        }
        if (Character.isLowerCase(builder.charAt(k))) {
            builder.setCharAt(k, '.');
        }
        if (Character.isDigit(builder.charAt(k))) {
        } else {
        }
    }
    for (int j = 0; j < builder.length(); j++) {
        if (j < builder.length() && builder.charAt(j) == ':' && builder.charAt(j + 1) == '.') {
            builder.deleteCharAt(j + 1);
        }
    }
    for (int i = 0; i < builder.length(); i++) {
        if (i < builder.length() - 1 && builder.charAt(i) == ':' && builder.charAt(i + 1) == ':') {
            builder.deleteCharAt(i);
        }
    }
    for (int i = 0; i < builder.length(); i++) {
        if (i < builder.length() - 1 && builder.charAt(i) == '+' && builder.charAt(i + 1) == '*') {
            builder.deleteCharAt(i + 1);
        }
    }
    for (int i = 0; i < builder.length(); i++) {
        if (i < builder.length() - 1 && builder.charAt(i) == '*' && builder.charAt(i + 1) == '+') {
            builder.deleteCharAt(i);
        }
    }
    for (int i = 0; i < builder.length(); i++) {
        if (i < builder.length() - 1 && builder.charAt(i) == '*' && builder.charAt(i + 1) == '>') {
            builder.deleteCharAt(i);
        }
    }
    for (int i = 0; i < builder.length(); i++) {
        if (i < builder.length() - 1 && builder.charAt(i) == '>' && builder.charAt(i + 1) == '*') {
            builder.deleteCharAt(i + 1);
        }
    }
    for (int i = 0; i < builder.length(); i++) {
        if (i < builder.length() - 1 && builder.charAt(i) == '*' && builder.charAt(i + 1) == ':') {
            builder.deleteCharAt(i + 1);
        }
    }


    return builder.toString();
}

Solution

  • So, every time I need to parse some text with Java, I mostly end up just using Regex. So I'd recommend you to also do so.

    You can test regular expressions at regex101.com.

    And also easily use it in Java:

    final inputText = ...
    final Pattern pattern = Patern.compile("Some regex code");
    final Matcher matcher = pattern.matcher(input);
    if (matcher.find()) {
        System.out.println(matcher.group(0));
    }
    

    Inside Regex you can define capturing groups with ( and ) and then grab the results by matcher.group(int).

    For example, you may first separate the equation using (.*) -> (.*).

    Then loop the left and right group using find with: (\d+) (\w+)(?: \+| -|$).

    After that you can use group(1) for the amount and group(2) for the element.

    And if needed also iterate the second group (the element) for the exact element distribution using (\w)(\d?). Then the first group is the element, for example for the text CO2 it yields two hits, the first hit has group(1) -> C and no second group. The second hit has group(1) -> O and group(2) -> 2.

    Test your regex here: regex101#Q6KMJo