我想从用户那里获取字符串,解析它,然后运行已解析的命令。
字符串输入类似于" F20N20E10L10",保证没有空格。
此输入我想转换为具有以下替换的LOGO命令:
seth 90 fd
lt 90 fd
fd 20 seth 0 fd 20 seth 90 fd 10 lt 90 fd 10
class MailJob extends Job
{
public $tries = 3;
public $status;
public function __construct()
{
$this->status = false; // set to false
}
/**
* Execute the job.
*/
public function handle()
{
$this->status = true;
// Assume job has failed, it went back to the Queue.
// status should be true when this job start processing again
}
}
因此上面的字符串输入将转换为这些LOGO命令:
JSONobject
所有Forth方言都允许输入,并解释一串命令。
但我无法通过搜索和替换字符串操作找到任何内容。在LOGO的任何方言中都可以这样做吗?愿意考虑任何。
感谢您的阅读。
答案 0 :(得分:2)
我已经有一段时间了,因为我已经写了任何徽标,所以我不确定这是否是最简单的方法,但这是你可以做到的一种方式。一般的想法是,您可以使用FIRST
,LAST
,BUTFIRST
和BUTLAST
来处理字符串作为字符列表,以获取字符串的不同部分。 (我在我能找到的前两个在线Logo解释器上进行了测试 - http://www.logointerpreter.com/turtle-editor.php和http://www.calormen.com/jslogo/ - 并且两者都运行良好,但是对于其他Logo方言,您可能需要进行一些小的更改。)< / p>
TO RUN_COMMANDS :commands
IF (EMPTY? :commands) [STOP]
MAKE "first_command (FIRST :commands)
MAKE "rest_of_commands (BUTFIRST :commands)
IF (NOT EMPTY? :rest_of_commands) [MAKE "split (GET_NUMBER :rest_of_commands ")]
MAKE "numeric_argument (LAST :split)
MAKE "rest_of_commands (FIRST :split)
RUN_SINGLE_COMMAND :first_command :numeric_argument
RUN_COMMANDS :rest_of_commands
END
TO MERGE_STRING :word :characters
IF (NOT EMPTY? :characters) [OP (MERGE_STRING (WORD :word (FIRST :characters)) (BUTFIRST :characters))]
OP :WORD
END
TO GET_NUMBER :word :number
IF (AND (NOT (EMPTY? :word)) (IS_DIGIT (FIRST :word))) [OP (SE (GET_NUMBER (BUTFIRST :word) (LPUT (FIRST :word) :number))]
OP (SE (MERGE_STRING " :word) (MERGE_STRING " :number))
END
TO IS_DIGIT :character
OP (OR
:character = "0
:character = "1
:character = "2
:character = "3
:character = "4
:character = "5
:character = "6
:character = "7
:character = "8
:character = "9)
END
TO RUN_SINGLE_COMMAND :command :parameter
(PRINT_COMMAND :command :parameter)
IF (:command = "F) [FD :parameter]
IF (:command = "B) [BK :parameter]
IF (:command = "L) [LT 90 FD :parameter]
IF (:command = "R) [RT 90 FD :parameter]
IF (:command = "N) [SETH 0 FD :parameter]
IF (:command = "S) [SETH 180 FD :parameter]
IF (:command = "E) [SETH 90 FD :parameter]
IF (:command = "W) [SETH 270 FD :parameter]
END
TO PRINT_COMMAND :command :parameter
IF (:command = "F) [PRINT (SE "FD :parameter)]
IF (:command = "B) [PRINT (SE "BK :parameter)]
IF (:command = "L) [PRINT (SE "LT 90 "FD :parameter)]
IF (:command = "R) [PRINT (SE "RT 90 "FD :parameter)]
IF (:command = "N) [PRINT (SE "SETH 0 "FD :parameter)]
IF (:command = "S) [PRINT (SE "SETH 180 "FD :parameter)]
IF (:command = "E) [PRINT (SE "SETH 90 "FD :parameter)]
IF (:command = "W) [PRINT (SE "SETH 270 "FD :parameter)]
END
然后,尝试运行:
RUN_COMMANDS "F20N20E10L10
这将打印并执行以下内容:
FD 20
SETH 0 FD 20
SETH 90 FD 10
LT 90 FD 10
一些解释
RUN_COMMANDS
是主要功能。它:
GET_NUMBER
,从字符串的开头提取一个数字(可能是多个字符)。RUN_SINGLE_COMMAND
IS_DIGIT
中使用 GET_NUMBER
来检查一个字符是否为数字(虽然我会打赌一些Logo方言有一个内置函数。)
MERGE_STRING
被使用是因为我有一些多字符的单词(&#34;单词&#34;是Logo代表一个字符串)我已经变成了单字符单词列表,我想要将列表合并回一个Word。但这可能不是必需的。
RUN_SINGLE_COMMAND
执行从输入字符串解析的每个单独命令。我刚刚使用了一个很大的IF
语句,而不是使用一个函数来解释字符串作为你建议的代码。 (某些徽标方言可能具有这样的功能,但我不确定是否有标准方法。)RUN_SINGLE_COMMAND
也会调用PRINT_COMMAND
,它会打印出未经简化的命令,因为它运行
潜在的堆栈溢出
我使用了很多递归,因为它更像是Logo的习惯,而且因为Logo方言通常没有很多循环结构(REPEAT
除外)。但我是以粗心的方式做到的,因为我只是快速写这篇文章给你一般的想法。特别是,我并不担心堆栈溢出(没有双关语),如果你提供了一个长输入字符串,我认为这可能会发生。要解决这个问题,你应该确保任何可以被任意调用多次的递归路径都是尾调用,Logo会优化掉。
乍一看,看起来RUN_COMMANDS
还可以,但MERGE_STRING
和GET_NUMBER
是相反的 - 而不是IF <condition> [<recursive_call>]
后跟OUTPUT <return_value>
,它会最好是IF (NOT <condition>) [OUTPUT <return_value>]
后跟<recursive_call>
。测试堆栈溢出并应用此修复我留给读者练习。 :)