Commit cb659ece authored by Robert Griesemer's avatar Robert Griesemer

additions to array container:

- added Slice, Cut, InsertArray, AppendArray
- renamed Remove -> Delete (so we have: Insert, Delete, Cut)
- more factoring of code
- extra tests (could use some more)

R=r,rsc
DELTA=179  (127 added, 22 deleted, 30 changed)
OCL=23648
CL=23685
parent 712522a6
...@@ -4,13 +4,47 @@ ...@@ -4,13 +4,47 @@
package array package array
type Element interface { type (
Element interface {};
Array struct {
a []Element
}
)
func copy(dst, src []Element) {
for i := 0; i < len(src); i++ {
dst[i] = src[i]
}
} }
type Array struct { // Insert n elements at position i.
// TODO do not export field func expand(a []Element, i, n int) []Element {
a []Element // make sure we have enough space
len0 := len(a);
len1 := len0 + n;
if len1 < cap(a) {
// enough space - just expand
a = a[0 : len1]
} else {
// not enough space - double capacity
capb := cap(a)*2;
if capb < len1 {
// still not enough - use required length
capb = len1
}
// capb >= len1
b := make([]Element, len1, capb);
copy(b, a);
a = b
}
// make a hole
for j := len0-1; j >= i ; j-- {
a[j+n] = a[j]
}
return a
} }
...@@ -61,52 +95,65 @@ func (p *Array) Last() Element { ...@@ -61,52 +95,65 @@ func (p *Array) Last() Element {
func (p *Array) Insert(i int, x Element) { func (p *Array) Insert(i int, x Element) {
p.a = expand(p.a, i, 1);
p.a[i] = x;
}
func (p *Array) Delete(i int) Element {
a := p.a; a := p.a;
n := len(a); n := len(a);
// grow array by doubling its capacity x := a[i];
if n == cap(a) { copy(a[i : n-1], a[i+1 : n]);
b := make([]Element, 2*n); a[n-1] = nil; // support GC, nil out entry
for j := n-1; j >= 0; j-- { p.a = a[0 : n-1];
b[j] = a[j];
} return x
a = b }
}
// make a hole
a = a[0 : n+1];
for j := n; j > i; j-- {
a[j] = a[j-1]
}
a[i] = x; func (p *Array) InsertArray(i int, x *Array) {
p.a = a p.a = expand(p.a, i, len(x.a));
copy(p.a[i : i + len(x.a)], x.a);
} }
func (p *Array) Remove(i int) Element { func (p *Array) Cut(i, j int) {
a := p.a; a := p.a;
n := len(a); n := len(a);
m := n - (j - i);
x := a[i]; copy(a[i : m], a[j : n]);
for j := i+1; j < n; j++ { for k := m; k < n; k++ {
a[j-1] = a[j] a[k] = nil // support GC, nil out entries
} }
a[n-1] = nil; // support GC, nil out entry p.a = a[0 : m];
p.a = a[0 : n-1]; }
return x
func (p *Array) Slice(i, j int) *Array {
s := New(j - i); // will fail in Init() if j < j
copy(s.a, p.a[i : j]);
return s;
} }
// Convenience wrappers
func (p *Array) Push(x Element) { func (p *Array) Push(x Element) {
p.Insert(len(p.a), x) p.Insert(len(p.a), x)
} }
func (p *Array) Pop() Element { func (p *Array) Pop() Element {
return p.Remove(len(p.a) - 1) return p.Delete(len(p.a) - 1)
}
func (p *Array) AppendArray(x *Array) {
p.InsertArray(len(p.a), x);
} }
......
...@@ -24,7 +24,7 @@ func TestNew(t *testing.T) { ...@@ -24,7 +24,7 @@ func TestNew(t *testing.T) {
} }
func Val(i int) int { func val(i int) int {
return i*991 - 1234 return i*991 - 1234
} }
...@@ -34,34 +34,34 @@ func TestAccess(t *testing.T) { ...@@ -34,34 +34,34 @@ func TestAccess(t *testing.T) {
var a array.Array; var a array.Array;
a.Init(n); a.Init(n);
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
a.Set(i, Val(i)); a.Set(i, val(i));
} }
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
if a.At(i).(int) != Val(i) { t.Error(i) } if a.At(i).(int) != val(i) { t.Error(i) }
} }
} }
func TestInsertRemoveClear(t *testing.T) { func TestInsertDeleteClear(t *testing.T) {
const n = 100; const n = 100;
a := array.New(0); a := array.New(0);
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
if a.Len() != i { t.Errorf("A wrong len %d (expected %d)", a.Len(), i) } if a.Len() != i { t.Errorf("A) wrong len %d (expected %d)", a.Len(), i) }
a.Insert(0, Val(i)); a.Insert(0, val(i));
if a.Last().(int) != Val(0) { t.Error("B") } if a.Last().(int) != val(0) { t.Error("B") }
} }
for i := n-1; i >= 0; i-- { for i := n-1; i >= 0; i-- {
if a.Last().(int) != Val(0) { t.Error("C") } if a.Last().(int) != val(0) { t.Error("C") }
if a.Remove(0).(int) != Val(i) { t.Error("D") } if a.Delete(0).(int) != val(i) { t.Error("D") }
if a.Len() != i { t.Errorf("E wrong len %d (expected %d)", a.Len(), i) } if a.Len() != i { t.Errorf("E) wrong len %d (expected %d)", a.Len(), i) }
} }
if a.Len() != 0 { t.Errorf("F wrong len %d (expected 0)", a.Len()) } if a.Len() != 0 { t.Errorf("F) wrong len %d (expected 0)", a.Len()) }
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
a.Push(Val(i)); a.Push(val(i));
if a.Len() != i+1 { t.Errorf("G wrong len %d (expected %d)", a.Len(), i+1) } if a.Len() != i+1 { t.Errorf("G) wrong len %d (expected %d)", a.Len(), i+1) }
if a.Last().(int) != Val(i) { t.Error("H") } if a.Last().(int) != val(i) { t.Error("H") }
} }
a.Init(0); a.Init(0);
if a.Len() != 0 { t.Errorf("I wrong len %d (expected 0)", a.Len()) } if a.Len() != 0 { t.Errorf("I wrong len %d (expected 0)", a.Len()) }
...@@ -70,17 +70,76 @@ func TestInsertRemoveClear(t *testing.T) { ...@@ -70,17 +70,76 @@ func TestInsertRemoveClear(t *testing.T) {
for j := 0; j < m; j++ { for j := 0; j < m; j++ {
a.Push(j); a.Push(j);
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
x := Val(i); x := val(i);
a.Push(x); a.Push(x);
if a.Pop().(int) != x { t.Error("J") } if a.Pop().(int) != x { t.Error("J") }
if a.Len() != j+1 { t.Errorf("K wrong len %d (expected %d)", a.Len(), j+1) } if a.Len() != j+1 { t.Errorf("K) wrong len %d (expected %d)", a.Len(), j+1) }
} }
} }
if a.Len() != m { t.Errorf("L wrong len %d (expected %d)", a.Len(), m) } if a.Len() != m { t.Errorf("L) wrong len %d (expected %d)", a.Len(), m) }
}
func verify_slice(t *testing.T, x *array.Array, elt, i, j int) {
for k := i; k < j; k++ {
if x.At(k).(int) != elt {
t.Errorf("M) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt)
}
}
s := x.Slice(i, j);
for k, n := 0, j-i; k < n; k++ {
if s.At(k).(int) != elt {
t.Errorf("N) wrong [%d] element %d (expected %d)", k, x.At(k).(int), elt)
}
}
}
func verify_pattern(t *testing.T, x *array.Array, a, b, c int) {
n := a + b + c;
if x.Len() != n {
t.Errorf("O) wrong len %d (expected %d)", x.Len(), n)
}
verify_slice(t, x, 0, 0, a);
verify_slice(t, x, 1, a, a + b);
verify_slice(t, x, 0, a + b, n);
}
func make_array(elt, len int) *array.Array {
x := array.New(len);
for i := 0; i < len; i++ {
x.Set(i, elt);
}
return x;
}
func TestInsertArray(t *testing.T) {
// 1
a := make_array(0, 0);
b := make_array(1, 10);
a.InsertArray(0, b);
verify_pattern(t, a, 0, 10, 0);
// 2
a = make_array(0, 10);
b = make_array(1, 0);
a.InsertArray(5, b);
verify_pattern(t, a, 5, 0, 5);
// 3
a = make_array(0, 10);
b = make_array(1, 3);
a.InsertArray(3, b);
verify_pattern(t, a, 3, 3, 7);
// 4
a = make_array(0, 10);
b = make_array(1, 1000);
a.InsertArray(8, b);
verify_pattern(t, a, 8, 1000, 2);
} }
/* currently doesn't compile due to linker bug
func TestSorting(t *testing.T) { func TestSorting(t *testing.T) {
const n = 100; const n = 100;
a := array.NewIntArray(n); a := array.NewIntArray(n);
...@@ -89,4 +148,3 @@ func TestSorting(t *testing.T) { ...@@ -89,4 +148,3 @@ func TestSorting(t *testing.T) {
} }
if sort.IsSorted(a) { t.Error("not sorted") } if sort.IsSorted(a) { t.Error("not sorted") }
} }
*/
...@@ -43,8 +43,8 @@ func (p *IntArray) Insert(i int, x int) { ...@@ -43,8 +43,8 @@ func (p *IntArray) Insert(i int, x int) {
} }
func (p *IntArray) Remove(i int) int { func (p *IntArray) Delete(i int) int {
return p.Array.Remove(i).(int) return p.Array.Delete(i).(int)
} }
......
...@@ -50,7 +50,7 @@ func test1() { ...@@ -50,7 +50,7 @@ func test1() {
} }
for v.Len() > 10 { for v.Len() > 10 {
v.Remove(10); v.Delete(10);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment