【问题标题】:How to translate box representation to parenthesis representation如何将框表示转换为括号表示
【发布时间】:2021-01-25 05:28:26
【问题描述】:

我一直在做一些很清楚的事情,但在某些时候,我无法理解。

所以我知道这张图片代表(a b c x d)

但是,我不明白这个会发生什么:

既然有一个上面什么都没有,它指向了两个东西,那么如何用括号写b x 和d a 有两种方式

我会写(c((b(x))(d(a)))),但我不太确定。

感谢您的回答,我很感激;

【问题讨论】:

  • 请解释当你说“一个没有任何东西”和“一个指向两个东西”时哪个框有问题;并尝试逐步解释您如何选择基于框表示来编写括号符号。祝你好运
  • 当我谈论一个什么都没有和一个指向两件事的时候,我基本上是在谈论相同的,即第二个,介于 c 和 d 之间。我会这样写,因为首先我们有 c,然后我们什么都没有,所以我们打开 (,然后我们有 b,然后我们有 b,我们有 x,所以我们以 (c((b(x))) 结尾,然后我们返回第二个框,现在我们有 d 和 a,它们的样式与 b 和 x 相同,所以我最终得到 (c(bx)(da))

标签: scheme lisp common-lisp


【解决方案1】:

我认为思考这些问题的有用方法是实现两件事:

  • 所有框都是 cons 单元格,aka 对;
  • 使用了一种略显无用的速记,如果您在不使用速记的情况下重新绘制图表,则更容易翻译。

无用的简写是这样绘制的框:

其实就是这样:

() 是唯一的“空盒”对象,在 Lisp 中传统上称为 nil,但在 Scheme 中没有名称(我认为)作为标准。

所以知道了这个速记你就可以拍你的照片了,和这张是一样的

然后展开到这个

所以,好的,现在你有了这张展开的图片,你可以简单地把它的表示写成文本,记住 cons 单元格的表示只是(l . r),比如说,lr是左右元素,空框对象的表示为()

我不想写下你的问题的文字表示,因为我不想做你的作业 - 我想解释 如何 做你的作业! – 但我会写下它的表示,比如:

好吧,只要按照方框,我们就会得到一个表示

((x . ()) . (y . ())

哎呀,这与您需要得到的答案完全不同。

但一切都没有丢失。现在你需要知道最后一件事:有三个特殊规则适用于打印(或读取)这样的 conses 的树(图)。

  • 规则 1。 (<anything> . ()) 形式的 cons 可以写成 (<anything>)
  • 规则 2。右手条目 (cdr) 本身就是一个 cons 的 cons 可以省略点并拼接右手 cons。所以 (x . (y . ...)) 可以写成例如(x y . ...)
  • 规则 3。 在编写 cons 树时,您通常会尝试应用规则 1 和 2,以尽量减少打印表示中的点数。

让我们将这些规则应用到上述结构中。

  • 我们从((x . ()) . (y . ())开始;
  • 我们可以对每一半应用规则 1 两次,得到((x) . (y))
  • 我们现在可以应用规则 2 一次,因为顶部对象的右侧是一个缺点,得到 ((x) y)。而这就像你应该提供的那种表现形式。

作为应用这些规则时的指南,最好从内到外应用它们,并应用所有规则 1,然后再应用规则 2。

所以总的来说,我建议的方法是:

  1. 重新绘制图表,删除 () 的简写;
  2. 从中读取 cons-tree 结构为(... . ...)
  3. 使用上面的规则来最小化你写下的 cons-tree 中的点数;
  4. 利润。

【讨论】:

  • 非常感谢您的回答。这真的很有帮助而且很清楚。
  • 您的规则 1 和 2 在语法上是相同的:(A B ... . ( C ... )) == (A B ... C ... ),同时删除点和后面的一对括号,其中 B ... 和 @ 987654350@ 可以是空序列。
  • @WillNess:我知道这一点。但我的规则告诉你如何根据语义重写事物:(a) 的 cdr 不是 cons,因此“cdr is a cons”规则不适用。
【解决方案2】:

从配对开始。每个框都是(x . y),其中xy 是框指向的部分。例如。第一个是:

(a . (b . (c . (x . (d . ())))))

现在,如果可以的话,大多数 lisps 将删除 .cdr 周围的双亲。 (d . ()) => (d) 并且您可以一直应用此简化,以便显示上述内容:

(a b c x d)

元素和结尾之间缺失的点在我的脑海中意味着. (...),所以虽然我没有看到它们,但我在看它时会想象点符号。

第二个方框符号的意思很清楚:

(c . ((b . (x . ())) . (d . (a . ()))))

现在,如果cdr 中有括号,您就可以删除点了。我把它留给你去做,因为你需要在你的头脑中向前和向后进行这种转变。例如。您应该能够查看((e f) x (i j)) 并说((e . (f . ())) . (x . ((i . (j . ()))))) 并且访问jcadaddr(它可能不存在,因为它是5,并且要求是4,因此您可以将其拆分为(car (cdaddr '((e . (f . ())) . (x . ((i . (j . ()))))))) ; ==> j

【讨论】:

    【解决方案3】:

    你可以和https://github.com/cbaggers/draw-cons-tree一起玩

    CL-USER> (ql:quickload "draw-cons-tree")
    CL-USER> (draw-cons-tree:draw-tree '(c ((b (x)) (d (a)))))
    [o|o]---[o|/]
     |       |      
     C      [o|o]---[o|/]
             |       |      
             |      [o|o]---[o|/]
             |       |       |      
             |       D      [o|/]
             |               |      
             |               A      
             |      
            [o|o]---[o|/]
             |       |      
             B      [o|/]
                     |      
                     X      
    NIL
    CL-USER> (draw-cons-tree:draw-tree '(c ((b (x)) d a)))
    [o|o]---[o|/]
     |       |      
     C      [o|o]---[o|o]---[o|/]
             |       |       |      
             |       D       A      
             |      
            [o|o]---[o|/]
             |       |      
             B      [o|/]
                     |      
                     X      
    NIL
    CL-USER> 
    

    【讨论】:

      【解决方案4】:

      通过递归应用相同的转换来转换任何箱形图:

      [ * | * ] --->  B
        |
        |
        v
        A
      

      变成

      ( {A} . {B} )
      

      其中{A} 表示通过相同过程转换的图A

      一个特殊的情况是[ A | / ](把它写成一个简写形式

      [ * | / ]
        |
        |
        v
        A
      

      ) 与

      相同
      [ A | * ] ---> NIL
      

      基本情况是{NIL} === ()

      另一个基本情况是,不在盒子内的任何东西都是原样。

      箭头指向哪个方向并不重要,重要的是它是从框的第一个字段还是从第二个字段开始。

      你的最后一张图就变成了

      (c . { ...                                  })
      (c . ( {...}             . { ...           }))
      (c . ( {...}             . (d . { ...     })))
      (c . ( {...}             . (d . (a . {NIL}))))
      (c . ( (b . {...})       . (d . (a . {NIL}))))
      (c . ( (b . (x . {NIL})) . (d . (a . {NIL}))))
      (c . ( (b . (x . (   ))) . (d . (a . (   )))))
      

      在完整地转换了您的框和指针图之后,您将得到一个文本字符串表示形式。为了通过删除所有多余的点和括号对来简化它,最后应用规则

      (A B ... . (C ...))  ===  (A B ... C ...)  ;; NB nothing after (C ...)!
      

      以纯粹的句法方式,在字符串内的任何地方重复,直到它不能再被应用。只需同时删除列表中最后一个子表达式周围的点和以下一对匹配括号即可。 B ...C ... 序列都可以是空的,也可以是非空的:

      (c . ( (b . (x . (   ))) . (d . (a . (   )))))
      (c . ( (b . (x        )) . (d . (a . (   )))))
      (c . ( (b . (x        )) . (d . (a        ))))
      (c . ( (b . (x        )) . (d    a         )))
      (c . ( (b    x         ) . (d    a         )))
      (c . ( (b    x         )    d    a          ))
      

      或者您可以按不同的顺序执行它,如

      (c . ( (b . (x . (   ))) . (d . (a . (   )))))
      (c     (b . (x . (   ))) . (d . (a . (   ))) )
      (c     (b . (x . (   )))    d . (a . (   ))  )
      (c     (b . (x . (   )))    d    a . (   )   )
      (c     (b . (x        ))    d    a           )
      

      在这两种情况下,我都为您多做一步。最终结果将是相同的。

      【讨论】:

        猜你喜欢
        • 2020-03-10
        • 1970-01-01
        • 1970-01-01
        • 2015-10-09
        • 1970-01-01
        • 1970-01-01
        • 2022-10-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多