2 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
3 Permission is hereby granted, free of charge, to any person obtaining a copy
4 of this software and associated documentation files (the "Software"), to deal
5 in the Software without restriction, including without limitation the rights
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 copies of the Software, and to permit persons to whom the Software is
8 furnished to do so, subject to the following conditions:
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 // C5 example: ViewPatterns 2005-07-22
25 // csc /r:C5.dll ViewPatterns.cs
29 using SCG
= System
.Collections
.Generic
;
31 namespace ViewPatterns
{
33 public static void Main(String
[] args
) {
34 IList
<char> lst
= new ArrayList
<char>();
35 lst
.AddAll
<char>(new char[] { 'a', 'b', 'c', 'd' }
);
36 IList
<char> v1
= lst
.View(1, 1);
37 Console
.WriteLine("v1 = {0}", v1
);
38 InsertBeforeFirst(v1
, '<', 'b');
39 InsertAfterFirst(v1
, '>', 'b');
40 Console
.WriteLine("v1 = {0}", v1
);
42 if (SequencePredecessor(v1
, 'b', out x
))
43 Console
.WriteLine("Predecessor of b is " + x
);
44 if (SequenceSuccessor(v1
, 'b', out x
))
45 Console
.WriteLine("Successor of b is " + x
);
46 if (!SequencePredecessor(v1
, 'c', out x
))
47 Console
.WriteLine("c has no predecessor");
48 if (!SequenceSuccessor(v1
, 'a', out x
))
49 Console
.WriteLine("a has no successor");
50 IList
<char> lst2
= new ArrayList
<char>();
51 lst2
.AddAll
<char>(new char[] { 'a', 'b', 'c', 'A', 'a', 'd', 'a' }
);
52 foreach (int i
in IndexesOf(lst2
, 'a'))
53 Console
.Write("{0} ", i
);
55 foreach (int i
in ReverseIndexesOf(lst2
, 'a'))
56 Console
.Write("{0} ", i
);
58 Console
.WriteLine(lst2
);
59 IList
<char> view
= lst2
.View(2,0);
60 InsertAtView(lst2
, view
, 'y');
61 Console
.WriteLine(lst2
);
62 InsertIntoView(view
, 'x');
63 Console
.WriteLine(lst2
);
66 // --- Patterns for zero-item views -----------------------------
68 // Number of items before zero-item view
70 public static int ItemsBefore
<T
>(IList
<T
> view
) {
74 // Number of items after zero-item view
76 public static int ItemsAfter
<T
>(IList
<T
> view
) {
77 return view
.Underlying
.Count
- view
.Offset
;
80 // Move (zero-item) view one item to the left
82 public static void MoveLeft
<T
>(IList
<T
> view
) {
88 // Move (zero-item) view one item to the right
90 public static void MoveRight
<T
>(IList
<T
> view
) {
96 // Test whether (zero-item) view is at beginning of list
98 public static bool AtBeginning
<T
>(IList
<T
> view
) {
99 return view
.Offset
== 0;
102 // Test whether (zero-item) view is at end of list
104 public static bool AtEnd
<T
>(IList
<T
> view
) {
105 return view
.Offset
== view
.Underlying
.Count
;
108 // Insert x into zero-item view and into underlying list
110 public static void InsertIntoView
<T
>(IList
<T
> view
, T x
) {
114 // Insert x into list at zero-item view
116 public static void InsertAtView
<T
>(IList
<T
> list
, IList
<T
> view
, T x
) {
117 list
.Insert(view
, x
);
120 // Delete the item before zero-item view
122 public static void DeleteBefore
<T
>(IList
<T
> view
) {
123 view
.Slide(-1,1).RemoveFirst();
126 // Delete the item after zero-item view
128 public static void DeleteAfter
<T
>(IList
<T
> view
) {
129 view
.Slide(0,1).RemoveFirst();
132 // Get the zero-item view at left endpoint. Succeeds on all lists
135 public static IList
<T
> LeftEndView
<T
>(IList
<T
> list
) {
136 return list
.View(0,0);
139 // Get the zero-item view at right endpoint. Succeeds on all
140 // lists and valid views.
142 public static IList
<T
> RightEndView
<T
>(IList
<T
> list
) {
143 return list
.View(list
.Count
,0);
147 // --- Patterns for one-item views ------------------------------
149 // Find the sequence predecessor x of y; or throw exception
151 public static T SequencePredecessor
<T
>(IList
<T
> list
, T y
) {
152 return list
.ViewOf(y
).Slide(-1)[0];
155 // Find the sequence predecessor x of y; or return false
157 public static bool SequencePredecessor
<T
>(IList
<T
> list
, T y
, out T x
) {
158 IList
<T
> view
= list
.ViewOf(y
);
159 bool ok
= view
!= null && view
.TrySlide(-1);
160 x
= ok
? view
[0] : default(T
);
164 // Find the sequence successor x of y; or throw exception
166 public static T SequenceSuccessor
<T
>(IList
<T
> list
, T y
) {
167 return list
.ViewOf(y
).Slide(+1)[0];
170 // Find the sequence successor x of y; or return false
172 public static bool SequenceSuccessor
<T
>(IList
<T
> list
, T y
, out T x
) {
173 IList
<T
> view
= list
.ViewOf(y
);
174 bool ok
= view
!= null && view
.TrySlide(+1);
175 x
= ok
? view
[0] : default(T
);
179 // Insert x into list after first occurrence of y (or throw
180 // NullReferenceException).
182 public static void InsertAfterFirst
<T
>(IList
<T
> list
, T x
, T y
) {
183 list
.Insert(list
.ViewOf(y
), x
);
186 // Insert x into list before first occurrence of y (or throw
187 // NullReferenceException)
189 public static void InsertBeforeFirst
<T
>(IList
<T
> list
, T x
, T y
) {
190 list
.Insert(list
.ViewOf(y
).Slide(0, 0), x
);
193 // Insert x into list after last occurrence of y (or throw
194 // NullReferenceException).
196 public static void InsertAfterLast
<T
>(IList
<T
> list
, T x
, T y
) {
197 list
.Insert(list
.LastViewOf(y
), x
);
200 // Insert x into list before last occurrence of y (or throw
201 // NullReferenceException)
203 public static void InsertBeforeLast
<T
>(IList
<T
> list
, T x
, T y
) {
204 list
.Insert(list
.LastViewOf(y
).Slide(0, 0), x
);
207 // Same meaning as InsertBeforeFirst on a proper list, but not on
210 public static void InsertBeforeFirstAlt
<T
>(IList
<T
> list
, T x
, T y
) {
211 list
.ViewOf(y
).InsertFirst(x
);
214 // Delete the sequence predecessor of first y; or throw exception
216 public static T RemovePredecessorOfFirst
<T
>(IList
<T
> list
, T y
) {
217 return list
.ViewOf(y
).Slide(-1).Remove();
220 // Delete the sequence successor of first y; or throw exception
222 public static T RemoveSuccessorOfFirst
<T
>(IList
<T
> list
, T y
) {
223 return list
.ViewOf(y
).Slide(+1).Remove();
226 // --- Other view patterns --------------------------------------
228 // Replace the first occurrence of each x from xs by y in list:
230 public static void ReplaceXsByY
<T
>(HashedLinkedList
<T
> list
, T
[] xs
, T y
) {
231 foreach (T x
in xs
) {
232 using (IList
<T
> view
= list
.ViewOf(x
)) {
241 // Get index in underlying list of view's left end
243 public static int LeftEndIndex
<T
>(IList
<T
> view
) {
247 // Get index in underlying list of view's right end
249 public static int RightEndIndex
<T
>(IList
<T
> view
) {
250 return view
.Offset
+ view
.Count
;
253 // Test whether views overlap
255 public static bool Overlap
<T
>(IList
<T
> u
, IList
<T
> w
) {
256 if (u
.Underlying
== null || u
.Underlying
!= w
.Underlying
)
257 throw new ArgumentException("views must have same underlying list");
259 return u
.Offset
< w
.Offset
+w
.Count
&& w
.Offset
< u
.Offset
+u
.Count
;
262 // Find the length of the overlap between two views
264 public static int OverlapLength
<T
>(IList
<T
> u
, IList
<T
> w
) {
266 return Math
.Min(u
.Offset
+u
.Count
, w
.Offset
+w
.Count
)
267 - Math
.Max(u
.Offset
, w
.Offset
);
269 return -1; // No overlap
272 // Test whether view u contains view v
274 public static bool ContainsView
<T
>(IList
<T
> u
, IList
<T
> w
) {
275 if (u
.Underlying
== null || u
.Underlying
!= w
.Underlying
)
276 throw new ArgumentException("views must have same underlying list");
279 return u
.Offset
<= w
.Offset
&& w
.Offset
+w
.Count
<= u
.Offset
+u
.Count
;
281 return u
.Offset
< w
.Offset
&& w
.Offset
< u
.Offset
+u
.Count
;
284 // Test whether views u and v have (or are) the same underlying list
286 public static bool SameUnderlying
<T
>(IList
<T
> u
, IList
<T
> w
) {
287 return (u
.Underlying
?? u
) == (w
.Underlying
?? w
);
290 // Find the index of the first item that satisfies p
292 public static int FindFirstIndex
<T
>(IList
<T
> list
, Fun
<T
,bool> p
) {
293 using (IList
<T
> view
= list
.View(0, 0)) {
294 while (view
.TrySlide(0, 1)) {
303 // Find the index of the last item that satisfies p
305 public static int FindLastIndex
<T
>(IList
<T
> list
, Fun
<T
,bool> p
) {
306 using (IList
<T
> view
= list
.View(list
.Count
, 0)) {
307 while (view
.TrySlide(-1, 1)) {
315 // Yield indexes of all items equal to x, in list order:
317 public static SCG
.IEnumerable
<int> IndexesOf
<T
>(IList
<T
> list
, T x
) {
318 IList
<T
> tail
= list
.View(0, list
.Count
);
319 tail
= tail
.ViewOf(x
);
320 while (tail
!= null) {
321 yield return tail
.Offset
;
322 tail
= tail
.Slide(+1,0).Span(list
);
323 tail
= tail
.ViewOf(x
);
327 // Yield indexes of items equal to x, in reverse list order.
329 public static SCG
.IEnumerable
<int> ReverseIndexesOf
<T
>(IList
<T
> list
, T x
) {
330 IList
<T
> head
= list
.View(0, list
.Count
);
331 head
= head
.LastViewOf(x
);
332 while (head
!= null) {
333 yield return head
.Offset
;
334 head
= list
.Span(head
.Slide(0,0));
335 head
= head
.LastViewOf(x
);