【问题标题】:Is there an easier way to do this problem without using so many if statements? and how?有没有更简单的方法来解决这个问题而不使用这么多的 if 语句?如何?
【发布时间】:2019-09-21 10:41:18
【问题描述】:

我们遇到了一个问题,要求使用字母 QDN(Quarter, Dime, Nickel) 来创建一个有限状态机,该状态机仅在它们加到 40 美分时才接受。我已经掌握了使用 IF 语句概念的基础知识。我想知道是否有更简单的方法可以花费更少的时间?

我已经尝试过大量的 if 案例,但使用该方法有很多步骤。

public class FSA2_rpf4961 {

public static void main(String[] args) {
    //The program will read in a sequence of strings and test them against a 
    //FSM. Your strings may not contain blank spaces
    System.out.println("Enter string to test or q to terminate");
    Scanner in = new Scanner (System.in);
    String testString = in.next();

    while (!testString.equals("q"))
    {
        String testOutput = applyFSA2(testString);
        System.out.println("For the test string "+testString+
                                ", the FSM output is "+testOutput);
        System.out.println("Enter next string to test or q to terminate:");
        testString = in.next();

    }
    in.close();

}
public static String applyFSA(String s) {
   String currentOut = "0";                // initial output in s0
   String currentState = "s0";             // initial state

   int i = 0;

   while (i<s.length())
   {
            //quarter first
           if (currentState.equals("s0") && s.charAt(i) == 'q')
           {
                    currentState = "s1";  
                    currentOut += 25;  // collect output on move to s1
           }
           else if (currentState.equals("s1") && s.charAt(i)  == 'd') {
            currentState = "s2";
            currentOut += 10;
           }
           else if (currentState.equals("s2") && s.charAt(i)  == 'n') {
            currentState = "s3";
            currentOut += 5;
           }
           else if (currentState.equals("s1") && s.charAt(i)  == 'n') {
            currentState = "s4";
            currentOut += 5;
           }
           else if (currentState.equals("s4") && s.charAt(i)  == 'd') {
            currentState = "s3";
            currentOut += 10;
           }

           //dime first
           else if (currentState.equals("s0") && s.charAt(i) == 'd')
           {
                    currentState = "s5";
                    currentOut += 10;   // d
            }

我们需要它只接受它增加 40 美分。这让我很难理解。

【问题讨论】:

  • 没有测试 40 美分,也没有拒绝 40 美分的消息。 currentState 似乎也没有必要,因为没有要求它们按升序排列。在 While 中,只需测试 s.charAt(i) 的 q 或 d 或 n 并添加适当的值。此外,在比较时将每个输入转换为小写。此外,q 不应同时等于 Quit 和 Quarter -- 使用 x 表示 Exit...

标签: if-statement printing count state fsm


【解决方案1】:

我将在这里泛泛而谈,因为您当前的代码很奇怪,几乎可以肯定会损坏。我不太明白你的“输出”应该是什么。

FSM 是对一组状态以及输入如何导致状态转换的定义。看起来您开始时大致是这样做的,但 currentOut 已损坏。 如果你的目标是得到一个总和,那么你就打败了整个练习的要点。总和是多少无关紧要。重要的是你最后处于什么状态——尤其是你是否处于“接受”状态,在这种情况下,字符串正好等于 40 美分。

至于如何在没有大量ifs 的情况下实现 FSM,您通常可以将状态存储在数组中,并将状态名称改为状态编号。到那时,理论上你可以摆脱所有你的ifs。 (但在现实世界中,您可能仍然希望忽略或拒绝 (q|d|n) 以外的字符。)

考虑这样的事情(伪代码):

    // Each array in `graph` represents a state.
    // Each entry is the state number (ie: index into `graph`) to go to
    // when you're in that state and see the corresponding char.
    //
    // BTW, the state graph makes a lot more sense when you consider nickels first.
    // A nickel takes you to the "next" state, and dimes and quarters act like
    // 2 and 5 nickels, respectively. When you do that, a pattern shows up.
    graph = [
      //  n  d  q
      //-----------
        [ 1, 2, 5 ], // s0
        [ 2, 3, 6 ], // s1
        [ 3, 4, 7 ], // s2
        [ 4, 5, 8 ], // s3
        [ 5, 6, 9 ], // s4
        [ 6, 7, 9 ], // s5
        [ 7, 8, 9 ], // s6
        [ 8, 9, 9 ], // s7
        [ 9, 9, 9 ], // s8
        [ 9, 9, 9 ]  // s9 (fail state)
    ]
    start = 0
    accept = 8
    fail = 9

    // at this point, walking the graph is trivial.
    state = start
    for each char c in s:
        index = "ndq".indexOf(c) // n->0, d->1, q->2, others -> -1
        state = graph[state][index]


    // Once the loop's done:
    //   if state == accept, you have exactly 40c.
    //   if state == fail, you have >40c. A FSM won't tell you how much,
    //      because FSMs can't count.
    // any other state represents a known amount that's less than 40c.

【讨论】:

    猜你喜欢
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多