if-statement - 有没有更简单的方法来解决这个问题而不使用这么多的 if 语句?如何?
问题描述
我们遇到了一个问题,要求使用字母 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 美分。这让我很难理解。
解决方案
我将在这里进行一般性的讨论,因为您当前的代码很奇怪,几乎可以肯定会损坏。我不太明白你的“输出”应该是什么。
FSM 是一组状态的定义以及输入如何导致状态转换。看起来你开始粗略地这样做,但currentOut
已经坏了。如果你的目标是得到一个总和,那么你就打败了整个练习的要点。总和是多少并不重要。重要的是你最后处于什么状态——尤其是你是否处于“接受”状态,在这种情况下,字符串正好等于 40 美分的状态。
至于如何在没有数以千计的if
s 的情况下实现 FSM,您通常可以将状态存储在数组中,并将您的状态名称改为状态编号。到那时,理论上你可以摆脱所有的if
s. (不过,在现实世界中,您可能仍然希望忽略或拒绝 (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.
推荐阅读
- opengl - How to instance draw with different transformations for multiple objects
- macos - 为什么 Docker For desktop (Mac) Persistent Volume 主机路径上的 Kubernetes 变得滞后?
- laravel - Laravel Sail 在 Ubuntu 20.04 LTS 中无法正常工作
- python - 将 3d numpy 数组分成 2 组 python
- latex - 捕获的 MiKTeX 异常:Unknown MiKTeX exception with asymptote
- jquery - 从 JSON 填充下拉列表
- node.js - 如何将值从 reactjs 发布到 expressJs
- java - 调用paint方法时JLabel不显示
- java - 检测用户何时按下删除键
- python - 通过 django 管理问题将图像保存在媒体文件夹中