From 76e326488d0177e74f5fc5972250fab2bc073345 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Thu, 5 Mar 2015 16:29:33 +0100 Subject: [PATCH] hashset implemented (with tests) --- sets/hashset/hashset.go | 101 ++++++++++++++++++++++ sets/hashset/hashset_test.go | 83 ++++++++++++++++++ stacks/linkedliststack/linkedliststack.go | 2 +- 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 sets/hashset/hashset.go create mode 100644 sets/hashset/hashset_test.go diff --git a/sets/hashset/hashset.go b/sets/hashset/hashset.go new file mode 100644 index 0000000..e45a4df --- /dev/null +++ b/sets/hashset/hashset.go @@ -0,0 +1,101 @@ +/* +Copyright (c) Emir Pasic, All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. See the file LICENSE included +with this distribution for more information. +*/ + +// Implementation of set backed by a hash table. +// Structure is not thread safe. +// References: http://en.wikipedia.org/wiki/Set_%28abstract_data_type%29 + +package hashset + +import ( + "fmt" + "strings" +) + +type Set struct { + items map[interface{}]struct{} +} + +var itemExists = struct{}{} + +// Instantiates a new empty set +func New() *Set { + return &Set{items: make(map[interface{}]struct{})} +} + +// Adds the items (one or more) to the set. +func (set *Set) Add(items ...interface{}) { + for _, item := range items { + set.items[item] = itemExists + } +} + +// Removes the items (one or more) from the set. +func (set *Set) Remove(items ...interface{}) { + for _, item := range items { + delete(set.items, item) + } +} + +// Check wether items (one or more) are present in the set. +// All items have to be present in the set for the method to return true. +// Returns true if no arguments are passed at all, i.e. set is always superset of empty set. +func (set *Set) Contains(items ...interface{}) bool { + for _, item := range items { + if _, contains := set.items[item]; !contains { + return false + } + } + return true +} + +// Returns true if set does not contain any elements. +func (set *Set) Empty() bool { + return set.Size() == 0 +} + +// Returns number of elements within the set. +func (set *Set) Size() int { + return len(set.items) +} + +// Clears all values in the set. +func (set *Set) Clear() { + set.items = make(map[interface{}]struct{}) +} + +// Returns all items in the set. +func (set *Set) Values() []interface{} { + values := make([]interface{}, set.Size()) + count := 0 + for item, _ := range set.items { + values[count] = item + count += 1 + } + return values +} + +func (set *Set) String() string { + str := "HashSet\n" + items := []string{} + for k, _ := range set.items { + items = append(items, fmt.Sprintf("%v", k)) + } + str += strings.Join(items, ", ") + return str +} diff --git a/sets/hashset/hashset_test.go b/sets/hashset/hashset_test.go new file mode 100644 index 0000000..93cb940 --- /dev/null +++ b/sets/hashset/hashset_test.go @@ -0,0 +1,83 @@ +/* +Copyright (c) Emir Pasic, All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. See the file LICENSE included +with this distribution for more information. +*/ + +package hashset + +import ( + "fmt" + "testing" +) + +func TestHashSet(t *testing.T) { + + set := New() + + // insertions + set.Add() + set.Add(1) + set.Add(2) + set.Add(2, 3) + set.Add() + + if actualValue := set.Empty(); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + if actualValue := set.Size(); actualValue != 3 { + t.Errorf("Got %v expected %v", actualValue, 3) + } + + // Asking if a set is superset of nothing, thus it's true + if actualValue := set.Contains(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + if actualValue := set.Contains(1); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + if actualValue := set.Contains(1, 2, 3); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + if actualValue := set.Contains(1, 2, 3, 4); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + set.Remove() + set.Remove(1) + + if actualValue, expactedValues := fmt.Sprintf("%d%d", set.Values()...), [2]string{"23", "32"}; actualValue != expactedValues[0] && actualValue != expactedValues[1] { + t.Errorf("Got %v expected %v", actualValue, expactedValues) + } + + if actualValue := set.Contains(1); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + set.Remove(1, 2, 3) + + if actualValue := set.Contains(3); actualValue != false { + t.Errorf("Got %v expected %v", actualValue, false) + } + + if actualValue := set.Empty(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + +} diff --git a/stacks/linkedliststack/linkedliststack.go b/stacks/linkedliststack/linkedliststack.go index 41650fa..528843a 100644 --- a/stacks/linkedliststack/linkedliststack.go +++ b/stacks/linkedliststack/linkedliststack.go @@ -80,7 +80,7 @@ func (stack *Stack) Size() int { } func (stack *Stack) String() string { - str := "RedBlackTree\n" + str := "LinkedListStack\n" element := stack.top elementsValues := []string{} for element != nil {