Merging Intervals out of hyphenated string ranges - go

I have a string like this:
ports := []string{"1", "2-7", "12-1200", "10-500"}
I would like to make an integer set out of this like the output should be :
[]intSet{ 1, 2-7, 10-1200 }
Where intSet is some kind of integer set from which I am able to easily remove and add elements.
Update 1
intSet is a list of sets.
So, 2-7 is also a set.
Update 2
Here the largest set is merged.
e.g.
"1" -> 1
"2-7" -> 2-7
"12-1200" & "10-500" => "10..12.....500....1200" -> 10-1200
Since it's a set so it encompasses a unique range for this, a range which covers the whole set.

package main
import (
"fmt"
"log"
"strconv"
"strings"
)
type intSet struct {
start int
end int
}
func (s intSet) String() string {
if s.start == s.end {
return fmt.Sprintf("%d", s.start)
}
return fmt.Sprintf("%d-%d", s.start, s.end)
}
func (s intSet) in(i int) bool {
return s.start <= i && i <= s.end
}
func (s *intSet) union(set intSet) {
if set.start < s.start {
s.start = set.start
}
if set.end > s.end {
s.end = set.end
}
}
func insert(set intSet, is []intSet) bool {
for i, s := range is {
if s.in(set.start) || s.in(set.end) {
is[i].union(set)
return true
}
//updated here with thankful to #mh-cbon
if set.in(s.start) || set.in(s.end) {
is[i].union(set)
return true
}
}
return false
}
func main() {
var set []intSet
ports := []string{"1", "2-7", "12-1200", "10-500", "9-5500"}
for _, port := range ports {
s := strings.Split(port, `-`)
if len(s) < 1 || len(s) > 2 {
log.Fatalln(`set cannot have multiple values or no value`)
}
start, err := strconv.Atoi(s[0])
if err != nil {
log.Fatalln(err)
}
end := start
if len(s) == 2 {
end, err = strconv.Atoi(s[1])
if err != nil {
log.Fatalln(err)
}
}
temSet := intSet{
start: start,
end: end,
}
if !insert(temSet, set) {
set = append(set, temSet)
}
}
fmt.Println(set) //[1 2-7 9-5500]
}
run here

Related

How to check if an element exists in linked list

I am trying to find if an element exists in my linked list so that duplicate elements are not added.
My code follows playground:
package main
import "fmt"
func (e Ensemble) EstVide() bool {
return e.ensemble == nil
}
func (e Ensemble) Card() int {
return e.longueur
}
type Cellule struct {
elem int
suivant *Cellule
}
type Ensemble struct {
ensemble *Cellule
longueur int
}
func (c Cellule) String() string {
if c.suivant == nil {
return fmt.Sprintf("%v}", c.elem)
}
return fmt.Sprintf("%v", c.elem)
}
func (e Ensemble) String() string {
if e.EstVide() {
return ""
}
res := "{"
for curr := e.ensemble; curr != nil; curr = curr.suivant {
res += fmt.Sprintf("%s ", curr)
}
return res[:len(res)-1]
}
func (e Ensemble) Appartient(valeur int) bool {
body := e.String()
for i := 0; i < e.Card(); i++ {
if valeur == int(body[i]) {
return true
}
}
return false
}
func (e *Ensemble) Ajouter(valeur int) {
if !e.Appartient(valeur) {
e.ensemble = &Cellule{elem: valeur, suivant: e.ensemble}
e.longueur++
}
}
func main() {
monEns := Ensemble{}
fmt.Printf("Nb d'éléments dans monEns %v\n", monEns.Card())
fmt.Printf("monEns = %v\n", monEns)
monEns.Ajouter(42)
monEns.Ajouter(10)
monEns.Ajouter(20)
monEns.Ajouter(10)
fmt.Printf("Nb d'éléments dans monEns %v\n", monEns.Card())
fmt.Printf("monEns = %v \n", monEns)
}
The output ({10 20 10 42} includes a duplicate element (10). How can I prevent this?

How to find a binary tree depth using breadth-first algorithm in Golang

I have a binary tree and I would like to find its maximum depth using a breadth-first approach.
I think I am having a logical error in where to increment the depth.
// You can edit this code!
// Click here and start typing.
package main
import (
"log"
"math"
)
type Queue []*Node
func (q *Queue) Enqueue(n *Node) {
*q = append(*q, n)
}
func (q *Queue) Dequeue() *Node {
node := (*q)[0]
*q = (*q)[1:]
return node
}
func (q *Queue) IsEmpty() bool {
return len(*q) == 0
}
type Node struct {
value *int
left *Node
right *Node
}
func (node *Node) insert(value int) {
if node.value == nil {
node.value = &value
return
}
if *node.value <= value {
if node.left == nil {
node.left = &Node{}
}
node.left.insert(value)
return
}
if node.right == nil {
node.right = &Node{}
}
node.right.insert(value)
}
// HELP NEEDED here
func (node *Node) NumberOfVisibleNodes() int {
var counter int
if node == nil || node.value == nil {
return counter
}
hashtable := map[int]int{}
levelDepth := 0
nodeQueue := Queue{node}
for !nodeQueue.IsEmpty() {
currentNode := nodeQueue.Dequeue()
_, found := hashtable[levelDepth]
if !found {
hashtable[levelDepth] = *currentNode.value
}
if currentNode.left != nil {
nodeQueue.Enqueue(currentNode.left)
hashtable[levelDepth+1] = *currentNode.left.value
}
if currentNode.right != nil {
nodeQueue.Enqueue(currentNode.right)
hashtable[levelDepth+1] = *currentNode.right.value
}
levelDepth++
}
return len(hashtable)
}
func (node *Node) NumberOfVisibleNodesRecursively() int {
if node == nil || node.value == nil {
return 0
}
leftMaxDepth := node.left.NumberOfVisibleNodesRecursively()
rightMaxDepth := node.right.NumberOfVisibleNodesRecursively()
maxDepth := math.Max(float64(leftMaxDepth), float64(rightMaxDepth))
return 1 + int(maxDepth)
}
func main() {
testCases := []struct {
expect string
arguments []int
expected int
}{
{
"expect to return 0 when nodes are empty",
[]int{},
0,
},
{
"expect to get 2",
[]int{3, 5},
2,
},
{
"expect to get 3",
[]int{3, 5, 2, 6, 4, 1},
3,
},
{
"expect to return 4",
[]int{3, 5, 2, 6, 4, 1, -10},
4,
},
}
for _, testCase := range testCases {
var tree Node
for _, value := range testCase.arguments {
tree.insert(value)
}
gotResult := tree.NumberOfVisibleNodes()
if gotResult != testCase.expected {
log.Fatalf("%s but got: %d wanted: %d ", testCase.expect, gotResult, testCase.expected)
}
}
}
I wonder if it's even possible. I know the best approach is to use a depth-first approach but I am curious to learn if the breadth approach is possible!
Running code is here: https://go.dev/play/p/exiI-QqRWIM
[UPDATE]
One approach that seems to work is using a tuple.
type TupleQueue []Tuple
func (tq *TupleQueue) Enqueue(t Tuple) {
*tq = append(*tq, t)
}
func (tq *TupleQueue) Dequeue() Tuple {
tuple := (*tq)[0]
*tq = (*tq)[1:]
return tuple
}
func (tq *TupleQueue) IsEmpty() bool {
return len(*tq) == 0
}
func (node *Node) NumberOfVisibleNodes() int {
if node == nil || node.value == nil {
return 0
}
var depth int
tupleQueue := TupleQueue{{depth, node}}
for !tupleQueue.IsEmpty() {
tuple := tupleQueue.Dequeue()
if tuple.level != depth {
depth++
}
if tuple.node.left != nil {
tupleQueue.Enqueue(Tuple{depth + 1, tuple.node.left})
}
if tuple.node.right != nil {
tupleQueue.Enqueue(Tuple{depth + 1, tuple.node.right})
}
}
return depth + 1
}
I wonder if we can do something similar with hashmaps
You don't need tuple or hashmap to do BFS. Just use queue, I show the code below.
func (node *Node) NumberOfVisibleNodes() int {
if node == nil || node.value == nil {
return 0
}
levelDepth := 0
nodeQueue := Queue{node}
for !nodeQueue.IsEmpty() {
tmpQueue := Queue{}
for !nodeQueue.IsEmpty(){
cNode := nodeQueue.Dequeue()
if cNode.right!= nil{
tmpQueue.Enqueue(cNode.right)
}
if cNode.left!= nil{
tmpQueue.Enqueue(cNode.left)
}
}
nodeQueue = tmpQueue
levelDepth++
}
return levelDepth
}

How to convert a slice of int to a slice of string

Well, I created a slice of int like this:
list_of_id := []string {1,2,3,4}
My code would do a check if a variable in my slice (list_of_id):
func contains(s [] int, input int) bool {
for _, v := range s {
if v == input {
return true
}
}
return false
}
func main() {
list_of_id := [] int {1,2,3,4}
fmt.Println(contains(list_of_id, 1))
}
I want to create a function with the flexibility that I could input 1 or "1" as well.
My intention is to create an if else condition in which the slice of int [] int {1,2,3,4} will be converted into a slice of string [] string {"1","2","3","4"} to check again.
Anddddd, I don't know how to do so. I tried to google it out but all I found is a solution to convert this [] int {1,2,3,4} to this "{1,2,3,4}"
import "strconv"
func contains(s [] int, input interface{}) bool {
switch i := input.(type) {
case int:
for _, v := range s {
if v == i {
return true
}
}
case string:
for _, v := range s {
if strconv.Itoa(v) == i {
return true
}
}
}
return false
}
https://play.golang.org/p/02J1f77n_aM
package main
import (
"fmt"
"strconv"
)
func contains(s []int, input interface{}) bool {
var c int
var err error
switch input.(type) {
case int:
c = input.(int)
case string:
tmp := input.(string)
c, err = strconv.Atoi(tmp)
}
if err != nil {
return false
}
for _, v := range s {
if v == c {
return true
}
}
return false
}
func main() {
list_of_id := []int{1, 2, 3, 4}
fmt.Println(contains(list_of_id, 3))
fmt.Println(contains(list_of_id, 5))
fmt.Println(contains(list_of_id, "1"))
fmt.Println(contains(list_of_id, "6"))
}
Here example

Removing an item in a Linked List with Go

I want to remove a Node from a linked list in Go, and I have this struct and these methods:
type Node struct {
Next *Node
Val int
}
func (n *Node) Append(val int) {
end := &Node{Val: val}
here := n
for here.Next != nil {
here = here.Next
}
here.Next = end
}
func Remove(n *Node, val int) *Node {
head := n
for head.Next != nil {
if head.Next.Val == val {
head.Next = head.Next.Next
return head
}
head = head.Next
}
return head
}
func NewNode(val int) *Node {
return &Node{Val: val}
}
I want to remove an item like this:
n := NewNode(1)
n.Append(2)
n.Append(3)
n.Append(4)
n.Append(5)
m := Remove(n, 3)
for m != nil {
fmt.Println(n.Val)
m = m.Next
}
The items that get printed out are 3 and 5, not 1,2,4and5`. I re-implemented this code in Python and got the expected answer. What is going on in Go? I have a feeling it has to do something with pointers.
You lose the head from returning a node you use to traverse. Also you are printing out the wrong object
type Node struct {
Next *Node
Val int
}
func (n *Node) Append(val int) {
end := &Node{Val: val}
here := n
for here.Next != nil {
here = here.Next
}
here.Next = end
}
func Remove(n *Node, val int) *Node {
traverser := n
for traverser.Next != nil {
if traverser.Next.Val == val {
traverser.Next = traverser.Next.Next
return n
}
traverser = traverser.Next
}
return n
}
func NewNode(val int) *Node {
return &Node{Val: val}
}
func main() {
n := NewNode(1)
n.Append(2)
n.Append(3)
n.Append(4)
n.Append(5)
m := Remove(n, 3)
for m != nil {
fmt.Println(m.Val)
m = m.Next
}
}

Golang container/list creating a FindAll function

I was wondering if this is the way to create and pass 'generic'(yeah I know, a sensitive word in GoLang) lists to a FindAll function.
Here's my attempt:
package main
import (
"container/list"
"fmt"
"strings"
)
func FindAll(lst *list.List, p func(interface{}) bool) *list.List {
ans := list.New()
for i := lst.Front(); i != nil; i = i.Next() {
if p(i.Value) {
ans.PushBack(i.Value)
}
}
return ans
}
func ConvertToInt(p func(int) bool) func(interface{}) bool {
return func(v interface{}) bool {
if value, ok := v.(int); ok {
if p(value) {
return true
} else {
return false
}
} else {
return false
}
}
}
func IsEven(n int) bool {
if n%2 == 0 {
return true
}
return false
}
func ConvertoString(p func(s string) bool) func(interface{}) bool {
return func(v interface{}) bool {
if value, ok := v.(string); ok {
if p(value) {
return true
} else {
return false
}
} else {
return false
}
}
}
func IsHello(str string) bool {
if strings.ToLower(str) == "hello" {
return true
} else {
return false
}
}
func main() {
fmt.Println("Find All Programs!\n\n")
lsti := list.New()
for i := 0; i < 11; i++ {
lsti.PushBack(i)
}
ansIsEven := FindAll(lsti, ConvertToInt(IsEven))
for i := ansIsEven.Front(); i != nil; i = i.Next() {
if value, ok := i.Value.(int); ok {
fmt.Printf("Found even: %d\n", value)
} else {
fmt.Println("Huh! What's that?")
}
}
}
I've been playing with this for a while and thought I'd better get the advice of the Go experts before I convince myself its correct.
The code as-is is pretty fine, but you should ask your self 2 questions:
1. Why shouldn't you use a typed slice? (interface{} performance is slow compared to the explicit type, although it will greatly improve in Go 1.7)
2. Would it be better to implement your specific type as a linked list?
Something like this can be much more efficient:
type IntList []int
func (l IntList) Filter(fn func(v int) bool) IntList {
var o IntList
for _, v := range l {
if fn(v) {
o = append(o, v)
}
}
return o
}
There's almost always a better alternative to container/list, however it all depends on your use case.

Resources