Skip to content

Commit e3d14a7

Browse files
ClémentClément
authored andcommitted
Releasing solution to AList.
1 parent d504298 commit e3d14a7

4 files changed

Lines changed: 346 additions & 0 deletions

File tree

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
5+
public class AList<T> : ICollection<T>
6+
{
7+
// Our implementation of list is so that
8+
// the alist array is always of the "right
9+
// size", so we don't need to keep track
10+
// of a separate counter for the size of the
11+
// list. This is more memory-
12+
// intensive (because arrays get created
13+
// frequently), but lighter to implement.
14+
private T[] alist;
15+
16+
public AList()
17+
{
18+
alist = new T[0];
19+
}
20+
21+
public bool IsEmpty()
22+
{
23+
return alist.Length == 0;
24+
}
25+
26+
public void Clear()
27+
{
28+
alist = new T[0];
29+
}
30+
31+
// Attribute and property for the
32+
// isReadOnly required by ICollection.
33+
public bool isReadonly = false;
34+
public bool IsReadOnly
35+
{
36+
get { return isReadonly; }
37+
set { isReadonly = value; }
38+
}
39+
40+
// Add is adding "to the left".
41+
public void Add(T value)
42+
{
43+
if (isReadonly)
44+
{
45+
throw new InvalidOperationException(
46+
"List is read-only, you cannot add to it."
47+
);
48+
}
49+
else
50+
{
51+
// We create a larger array
52+
// using the length of the existing
53+
// array.
54+
T[] newlist = new T[alist.Length + 1];
55+
// We insert the new value "to the left".
56+
newlist[0] = value;
57+
// We copy the remaining values,
58+
// shifting them by one.
59+
for (int i = 0; i < alist.Length; i++)
60+
newlist[i + 1] = alist[i];
61+
// Finally, our new array becomes our
62+
// alist attribute.
63+
alist = newlist;
64+
}
65+
}
66+
67+
68+
// Remove the first node containing the value
69+
// if it exists and returns true,
70+
// returns false otherwise.
71+
public bool Remove(T value)
72+
{
73+
if (isReadonly)
74+
{
75+
throw new InvalidOperationException(
76+
"List is read-only, you cannot remove from it."
77+
);
78+
}
79+
bool removed = false;
80+
if (!IsEmpty())
81+
{
82+
int i = 0;
83+
while (i < alist.Length && !removed)
84+
{
85+
if (alist[i].Equals(value))
86+
{
87+
removed = true;
88+
89+
// We create the array that will replace
90+
// the current one.
91+
92+
T[] newList = new T[alist.Length - 1];
93+
// We first copy the values
94+
// before the value we found:
95+
for (int j = 0; j < i; j++)
96+
newList[j] = alist[j];
97+
// We now copy the values *after*
98+
// the value we found.
99+
for (int j = i; j < newList.Length; j++)
100+
newList[j] = alist[j + 1];
101+
alist = newList;
102+
}
103+
i++;
104+
}
105+
}
106+
return removed;
107+
}
108+
109+
public bool Contains(T value)
110+
{
111+
// We start by assuming we did not find
112+
// the target value.
113+
bool found = false;
114+
// We go through the array.
115+
for (int i = 0; i < alist.Length; i++)
116+
{
117+
if (alist[i].Equals(value)) found = true;
118+
}
119+
return found;
120+
}
121+
122+
123+
// Adding "to the right" (as the last value).
124+
public void AddR(T value)
125+
{
126+
if (isReadonly)
127+
{
128+
throw new InvalidOperationException(
129+
"List is read-only, you cannot add to it."
130+
);
131+
}
132+
else
133+
{
134+
// We resize the array using
135+
// built-in method.
136+
Array.Resize(ref alist, alist.Length + 1);
137+
// We insert the new value "at the end".
138+
alist[alist.Length - 1] = value;
139+
}
140+
}
141+
142+
// Count property simply returns
143+
// the length of the alist array
144+
// if it is not null.
145+
public int Count
146+
{
147+
get
148+
{
149+
return alist.Length;
150+
}
151+
}
152+
153+
// Copies the elements of the ICollection to an Array, starting at a particular Array index.
154+
public void CopyTo(T[] array, int arrayIndex)
155+
{
156+
if (array == null)
157+
// The array into which we copy
158+
// cannot be null.
159+
throw new ArgumentNullException();
160+
if (arrayIndex < 0)
161+
// The index must be strictly positive.
162+
throw new ArgumentOutOfRangeException();
163+
if (Count > array.Length - arrayIndex)
164+
// If there is not enough room in the
165+
// array given as argument to copy
166+
// our list, we throw an exception.
167+
throw new ArgumentException(
168+
$"The destination array does not have enough space ({array.Length}) to copy the list ({Count}) starting at the given index ({arrayIndex})."
169+
);
170+
// If none of the exceptions were triggered,
171+
// we can copy the values at the right index.
172+
for (int i = 0; i < alist.Length; i++)
173+
{
174+
array[i + arrayIndex] = alist[i];
175+
}
176+
}
177+
178+
/* The following is "bureaucracy" to realize the
179+
* ICollection interface. */
180+
181+
public IEnumerator<T> GetEnumerator()
182+
{
183+
if (!IsEmpty())
184+
{
185+
for (int i = 0; i < alist.Length; i++)
186+
{
187+
yield return alist[i];
188+
}
189+
}
190+
}
191+
192+
IEnumerator IEnumerable.GetEnumerator()
193+
{
194+
return this.GetEnumerator(); // call the generic version of the method
195+
}
196+
197+
/* We are done realizing the ICollection interface. */
198+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
using System;
2+
3+
class Program
4+
{
5+
static void Main(string[] args)
6+
{
7+
AList<int> myList1 = new AList<int>();
8+
9+
/* Testing IsEmpty(), Clear() and Count. */
10+
Console.WriteLine("The list is empty: " + myList1.IsEmpty()); // Should display "True".
11+
Console.WriteLine("List size: " + myList1.Count); // Should display "0".
12+
myList1.Add(10);
13+
Console.WriteLine("The list is empty: " + myList1.IsEmpty()); // Should display "False".
14+
Console.WriteLine("List size: " + myList1.Count); // Should display "1".
15+
myList1.Clear();
16+
Console.WriteLine("The list is empty: " + myList1.IsEmpty()); // Should display "True".
17+
Console.WriteLine("List size: " + myList1.Count); // Should display "0".
18+
myList1.Add(10);
19+
myList1.Remove(10);
20+
Console.WriteLine("The list is empty: " + myList1.IsEmpty()); // Should display "True".
21+
Console.WriteLine("List size: " + myList1.Count); // Should display "0".
22+
23+
24+
/* Adding more elements, and then displaying the list.*/
25+
for (int i = 0; i < 15; i++)
26+
{
27+
myList1.Add(i);
28+
}
29+
30+
// A benefit of realizing the ICollection interface
31+
// is that we can iterate over elements of lists now:
32+
foreach (var item in myList1)
33+
{
34+
Console.Write(item + " ");
35+
}
36+
Console.WriteLine("");
37+
Console.WriteLine("List size: " + myList1.Count); // Should display "15".
38+
39+
/* Adding "from the rigt" */
40+
for (int i = -10; i < 0; i++)
41+
{
42+
myList1.AddR(i);
43+
}
44+
foreach (var item in myList1)
45+
{
46+
Console.Write(item + " ");
47+
}
48+
Console.WriteLine("");
49+
Console.WriteLine("List size: " + myList1.Count); // Should display "15".
50+
51+
52+
/* Testing Remove in more detail.*/
53+
54+
// 1. Removing a value that is present one time.
55+
Console.Write(
56+
"We removed an occurence of 10: "
57+
+ myList1.Remove(10)
58+
+ ".\n"
59+
);
60+
foreach (var item in myList1)
61+
{
62+
Console.Write(item + " ");
63+
}
64+
Console.WriteLine("");
65+
66+
// 2. Removing a value that is present three times.
67+
myList1.Add(1);
68+
myList1.Add(1);
69+
Console.Write(
70+
"We removed an occurence of 1: "
71+
+ myList1.Remove(1)
72+
+ ".\n"
73+
);
74+
foreach (var item in myList1)
75+
{
76+
Console.Write(item + " ");
77+
}
78+
Console.WriteLine("");
79+
80+
// 3. Removing a value that is not in the list.
81+
Console.Write(
82+
"We removed an occurence of 20: "
83+
+ myList1.Remove(20)
84+
+ ".\n"
85+
);
86+
foreach (var item in myList1)
87+
{
88+
Console.Write(item + " ");
89+
}
90+
Console.WriteLine("");
91+
92+
93+
/*
94+
* Advanced testing:
95+
* IsReadOnly and CopyTo.
96+
*/
97+
Console.WriteLine(
98+
"Our list is read-only: " + myList1.IsReadOnly + "."
99+
);
100+
myList1.IsReadOnly = true;
101+
Console.WriteLine(
102+
"Our list is read-only: " + myList1.IsReadOnly + "."
103+
);
104+
try
105+
{
106+
myList1.Add(12);
107+
}
108+
catch (Exception ex)
109+
{
110+
Console.WriteLine(ex.Message);
111+
}
112+
try
113+
{
114+
myList1.Remove(1);
115+
}
116+
catch (Exception ex)
117+
{
118+
Console.WriteLine(ex.Message);
119+
}
120+
121+
int[] array = new int[myList1.Count + 1];
122+
try
123+
{
124+
myList1.CopyTo(array, 6);
125+
}
126+
catch (Exception ex)
127+
{
128+
Console.WriteLine(ex.Message);
129+
}
130+
// We insert a dummy value
131+
// into the array that will receive
132+
// a copy of the list at index 1.
133+
array[0] = -10;
134+
myList1.CopyTo(array, 1);
135+
Console.WriteLine("The array contains:");
136+
foreach (int i in array)
137+
{
138+
Console.Write(i + " ");
139+
}
140+
}
141+
}

source/projects/AList.zip

-2.21 KB
Binary file not shown.

source/projects/alist.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,10 @@ Bonus points will be given if:
7777

7878
Please, follow our [guideline on project submission](./projects/submission).
7979
In particular, make sure you write your name and the date in a delimited comment at the beginning of your file.
80+
81+
82+
## Solution
83+
84+
A possible solution is shared [in this archive](./code/projects/AList.zip).
85+
86+
Note that it does not use a "counter" to keep track of how many elements are in the list, but instead resize the array and create a new array of the appropriate size when needed: this is less efficient, since copying the array is linear in its size, but gives a more compact code.

0 commit comments

Comments
 (0)