bag, queue
This commit is contained in:
		
							parent
							
								
									6f9dc7b91b
								
							
						
					
					
						commit
						a35bb36872
					
				
					 4 changed files with 181 additions and 0 deletions
				
			
		
							
								
								
									
										51
									
								
								fundamentals/bag/bag.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								fundamentals/bag/bag.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | ||||||
|  | package bag | ||||||
|  | 
 | ||||||
|  | // "Generic" item. | ||||||
|  | // When type parameters will land this type became | ||||||
|  | // type Item[T any] T | ||||||
|  | type Item interface{} | ||||||
|  | 
 | ||||||
|  | type Bag interface { | ||||||
|  | 	Add(Item) | ||||||
|  | 	Size() int | ||||||
|  | 	IsEmpty() bool | ||||||
|  | 	ForEach(func(Item)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // We use linked list as internal data structure | ||||||
|  | // to get O(1) speed for Add operation | ||||||
|  | type node struct { | ||||||
|  | 	item Item | ||||||
|  | 	next *node | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type bag struct { | ||||||
|  | 	size int | ||||||
|  | 	head *node | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewBag() Bag { | ||||||
|  | 	return &bag{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (b *bag) Add(item Item) { | ||||||
|  | 	next := b.head | ||||||
|  | 	b.head = &node{item, next} | ||||||
|  | 	b.size++ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (b *bag) Size() int { | ||||||
|  | 	return b.size | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (b *bag) IsEmpty() bool { | ||||||
|  | 	return b.size == 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // As for now Go doesn't have iterators. | ||||||
|  | // But we can simulate them with ForEach method | ||||||
|  | func (b *bag) ForEach(f func(Item)) { | ||||||
|  | 	for current := b.head; current != nil; current = current.next { | ||||||
|  | 		f(current.item) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								fundamentals/bag/bag_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								fundamentals/bag/bag_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | package bag | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestSimple(t *testing.T) { | ||||||
|  | 	bag := NewBag() | ||||||
|  | 	sum := 0 | ||||||
|  | 
 | ||||||
|  | 	bag.Add(1) | ||||||
|  | 	bag.Add(2) | ||||||
|  | 	bag.Add(3) | ||||||
|  | 
 | ||||||
|  | 	bag.ForEach(func(i Item) { sum += i.(int) }) | ||||||
|  | 
 | ||||||
|  | 	if sum != 6 { | ||||||
|  | 		log.Fatal("wrong items in bag") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestEmpty(t *testing.T) { | ||||||
|  | 	bag := NewBag() | ||||||
|  | 	sum := 0 | ||||||
|  | 
 | ||||||
|  | 	if bag.Size() != 0 || !bag.IsEmpty() { | ||||||
|  | 		log.Fatal("bag should be empty") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bag.ForEach(func(i Item) { sum += i.(int) }) | ||||||
|  | 
 | ||||||
|  | 	if sum != 0 { | ||||||
|  | 		log.Fatal("wrong items in bag") | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								fundamentals/queue/queue.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								fundamentals/queue/queue.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | ||||||
|  | package queue | ||||||
|  | 
 | ||||||
|  | // "Generic" item. | ||||||
|  | // When type parameters will land this type became | ||||||
|  | // type Item[T any] T | ||||||
|  | type Item interface{} | ||||||
|  | 
 | ||||||
|  | type Queue interface { | ||||||
|  | 	Enqueue(Item) | ||||||
|  | 	Dequeue() Item | ||||||
|  | 	Size() int | ||||||
|  | 	IsEmpty() bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // We use linked list as internal data structure | ||||||
|  | // to get O(1) speed for push and pop opeartions | ||||||
|  | type node struct { | ||||||
|  | 	item Item | ||||||
|  | 	next *node | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type queue struct { | ||||||
|  | 	size int | ||||||
|  | 	head *node | ||||||
|  | 	tail *node | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewQueue() Queue { | ||||||
|  | 	return &queue{} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (q *queue) Enqueue(item Item) { | ||||||
|  | 	oldTail := q.tail | ||||||
|  | 	q.tail = &node{item: item, next: nil} | ||||||
|  | 	if q.IsEmpty() { | ||||||
|  | 		q.head = q.tail | ||||||
|  | 	} else { | ||||||
|  | 		oldTail.next = q.tail | ||||||
|  | 	} | ||||||
|  | 	q.size++ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (q *queue) Dequeue() Item { | ||||||
|  | 	first := q.head | ||||||
|  | 	q.head = q.head.next | ||||||
|  | 	if q.IsEmpty() { | ||||||
|  | 		q.tail = nil | ||||||
|  | 	} | ||||||
|  | 	q.size-- | ||||||
|  | 	return first.item | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (q *queue) Size() int { | ||||||
|  | 	return q.size | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (q *queue) IsEmpty() bool { | ||||||
|  | 	return q.head == nil | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								fundamentals/queue/queue_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								fundamentals/queue/queue_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | package queue | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestSimple(t *testing.T) { | ||||||
|  | 	queue := NewQueue() | ||||||
|  | 
 | ||||||
|  | 	queue.Enqueue(10) | ||||||
|  | 	queue.Enqueue(20) | ||||||
|  | 	queue.Enqueue(30) | ||||||
|  | 
 | ||||||
|  | 	first, second := queue.Dequeue().(int), queue.Dequeue().(int) | ||||||
|  | 
 | ||||||
|  | 	if first != 10 && second != 20 { | ||||||
|  | 		log.Fatal("wrong order") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestSize(t *testing.T) { | ||||||
|  | 	queue := NewQueue() | ||||||
|  | 
 | ||||||
|  | 	if queue.Size() != 0 { | ||||||
|  | 		log.Fatal("empty queue should have size 0") | ||||||
|  | 	} | ||||||
|  | 	queue.Enqueue(10) | ||||||
|  | 	queue.Enqueue(20) | ||||||
|  | 	queue.Enqueue(30) | ||||||
|  | 
 | ||||||
|  | 	if queue.Size() != 3 { | ||||||
|  | 		log.Fatal("wrong size") | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue