3 Smalltalk implementation of a `same-fringe' solver.
5 Use GNU Smalltalk syntax -- it seems more Emacs-friendly.
8 Object subclass: Node [
11 <comment: 'I represent simple binary tree nodes. My instances consist of
12 a data object, and left and right subtrees. The leaves of a tree are
13 instances of LeafNode.'>
14 <category: 'Toys-SameFringe'>
16 Node class >> left: aNode data: anObject right: anotherNode [
17 "Answer a newly tree Node with the given subtrees and data."
19 <category: 'instance creation'>
20 ^self new left: aNode data: anObject right: anotherNode
23 Node class >> parse: aString [
24 "Answer a newly constructed tree, parsed from aString."
28 stream := ReadStream on: aString.
29 tree := stream parseTree.
30 stream atEnd ifFalse: [self error: 'trailing junk'].
34 left: aNode data: anObject right: anotherNode [
35 "Initialize a (presumably) new instance."
37 <category: 'initialization'>
45 "Answer the receiver's left subtree."
47 <category: 'accessing'>
52 "Answer the receiver's right subtree."
54 <category: 'accessing'>
59 "Answer the receiver's data."
61 <category: 'accessing'>
66 "Answer false, becase the receiver is not a leaf."
73 "Answer a new iterator to walk this node."
75 <category: 'iteration'>
76 ^NodeIterator for: self
79 inorderTell: aBlock tell: aNodeIterator [
80 "This is the hairy part of the iteration protocol.
82 The algorithm works like this. We're meant to wander as far down
83 the left of the tree as we can; once we're there, we call
84 aNodeIterator with the data we found and a block which will continue
85 the iteration over the rest of the tree and finally invoke aBlock.
87 Observe that there are no explicit conditionals here. It's all done
88 with object dispatch. And smoke. And mirrors.
90 Also note that this is tail-recursive. The `stack' is built up in
91 the hairy block constructions, which all go on the heap."
93 <category: 'private iteration'>
98 then: [right inorderTell: aBlock tell: aNodeIterator]]
102 sameFringeAs: aNode [
103 "Answer whether traversing the receiver inorder yields the same
104 objects as traversing aNode."
106 <category: 'comparison'>
109 ib := aNode iterator.
110 [ia atEnd] whileFalse:
111 [ib atEnd ifTrue: [^false].
112 (ia next = ib next) ifFalse: [^false]].
117 "Write a simple representation of self to the stream."
119 <category: 'printing'>
127 Node class >> main: anArray [
128 "Noddy script main program."
130 <category: 'command line'>
133 [(self parse: (anArray at: 1)) iterator do:
134 [:char | FileStream stdout nextPut: char].
135 FileStream stdout nl];
137 [FileStream stdout display:
138 (((self parse: (anArray at: 1))
139 sameFringeAs: (self parse: (anArray at: 2)))
141 ifFalse: ['no match']);
143 at: anArray size ifAbsent: [self error: 'bad args'])
148 nextPutAll: 'smalltalk-fringe: ';
149 nextPutAll: error messageText;
156 PositionableStream extend [
158 "Answer a newly constructed tree, parsed from the receiver.
160 The syntax is very simple:
162 tree ::= empty | `(' tree char tree `)'
164 where char is any character. Ambiguity is resolved by deciding that
165 something beginning with `(' where a tree is expected really is a
166 tree and not an empty tree followed by the char `('."
168 <category: 'parsing'>
171 self peek = $( ifFalse: [^LeafNode instance].
173 left := self parseTree.
174 self atEnd ifTrue: [self error: 'no data'].
176 right := self parseTree.
177 self next = $) ifFalse: [self error: 'missing )'].
178 ^Node left: left data: data right: right
182 Object subclass: LeafNode [
183 <comment: 'I represent the leaves of a tree of Nodes. I don''t hold any
184 kind of interesting state. My methods provide the base cases for some of the
185 recursive protocols used to handle Nodes.'>
186 <category: 'Toys-SameFringe'>
188 instance := LeafNode new.
191 "Write a simple representation of self to the stream."
193 <category: 'printing'>
198 "Answer true, because the receiver is a leaf node."
200 <category: 'testing'>
205 "Return a new iterator to walk this node."
207 <category: 'iteration'>
208 ^NodeIterator for: self
211 inorderTell: aBlock tell: aNodeIterator [
212 "This is the hairy part of the iteration protocol.
214 But in this case it's simple. We've overshot the end, so we just
215 need to call aBlock to persuade our parent to announce itself to the
218 <category: 'private iteration'>
222 LeafNode class >> instance [
223 "Return the unique instance of the leaf node."
225 <category: 'singleton'>
230 Stream subclass: NodeIterator [
233 <comment: 'I hold the state for external iteration of trees of Nodes and
234 (halfheartedly) implement the Stream protocol.'>
235 <category: 'Toys-SameFringe'>
237 found: anObject then: aBlock [
238 "Stash the newly found item from the hairy iteration protocol.
240 When the iteration protocol decides on the next leftmost item to
241 return, it gives us anObject that it found, and aBlock which will
242 continue until it finds the next object."
244 <category: 'private iteration'>
249 NodeIterator class >> for: aNode [
250 "Answer a new iterator for the tree starting at aNode."
252 <category: 'instance creation'>
253 ^self new walk: aNode
257 "Start walking a subtree starting at aNode.
259 We get the node to iterate itself and finally tell us that it's
262 <category: 'initialization'>
263 aNode inorderTell: [rest := nil] tell: self
267 "Answer the next element from the tree, or nil if we've hit the end."
269 <category: 'reading'>
278 "Answer the next element without removing it."
280 <category: 'reading'>
281 rest ifNil: [^nil] ifNotNil: [^item]
285 "Answer whether we have reached the end of the iteration."
287 <category: 'testing'>