2015-05-12 2 views
0

Im пытается решить уравнение так: Четыре плюс десять делится на (пятьдесят пять плюс девять)Решая математическое уравнение, записанное в словах в Java

так, что я получаю ответ: 4,15625

Я знаю, что я могу решить уравнение String sentence = "4+10/(55+9)" следующим образом:

ScriptEngineManager mgr = new ScriptEngineManager(); 
ScriptEngine engine = mgr.getEngineByName("JavaScript"); 
String infix = sentence; 
try { 
    System.out.println(engine.eval(infix)); 
} catch (ScriptException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 

Но в любом случае, чтобы просто решить слова (nine..plu s..divide ..) уравнение. Или есть способ конвертировать слова (nine..plus..divide ..) в строку типа (9 ... + .../...), а затем использовать функцию, показанную выше, чтобы реши это?

Спасибо!

+0

Я думаю, вам нужно будет составить список всех чисел и математических слов, чтобы сделать это. например пятьдесят = 5 и пять = 5, и они объединят их 55. split =/и by = nothing и plus = +. Я не уверен, что это будет действительный ответ, поэтому я помещаю его здесь в комментарии. – Forseth11

+2

Стандартный способ сделать это будет использовать синтаксический анализатор, такой как Antlr: http://www.antlr.org/ –

+0

Как сказал @Oliver, или вам нужно сканировать и анализировать, что, вероятно, они хотят от вас. – Tarik

ответ

1

Вы можете использовать библиотеку синтаксиса, такую ​​как antlr, что, вероятно, является лучшей идеей, если вы хотите полноценный, выразительный язык и правильную обработку ошибок.

Для быстрого и грязного решение, которое вы можете написать свой собственный парсер, используя регулярные выражения и замены карты:

public class NaturalLanguageMath { 

    public static void main(String[] args) { 
     String sentence = "Four plus Ten divided by (fifty-five plus nine)"; 
     System.out.println(toMath(sentence)); 
    } 

    // Regular expression that will match our symbols 
    // special case for "divided by" since that's two words for one symbol 
    static final Pattern SYMBOL_PATTERN = Pattern.compile("(divided by|[a-z-]+)", Pattern.CASE_INSENSITIVE); 

    private static String toMath(String sentence) { 
     // Builder to build the translated string 
     StringBuilder builder = new StringBuilder(); 
     // End of the last matched group 
     int lastEnd = 0; 
     // Go through all symbols in the string 
     Matcher matcher = SYMBOL_PATTERN.matcher(sentence); 
     while(matcher.find()) { 
      // The matched symbol 
      String symbol = matcher.group(0).toLowerCase(); 
      // Get the replacement 
      String replacement = getReplacement(symbol); 
      // Append everything between the previous match and this match 
      builder.append(sentence.substring(lastEnd, matcher.start())); 
      // Append the replacement 
      builder.append(replacement); 
      // Update the end 
      lastEnd = matcher.end(); 
     } 
     // Append the end of the string and return it 
     builder.append(sentence.substring(lastEnd)); 
     return builder.toString(); 
    } 

    // Map to hold replacement symbols 
    static final HashMap<String, String> REPLACEMENT_MAP = new HashMap<>(); 
    static { 
     REPLACEMENT_MAP.put("four", "4"); 
     REPLACEMENT_MAP.put("plus", "+"); 
     REPLACEMENT_MAP.put("ten", "10"); 
     REPLACEMENT_MAP.put("fifty", "50"); 
     REPLACEMENT_MAP.put("five", "5"); 
     REPLACEMENT_MAP.put("nine", "9"); 
     REPLACEMENT_MAP.put("divided by", "/"); 
    } 

    private static String getReplacement(String symbol) { 
     // Handle compounds such as fifty-five 
     if(symbol.contains("-")) { 
      // add each individual symbol together and return the result 
      // this is far from perfect since it will allow compounds such as 
      // fifty-five-nine which would become 64 
      int value = 0; 
      // Go through each individual symbol and translate it 
      String[] symbols = symbol.split("-"); 
      for(String s : symbols) { 
       if(!REPLACEMENT_MAP.containsKey(s)) { 
        throw new IllegalArgumentException("Unknown symbol: " + s); 
       } 
       value += Integer.parseInt(getReplacement(s)); 
      } 
      return String.valueOf(value); 
     // Straight translation 
     } else if (REPLACEMENT_MAP.containsKey(symbol)) { 
      return REPLACEMENT_MAP.get(symbol); 
     // Unknown symbol 
     } else { 
      throw new IllegalArgumentException("Unknown symbol: " + symbol); 
     } 
    } 
} 

Выход:

4 + 10/(55 + 9)

+0

Правда, глядя на antlr, это похоже на лучший подход, но это также делает работу. Очень круто. Спасибо – huddie96

+0

Мне просто нужно создать карту – huddie96

Смежные вопросы