如何在LOGO中执行子字符串替换?

时间:2017-08-03 13:11:05

标签: replace string-matching logo-lang

我想从用户那里获取字符串,解析它,然后运行已解析的命令。

字符串输入类似于" F20N20E10L10",保证没有空格。

此输入我想转换为具有以下替换的LOGO命令:

  • " F" →seth 90 fd
  • " N" →lt 90 fd
  • " E" →fd 20 seth 0 fd 20 seth 90 fd 10 lt 90 fd 10
  • " L" →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的任何方言中都可以这样做吗?愿意考虑任何。

感谢您的阅读。

1 个答案:

答案 0 :(得分:2)

我已经有一段时间了,因为我已经写了任何徽标,所以我不确定这是否是最简单的方法,但这是你可以做到的一种方式。一般的想法是,您可以使用FIRSTLASTBUTFIRSTBUTLAST来处理字符串作为字符列表,以获取字符串的不同部分。 (我在我能找到的前两个在线Logo解释器上进行了测试 - http://www.logointerpreter.com/turtle-editor.phphttp://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是主要功能。它:

  1. 从sting中提取第一个字母(我假设每个命令都缩写为单个字母)
  2. 调用GET_NUMBER,从字符串的开头提取一个数字(可能是多个字符)。
  3. 将单字母缩写的命令和数字传递给RUN_SINGLE_COMMAND
  4. 递归以重复此过程
  5. 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_STRINGGET_NUMBER是相反的 - 而不是IF <condition> [<recursive_call>]后跟OUTPUT <return_value>,它会最好是IF (NOT <condition>) [OUTPUT <return_value>]后跟<recursive_call>。测试堆栈溢出并应用此修复我留给读者练习。 :)