Peeking into the top of the Priority Queue in Go? - go

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

Related

how to get length of linked list in golang with recursive of method pointer?

I have a single linked list. how do I get the length of the linked list with a recursive method that had a pointer receiver?
type Node struct {
data int
next *Node
}
I had tried like this, but always return 1
func (n *Node) recursiveLength() (result int) {
if n != nil {
result += 1
n = n.next
}
return
}
Your solution is not recursive. It's have compilation error. But if we want to fix it it could be like this:
package main
import "fmt"
type Node struct {
data int
next *Node
}
func (n *Node) recursiveLength() (result int) {
if n != nil {
result += 1
n = n.next
return result + n.recursiveLength()
}
return 0
}
func main() {
x := Node{data: 0, next: &Node{data: 1, next: &Node{data: 2, next: nil}}}
fmt.Println(x.recursiveLength())
}
But this is not a good idea to write length method, It's better to change it to a function that accepts a Node and returns its length:
package main
import "fmt"
type Node struct {
data int
next *Node
}
func recursiveLength(n *Node) (result int) {
if n != nil {
n = n.next
return 1 + recursiveLength(n)
}
return 0
}
func main() {
x := Node{data: 0, next: &Node{data: 1, next: &Node{data: 2, next: nil}}}
fmt.Println(recursiveLength(&x))
}

implement generics in go using interfaces?

I am trying to write a stack in Go which works for int and rune array type. But this does not seem to work. I thought that was supposed to work as I have an Interface type to hold any type. The operation of the stack is common for all types. I don't want to use the stack interface that comes with go
package main
import "math"
type expressionStack interface {
pop() interface
getSize() int
push(item interface)
peek() interface
}
type intStack []int
type runeStack []rune
func createStack(st interface) {
return &expressionStack{}
}
func (stack *expressionStack) getSize() int {
return len(stack)
}
func (stack *expressionStack) pop() int {
length := len(stack)
if length == 0 {
panic("Stack is underflown")
}
item := stack[length-1]
stack = stack[:length-1]
return item
}
func (stack *expressionStack) push(item interface) {
stack = append(stack, item)
}
func (stack *expressionStack) peek() int {
leng := len(stack)
if leng == 0 {
return -math.MaxInt32
}
item := stack[leng-1]
return item
}
a solution to those problem is to use code gen.
It requires to arrange a bit the api because generator are pretty dumb, but it does the job.
I start by declaring a package under GOPATH (old school) at test/d/gen
I create a new file template.go, and arranged a bit the code
package gen
type T int
type expressionStack []T
func (stack *expressionStack) getSize() int {
return len(*stack)
}
func (stack *expressionStack) pop() T {
length := len(*stack)
if length == 0 {
panic("Stack is underflown")
}
item := (*stack)[length-1]
*stack = (*stack)[:length-1]
return item
}
func (stack *expressionStack) push(item T) {
*stack = append(*stack, item)
}
func (stack *expressionStack) peek() (zero T, ok bool) {
leng := len(*stack)
if leng == 0 {
return
}
item := (*stack)[leng-1]
return item, true
}
I have tried to use https://github.com/mmatczuk/go_generics witth something like go_generics -t=T=int32 -t=expressionStack=IntStack -i=./template.go -o out.go -p gen, but it failed.
tried another one https://github.com/clementauger/jenjen with jenjen -template=test/d/gen "expressionStack:T => int32, T => -, expressionStack=>Int32Stack" -
I got a neat output
package gen
type Int32Stack []int32
func (stack *Int32Stack) getSize() int {
return len(*stack)
}
func (stack *Int32Stack) pop() int32 {
length := len(*stack)
if length == 0 {
panic("Stack is underflown")
}
item := (*stack)[length-1]
*stack = (*stack)[:length-1]
return item
}
func (stack *Int32Stack) push(item int32) {
*stack = append(*stack, item)
}
func (stack *Int32Stack) peek() (zero int32, ok bool) {
leng := len(*stack)
if leng == 0 {
return
}
item := (*stack)[leng-1]
return item, true
}
the hard stuff was to figure out that "expressionStack:T => int32, T => -, expressionStack=>Int32Stack", its a three statements instructions,
expressionStack: T=>int32 within expressionStack replace T by int32
T => -, within the package, remove T
expressionStack=>Int32Stack, within the package, rename expressionStack to Int32Stack
Though, i had some problem saving the output to the desired file with that last package. not perfect.
there is also a bunch of others package to do that,
https://github.com/cheekybits/genny
https://pkg.go.dev/cmd/gofmt with -r option
I think i found a solution
package main
import (
"math"
"reflect"
)
type expressionStack []interface{}
func (stack *expressionStack) getSize() int {
return len(*stack)
}
func (stack *expressionStack) pop() interface{} {
length := len(*stack)
if length == 0 {
panic("Stack is underflown")
}
item := (*stack)[length-1]
*stack = (*stack)[:length-1]
return item
}
func (stack *expressionStack) push(item interface{}) {
*stack = append(*stack, item)
}
func (stack *expressionStack) peek() interface{} {
leng := len(*stack)
if reflect.TypeOf(stack).Kind() == reflect.Int32 {
if leng == 0 {
return -math.MaxInt32
}
} else {
if leng == 0 {
return 'E'
}
}
item := (*stack)[leng-1]
return item
}

Wrapper around slice is doing weird things

I am probably wasting my time implementing this, but I am looking for a way to push/pop to a slice more easily, so I have this:
package h
import (
"sync"
log "github.com/sirupsen/logrus"
)
type List struct {
internalList []interface{}
mux sync.Mutex
}
func MakeList(l []interface{}) List{
return List{l, sync.Mutex{}}
}
func (l List) Add(args ...interface{}) List{
l.mux.Lock()
l.internalList = append(l.internalList, args...)
log.Info(l.internalList)
l.mux.Unlock()
return l;
}
func (l List) Push(v interface{}) List {
l.mux.Lock()
l.internalList = append(l.internalList, v)
log.Info("internal:",l.internalList);
l.mux.Unlock()
return l;
}
func (l List) Pop() interface{}{
l.mux.Lock()
length :=len(l.internalList);
log.Info("the length is:", length)
if length < 1 {
return nil;
}
last := l.internalList[length-1]
l.internalList = l.internalList[:length-1]
l.mux.Unlock()
return last;
}
func (l List) GetLength() int {
return len(l.internalList);
}
func (l List) Shift() interface{} {
l.mux.Lock()
if len(l.internalList) < 1 {
return nil;
}
first := l.internalList[0];
l.internalList = l.internalList[1:]
l.mux.Unlock()
return first;
}
func (l List) Unshift(v interface{}){
l.mux.Lock()
l.internalList = append([]interface{}{v}, l.internalList...)
l.mux.Unlock()
}
func (l List) GetValue() []interface{}{
return l.internalList
}
and then I use it like so:
package main
import (
"github.com/sirupsen/logrus"
"huru/h"
"huru/utils"
)
func main(){
x := h.List{}
x.Push(3)
logrus.Info("value:",x.GetValue())
logrus.Info("len:",x.GetLength());
logrus.Info(x.Pop());
}
but the weird thing is I get this:
INFO[0000] internal:[3]
INFO[0000] value:[]
INFO[0000] len:0
INFO[0000] the length is:0
INFO[0000] <nil>
I have no idea why 3 gets added to the slice, but then the slice length mysteriously goes to zero and when I pop() I get nil. Anybody know why that's happening?
Given the existing answer, I am wondering if there is a difference between:
func (l *List) Add(args ...interface{}) *List {
l.mux.Lock()
l.internalList = append(l.internalList, args...)
log.Info(l.internalList)
l.mux.Unlock()
return l;
}
func (l *List) Push(v interface{}) *List {
l.mux.Lock()
l.internalList = append(l.internalList, v)
log.Info("internal:",l.internalList)
l.mux.Unlock()
return l
}
and
func (l *List) Add(args ...interface{}) List {
l.mux.Lock()
l.internalList = append(l.internalList, args...)
log.Info(l.internalList)
l.mux.Unlock()
return *l;
}
func (l *List) Push(v interface{}) List {
l.mux.Lock()
l.internalList = append(l.internalList, v)
log.Info("internal:",l.internalList)
l.mux.Unlock()
return *l
}
Since your methods are mutating the data, they need to use pointer receivers:
func (l *List) Push(v interface{}) List {
...
}
Otherwise, the state will be updated on the copy of the struct, and lost after that.
More on that in Effective Go
Update: I noticed that you return the updated value from your methods. If the copy is what you actually want, you need to keep the value receivers as they are now, but then use the returned values in your calling code as well:
x = x.Push(3)

How to embed and override a struct in Go

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}}

Priority queue and heap

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
}

Resources