I'm trying to implement a priority queue based on the example provided in the documentation.
Docs: priorityQueue
In short it looks like this (not everything is included):
package pq
type Item struct {
container interface{}
priority int
index int
}
type PriorityQueue []*Item
func NewItem(value interface{}, prio int) *Item {
return &Item {container: value, priority: prio}
}
func (pq PriorityQueue) Len() int {
return len(pq)
}
func (pq PriorityQueue) Less(i, j int) bool {
return pq[i].priority > pq[j].priority
}
func (pq *PriorityQueue) Swap(i, j int) {
(*pq)[i], (*pq)[j] = (*pq)[j], (*pq)[i]
(*pq)[i].index = i
(*pq)[j].index = j
}
func (pq PriorityQueue) Push(x interface{}) {
fmt.Printf("adr: %p\n", &pq)
n := len(pq)
item := x.(*Item)
item.index = n
pq = append(pq, item)
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
itm := old[n - 1]
itm.index = -1
*pq = old[0 : n-1]
return itm.container
}
The main.go file:
func main() {
q := pq.PriorityQueue{}
heap.Init(q)
fmt.Printf("\nAdr: %p\n", &q)
q.Push(pq.NewItem("h", 2))
for i := 0; i < 5; i++ {
item := pq.NewItem("test", i * 13 % 7)
heap.Push(q, item)
}
for q.Len() > 0 {
fmt.Println("Item: " + heap.Pop(q).(string))
}
}
As you can see when comparing to the example I do not use pointers since doing that will give me a compile error telling me that my priority queue does not implement the interface properly.
This leaves me with the following problem when I do:
heap.Push(q, item)
that the item is not appended to the queue.
I've tried to write out the queues pointer address and it shows different addresses. This explains why it does not work, but souldn't slices not be reference types a long with maps?
And more specificly: How do i solve my problem?
Hope you can help!
Edit: Added full code and error: cannot use q (type pq.PriorityQueue) as type heap.Interface in function argument:
pq.PriorityQueue does not implement heap.Interface (Pop method has pointer receiver)
As the example code shows, the Push method must have a pointer receiver.
The trick is that all the calls to heap.XXX functions, require that you pass your heap in as a pointer (e.g.: heap.Init(&pq)). This is not the case in the code you posted. Here is a working version of your code. You can run it on the Go playground.
Note that in this code, I explicitly initialize the queue as a pointer: q := new(PriorityQueue). And this is what I pass in to all the heap functions.
The confusion here arises mostly because you are essentially implementing 2 interfaces.
The heap.Interface and the sort.Interface (The latter is part of the prior's type definition). But the sort interface is fine with non-pointer receivers, while the other one is not.
package main
import "fmt"
import "container/heap"
func main() {
q := new(PriorityQueue)
heap.Init(q)
fmt.Printf("\nAdr: %p\n", &q)
q.Push(NewItem("h", 2))
for i := 0; i < 5; i++ {
heap.Push(q, NewItem("test", i*13%7))
}
for q.Len() > 0 {
fmt.Println("Item: " + heap.Pop(q).(string))
}
}
type Item struct {
container interface{}
priority int
index int
}
type PriorityQueue []*Item
func NewItem(value interface{}, prio int) *Item {
return &Item{container: value, priority: prio}
}
func (pq PriorityQueue) Len() int {
return len(pq)
}
func (pq PriorityQueue) Less(i, j int) bool {
return pq[i].priority > pq[j].priority
}
func (pq PriorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
pq[i].index = i
pq[j].index = j
}
func (pq *PriorityQueue) Push(x interface{}) {
fmt.Printf("adr: %p\n", pq)
n := len(*pq)
item := x.(*Item)
item.index = n
*pq = append(*pq, item)
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
itm := old[n-1]
itm.index = -1
*pq = old[0 : n-1]
return itm.container
}
Related
I'm trying to modify values of a map of maps.
Following code shows fatal error: concurrent map read and map write unless I lock whole Map (using defer in method Map.Add in line 17).
My question is, how can I implement it correctly to effectively make use of goroutines concurrency and do not turn my asynchronous code to some synchronous code?
package main
import (
"fmt"
"sync"
"time"
)
type Map struct {
mutex sync.Mutex
item map[int]*Item
}
func (m *Map) Add(key int) {
m.mutex.Lock()
m.item[key] = &Item{value: make(map[int]int)}
defer m.mutex.Unlock()
for j := 0; j < 100; j++ {
go m.item[key].Inc(j)
}
}
type Item struct {
mutex sync.Mutex
value map[int]int
}
func (m *Item) Inc(key int) {
m.mutex.Lock()
m.value[key]++
m.mutex.Unlock()
}
func (m *Item) Value(key int) int {
m.mutex.Lock()
defer m.mutex.Unlock()
return m.value[key]
}
func main() {
m := Map{item: make(map[int]*Item)}
for i := 0; i < 100; i++ {
go m.Add(i)
}
time.Sleep(time.Second)
fmt.Println(m.item[1])
}
I was trying to implement a sample program using heap, and I am able to Push and Pop from the Heap. I was able to implement the Push and Pop methods and use them as follows:
import "container/heap"
type Meeting struct {
start int
end int
}
func NewMeeting(times []int) *Meeting {
return &Meeting{start: times[0], end: times[1] }
}
type PQ []*Meeting
func (pq PQ) Len() int {
return len(pq)
}
func (pq PQ) Less(i, j int) bool {
return pq[i].end < pq[j].end
}
func (pq PQ) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
}
func (pq *PQ) Push(x interface{}) {
item := x.(*Meeting)
*pq = append(*pq, item)
}
func (pq *PQ) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
old[n-1] = nil // avoid memory leak
*pq = old[0 : n-1]
return item
}
func minMeetingRooms(intervals [][]int) int {
pq := make(PQ, 0)
heap.Init(&pq)
heap.Push(&pq, NewMeeting([]int{1, 3}))
heap.Push(&pq, NewMeeting([]int{1, 2}))
fmt.Println(heap.Pop(&pq).(*Meeting)) // I would like to log this without popping prom the Queue
return 0
}
Please see the comment in the code snippet in the minMeetingRooms function.
I would like to log the top of the Priority Queue, without actually popping it. How can I go that?
You can "peek" the element that pop() will return by returning the first element of the underlying array. (i.e. pq[0])
fmt.Println(pq[0])
you need to use the first element to peek
I am constructing the min/max heaps of ints to satisfy the interface from container/heap.
The min heap works well such as
type MinHeapInt []int
func (h MinHeapInt) Len() int {
return len(h)
}
func (h MinHeapInt) Less(i, j int) bool {
return h[i] < h[j]
}
func (h MinHeapInt) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
func (h *MinHeapInt) Peek() interface{} {
return (*h)[0]
}
func (h *MinHeapInt) Push(x interface{}) {
*h = append(*h, x.(int))
}
func (h *MinHeapInt) Pop() interface{} {
length := len(*h)
res := (*h)[length - 1]
*h = (*h)[0 : length - 1]
return res
}
Now I am trying to develop the max heap by only overriding the Less method.
The first solution does not work since it cannot find the array
type MaxHeapInt struct {
MinHeapInt
}
func (h MaxHeapInt) Less(i, j int) bool {
return h[i] > h[j]
}
The second solution only keeps the Less method.
type MaxHeapInt MinHeapInt
func (h MaxHeapInt) Less(i, j int) bool {
return h[i] > h[j]
}
Wonder if there is anyway to get around. Thanks!
Your first solution is trying to index the MaxHeapInt struct, not the MinHeapInt slice.
type MaxHeapInt struct {
MinHeapInt
}
func (h MaxHeapInt) Less(i, j int) bool {
return h.MinHeapInt[i] > h.MinHeapInt[j]
}
If you want them to be initialized the same, then create a partial heap implementation, and wrap in the desired struct (similar to the wrapper example in the sort package).
type Max struct{ IntHeap }
func (h Max) Less(i, j int) bool {
return h.IntHeap[i] > h.IntHeap[j]
}
type Min struct{ IntHeap }
func (h Min) Less(i, j int) bool {
return h.IntHeap[i] < h.IntHeap[j]
}
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Peek() interface{} { return (*h)[0] }
func (h *IntHeap) Push(x interface{}) {
*h = append(*h, x.(int))
}
func (h *IntHeap) Pop() interface{} {
length := len(*h)
res := (*h)[length-1]
*h = (*h)[0 : length-1]
return res
}
// Now these can be initialized like
// Min{IntHeap{1, 2, 3}}
// Max{IntHeap{1, 2, 3}}
er, I am trying to learn go by implementing a random graph. I get an error on n.value undefined (type int has no field or method value), and n.neigbours undefined (type int has no field or method neigbours). I can not understand that compilation error as i create a new slice of nodesnr size of empty nodes in the g.nodes = make([]node, g.nodesnr). What is the problem?
package main
import (
"fmt"
//"math/rand"
)
type node struct {
value int
neigbours []int
}
type edge struct {
source int
sink int
}
type graph struct {
nodesnr, edgesnr int
nodes []node
edges chan edge
}
func main() {
randomGraph()
}
func input(tname string) (number int) {
fmt.Println("input a number of " + tname)
fmt.Scan(&number)
return
}
func randomGraph() (g graph) {
g = graph{nodesnr: input("nodes"), edgesnr: input("edges")}
g.addNodes()
for i := 0; i < g.nodesnr; i++ {
fmt.Println(g.nodes[i].value)
}
//g.addEdges()
return
}
func (g *graph) addNodes() {
g.nodes = make([]node, g.nodesnr)
for n := range g.nodes {
n.value = 2
n.neigbours = nil
return
}
}
func (g *graph) addEdges() {
g.edges = make(chan edge)
for i := 0; i < g.edgesnr; i++ {
//g.newEdge()
return
}
}
/*
func (g* graph) newEdge(){
e := new(edge)
e.source, e.sink = rand.Intn(g.nodesnr), rand.Intn(g.nodesnr)
g.edges <-e*
//g.addEdge()
}
*/
func (g *graph) edgeCheck(ep *edge) string {
if ep.source == ep.sink {
return "self"
}
//if(g.neigbourCheck(g.nodes[ep.source].neigbours, ep.sink) OR g.neigbourCheck(g.nodes[ep.sink].neigbours, ep.source){
// return "present"
return "empty"
}
func (g *graph) neigbourCheck(neigbours []node, node int) bool {
for neigbour := range neigbours {
if node == neigbour {
return true
}
}
return false
}
func (g *graph) addEdge() {
e := <-g.edges
switch etype := g.edgeCheck(&e); etype {
case "present":
fallthrough
case "self":
fmt.Println("self")
//go g.newEdge()
case "empty":
//g.nodes[e.source] = append(g.nodes[e.source], e.sink),
//g.nodes[e.sink] = append(g.nodes[e.sink], e.source)
fmt.Println("empty")
default:
fmt.Println("something went wrong")
}
}
Playground
Your error lies on line 47
for n := range g.nodes
When iterating over a slice, when using only one value, that value (n) will be set to the index, which is of type int. What you need to do is to change the line to:
for _, n := range g.nodes
This means that you discard the index but put the value in n instead.
Edit
n will be a copy of the value which means any changes made to n will not affect the node in the slice. To edit the node in the slice, you should actually get the index instead of the value:
for i := range g.nodes {
g.nodes[i].value = 2
g.nodes[i].neigbours = nil
return
}
I've been trying some things out in Go and I've hit a problem that I can't figure out.
package main
import "fmt"
import "strconv"
func writeHello(i int, ) {
fmt.Printf("hello, world "+strconv.Itoa(i)+"\n")
}
type SliceStruct struct {
data [][]int;
}
func (s SliceStruct) New() {
s.data=make([][]int,10);
}
func (s SliceStruct) AllocateSlice(i int) {
s.data[i]=make([]int,10);
}
func (s SliceStruct) setData(i int, j int, data int) {
s.data[i][j] = data;
}
func (s SliceStruct) getData(i int, j int) int {
return s.data[i][j]
}
func useSliceStruct(){
sliceStruct := SliceStruct{};
sliceStruct.New();
for i := 0; i < 10; i++ {
sliceStruct.AllocateSlice(i);
for j:=0; j<10; j++ {
sliceStruct.setData(i,j,i);
writeHello(sliceStruct.getData(i,j));
}
}
}
func dontUseSliceStruct(){
data:=make([][]int,10);
for i := 0; i < 10; i++ {
data[i]=make([]int,10);
for j:=0; j<10; j++ {
data[i][j] = i;
writeHello(data[i][j]);
}
}
}
func main() {
dontUseSliceStruct();
useSliceStruct();
}
When it gets to the function useSliceStruct, the code fails at the first call to AllocateSlice() with an index out of range error.
As far as I can tell the code for the two methods does idential things. So what am I missing?
DOH, just worked it out.
I wasn't using a reference to the struct in the function declarations.
func (s SliceStruct)
Should have been
func (s *SliceStruct)