Get a subtree by breadth-first index using continuation-passing style

落爺英雄遲暮 提交于 2021-01-04 06:38:07

问题


This question is a follow-up on How do I get a subtree by index?. That question deals with depth-first indexing (for which I have provided a depth-first continuation-passing style solution). This question here is about breadth-first indexing, and specifically about solving the problem using continuation-passing style (CPS).

Suppose I have a tree that represents '(+ (* 5 6) (sqrt 3)):

The index of nodes starts from 0 at the root, and is breadth-first. In the picture above, I have labelled all the nodes with their index to show this.

I would like to define a function subtree-bfs that takes a tree and an index number, and returns the subtree rooted at the given index. For example:

(define tree '(+ (* 5 6) (sqrt 3)))

(subtree-bfs tree 0)  ; Returns: '(+ (* 5 6) (sqrt 3)))
(subtree-bfs tree 1)  ; Returns: '(* 5 6)
(subtree-bfs tree 2)  ; Returns: '(sqrt 3)
(subtree-bfs tree 3)  ; Returns: 5
(subtree-bfs tree 4)  ; Returns: 6
(subtree-bfs tree 5)  ; Returns: 3

I would like to solve the problem using continuation-passing style. How do I define subtree-bfs?


So far, I have this:

(define (node-children node)
  ;; (node-children 123) -> '()
  ;; (node-children (+ 1 (+ 2 3))) -> '(1 (+ 2 3))
  (cond [(pair? node) (cdr node)]
        [(null? node) (error "Invalid node" node)]
        [else '()]))

(define (traverse-row& nodes index counter k)
  ;; 'counter' is the index number of the first node in 'nodes'.
  (cond [(null? nodes) (k counter)]
        [(= counter index) (car nodes)]
        [else
         (traverse-row& (cdr nodes)
                        index
                        (+ counter 1)
                        k)]))

(define (children-k children index k)
  (if (null? children)
      k
      (lambda (counter)
        (subtree-bfs& (car children)
                      index
                      counter
                      (children-k (cdr children) index k)))))

(define (subtree-bfs& nodes index counter k)
  (traverse-row& nodes
                 index
                 counter
                 (children-k (map (lambda (node)
                                    (node-children node))
                                  nodes)
                             index
                             k)))

(define (subtree-bfs tree index)
  (subtree-bfs& (list tree)
                index
                0
                (lambda (max-index+1)
                  ;; (- max-index+1 1) represents the maximum valid index number.
                  (error "Index out of bounds" index))))

This implementation appears to work correctly. However, it seems rather long. Since I am inexperienced with CPS, I thought that there must be a better CPS solution to this problem. Is there a better CPS solution?

Note 1: Forgive me for not adequately commenting the code. I must admit that I do not completely understand the solution myself (!) I am rather amazed that I was able to find a solution in the first place.

Note 2: This question may be more suitable for the code review site. However, given the lack of attention to Scheme and Racket over there, a question like this would likely never be answered.

来源:https://stackoverflow.com/questions/65485997/get-a-subtree-by-breadth-first-index-using-continuation-passing-style

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!