So I have following structs, and I want to iterate through FiniteSet to get all ranges between the actual keys from the range. By that I mean get ranges excluding the keys. The reason for float64 is because I want to handle Math.inf() too. I am not sure if this is the best approach though.
type (
FiniteSet struct {
set map[float64]nothing
}
nothing struct{}
Range struct {
lowerBoundary float64
upperBoundary float64
}
)
e.g
map[float64]nothing {
math.Inf(-1): nothing{},
1: nothing{},
2: nothing{},
5: nothing{},
math.Inf(): nothing{}
}
I want the output to be yield
[]Range {
Range{math.inf(-1), 0},
Range{3,4},
Range{6, math.Inf()}
}
}
I would include my attempt on the implementation, if it weren't such a mess. I doubt it will provide anything but confusion to the question.
package main
import (
"fmt"
"math"
"sort"
)
type (
FiniteSet struct {
set map[float64]nothing
}
nothing struct{}
Range struct {
lowerBoundary float64
upperBoundary float64
}
)
func main() {
data := map[float64]nothing{
math.Inf(-1): nothing{},
1: nothing{},
2: nothing{},
5: nothing{},
math.Inf(1): nothing{},
}
r := process(data)
fmt.Printf("%v\n", r)
}
func process(data map[float64]nothing) []Range {
keys := make([]float64, 0)
for k := range data {
keys = append(keys, k)
}
sort.Float64s(keys)
r := make([]Range, 0)
for i := 0; i < len(keys)-1; i++ {
if 1 == keys[i+1]-keys[i] {
continue
}
var current Range
if keys[i] == math.Inf(-1) {
current.lowerBoundary = keys[i]
} else {
current.lowerBoundary = keys[i] + 1
}
if keys[i+1] == math.Inf(1) {
current.upperBoundary = keys[i+1]
} else {
current.upperBoundary = keys[i+1] - 1
}
r = append(r, current)
}
return r
}
Related
I'm trying to build simple function to count elements in slice (like len) It must be simple (without additional libs) and with recursion. The problem is when i try to check is slice is empty (is nul).
package main
import "fmt"
func main() {
x := []int{1, 2, 3}
fmt.Println(len2(x))
}
func len2(s []int) int {
if s == nil {
return 0
}
return 1 + len2(s[1:])
}
the result it should be in this example '3'.
It's broken in if s == nil:
panic: runtime error: slice bounds out of range
It panics because you have no valid termination condition.
When your len2() is called with a non-nil empty slice, it attempts to slice it like s[1:], which will be a runtime panic.
Instead of checking for nil slice, check if the slice is empty by comparing its length to 0:
func len2(s []int) int {
if len(s) == 0 {
return 0
}
return 1 + len2(s[1:])
}
Try it on the Go Playground.
If you can't use the builtin len() function (which you already did in your solution), you may use the for ... range:
func len2(s []int) int {
size := 0
for i := range s {
size = i + 1
}
return size
}
Try this on the Go Playground.
And if it must be recursive, then for example:
func len2(s []int) int {
size := 0
for range s {
size = 1 + len2(s[1:])
break
}
return size
}
Try this on the Go Playground.
But know that these are awful solutions compared to using the builtin len().
The following is not a solution with better performance than len but an implementation that does not use any extra libraries and depends on recursion to find length
func len2(s []int) (count int) {
defer func() {
if r := recover(); r != nil {
count = 0
}
}()
return 1 + len2(s[1:])
}
Here is sample code
package main
import "fmt"
func main() {
var x []int = nil
var x1 = []int{1, 2, 3, 4}
var x2 = []int{}
var x3 = make([]int, 10, 20)
fmt.Println(len2(x))
fmt.Println(len2(x1))
fmt.Println(len2(x2))
fmt.Println(len2(x3))
}
func len2(s []int) (count int) {
defer func() {
if r := recover(); r != nil {
count = 0
}
}()
return 1 + len2(s[1:])
}
Checkout the same in playground
If you can leave without recursion here is a function that does not use len() and should be faster then re-slicing recursively.
func len2(s []int) (count int) {
for i := range s {
count = i + 1
}
}
If you do not want to use len() func, you can use cap()
func main() {
x := []int{1, 2, 3}
fmt.Println(len2(x))
}
func len2(s []int) int {
if cap(s) == 0 {
return 0
}
return 1 + len2(s[1:])
}
Try it again
Original Answer:
In order to check if an array (slice) is empty, you should use the function len()
if len(s) == 0 {
return 0
}
Try it
I am new to golang, here I am using BubleSort and InsertionSort and generating a rando slice for the functions. Can I use pointers some how to hand both functions the unsorted slice? because when I run the program the first function sorts the slice and the the second function uses that sorted slice. I know there are different ways to give both functions the unsorted slice, but I want to see how can I use pointers to do this. Thank you.
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
slice := generateSlice(4)
fmt.Println(BubleSort(slice))
fmt.Println(InsertionSort(slice))
}
func generateSlice(size int) []int {
slice := make([]int, size, size)
rand.Seed(time.Now().UnixNano())
for i := 0; i < size; i++ {
slice[i] = rand.Intn(10)
}
return slice
}
func BubleSort(slice []int) []int {
fmt.Println("unsorted Buble", slice)
for i := 1; i <= len(slice); {
for j := 0; j < len(slice)-i; {
if slice[j] > slice[j+1] {
slice[j], slice[j+1] = slice[j+1], slice[j]
}
j++
}
i++
}
return slice
}
func InsertionSort(slice []int) []int {
fmt.Println("unsorted Insertion", slice)
for i := 1; i <= len(slice)-1; {
// Check j and j-1 and swap the smaller number to left in each
itteartion to reach the first 2 elements of the slice
for j := i; j >= 1; {
if slice[j] < slice[j-1] {
slice[j], slice[j-1] = slice[j-1], slice[j]
}
j--
}
i++
}
return slice
}
Andy is correct
As an alternative, you can copy the slice before sorting it, as in here (on Play):
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
slice := generateSlice(4)
fmt.Println(BubleSort(copySlice(slice)))
fmt.Println(InsertionSort(copySlice(slice)))
}
func copySlice(src []int) []int {
dest := make([]int, len(src))
copy(dest, src)
return dest
}
func generateSlice(size int) []int {
slice := make([]int, size, size)
rand.Seed(time.Now().UnixNano())
for i := 0; i < size; i++ {
slice[i] = rand.Intn(10)
}
return slice
}
func BubleSort(slice []int) []int {
fmt.Println("unsorted Buble", slice)
for i := 1; i <= len(slice); {
for j := 0; j < len(slice)-i; {
if slice[j] > slice[j+1] {
slice[j], slice[j+1] = slice[j+1], slice[j]
}
j++
}
i++
}
return slice
}
func InsertionSort(slice []int) []int {
fmt.Println("unsorted Insertion", slice)
for i := 1; i <= len(slice)-1; {
// Check j and j-1 and swap the smaller number to left in each itteartion to reach the first 2 elements of the slice
for j := i; j >= 1; {
if slice[j] < slice[j-1] {
slice[j], slice[j-1] = slice[j-1], slice[j]
}
j--
}
i++
}
return slice
}
I am learning Go as well. I think the fact that you are using slice is what causing the unwanted behaviour (when I run the program the first function sorts the slice and the the second function uses that sorted slice). As explained here:
A slice does not store any data, it just describes a section of an underlying array.
Changing the elements of a slice modifies the corresponding elements of its underlying array.
Other slices that share the same underlying array will see those changes.
I don't think passing pointer will produce different results as slices point to the same array. What you can do is maybe receive an array instead of slice?
Hope it helps! :)
Combinations can be printed using the following recursive code (inspired from Rosetta)
I thought it would be easy to store the intermediate results in an []int or the set of combination in an [][]int. But, because the function is recursive, it is not so easy than replacing the
fmt.Println(s)
by a
return s
with a minor modification of the function output for example. I also tried to feed a pointer like
p *[][]int
with the variable "s" inside the recursive function, but I failed :-/
I think it is a general problem with recursive functions so if you have some advises to solve this problem it will help me a lot !
Many thanks in advance ! ;)
package main
import (
"fmt"
)
func main() {
comb(5, 3)
}
func comb(n, m int) {
s := make([]int, m)
last := m - 1
var rc func(int, int)
rc = func(i, next int) {
for j := next; j < n; j++ {
s[i] = j
if i == last {
fmt.Println(s)
} else {
rc(i+1, j+1)
}
}
return
}
rc(0, 0)
}
Seems to me that s is being reused by each rc call so you just need to ensure that when storing s into an [][]int you store its copy, so as to not overwrite its contents during the next iteration.
To copy a slice you can use append like this:
scopy := append([]int{}, s...)
https://play.golang.org/p/lggy5JFL0Z
package main
import (
"fmt"
)
func main() {
out := comb(5, 3)
fmt.Println(out)
}
func comb(n, m int) (out [][]int) {
s := make([]int, m)
last := m - 1
var rc func(int, int)
rc = func(i, next int) {
for j := next; j < n; j++ {
s[i] = j
if i == last {
out = append(out, append([]int{}, s...))
} else {
rc(i+1, j+1)
}
}
return
}
rc(0, 0)
return out
}
In the following example, a person has a slice of friendships, and I try to initialize a friendship as a pointer to another person object, but for some reason it fails, and the result is that nobody has any friendships. Am I not using a pointer somewhere where I should be?
package main
import (
"fmt"
"math/rand"
)
type friendship struct {
friend *person
}
type person struct {
name int
friendship []friendship
}
func createPerson(id int) person {
return person{id, make([]friendship, 0)}
}
func (p *person) addFriends(possibleFriends []*person, numFriends int) {
var friend *person
for i := 0; i < numFriends; i++ {
friend = possibleFriends[rand.Intn(len(possibleFriends))]
p.friendship = append(p.friendship, friendship{friend})
}
}
func main() {
numPeople := 20
people := make([]person, numPeople)
possibleFriends := make([]*person, numPeople)
for i := 0; i < numPeople; i++ {
people[i] = createPerson(i)
possibleFriends[i] = &(people[i])
}
for _, p := range people {
p.addFriends(possibleFriends, 2)
}
fmt.Println(people)
}
use
for i := 0; i < numPeople; i++ {
people[i].addFriends(possibleFriends, 2)
}
or
for i, _ := range people {
people[i].addFriends(possibleFriends, 2)
}
instead of
for _, p := range people {
p.addFriends(possibleFriends, 2)
}
this is because p is a copy of people[i], addFriends has no effect on slice people
How to cast reflect.Value to its type?
type Cat struct {
Age int
}
cat := reflect.ValueOf(obj)
fmt.Println(cat.Type()) // Cat
fmt.Println(Cat(cat).Age) // doesn't compile
fmt.Println((cat.(Cat)).Age) // same
Thanks!
concreteCat,_ := reflect.ValueOf(cat).Interface().(Cat)
see http://golang.org/doc/articles/laws_of_reflection.html
fox example
type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)
y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)
Ok, I found it
reflect.Value has a function Interface() that converts it to interface{}
This func auto-converts types as needed. It loads a config file values into a simple struct based on struct name and fields:
import (
"fmt"
toml "github.com/pelletier/go-toml"
"log"
"os"
"reflect"
)
func LoadConfig(configFileName string, configStruct interface{}) {
defer func() {
if r := recover(); r != nil {
fmt.Println("LoadConfig.Recovered: ", r)
}
}()
conf, err := toml.LoadFile(configFileName)
if err == nil {
v := reflect.ValueOf(configStruct)
typeOfS := v.Elem().Type()
sectionName := getTypeName(configStruct)
for i := 0; i < v.Elem().NumField(); i++ {
if v.Elem().Field(i).CanInterface() {
kName := conf.Get(sectionName + "." + typeOfS.Field(i).Name)
kValue := reflect.ValueOf(kName)
if (kValue.IsValid()) {
v.Elem().Field(i).Set(kValue.Convert(typeOfS.Field(i).Type))
}
}
}
} else {
fmt.Println("LoadConfig.Error: " + err.Error())
}
}
Seems the only way would be to do a switch statement similar to (code below) (also, something like the commented line would've-been nice though doesn't work (:()):
func valuesFromStruct (rawV interface{}) []interface{} {
v := reflect.ValueOf(rawV)
out := make([]interface{}, 0)
for i := 0; i < v.NumField(); i += 1 {
field := v.Field(i)
fieldType := field.Type()
// out = append(out, field.Interface().(reflect.PtrTo(fieldType)))
switch (fieldType.Name()) {
case "int64":
out = append(out, field.Interface().(int64))
break`enter code here`
case "float64":
out = append(out, field.Interface().(float64))
break
case "string":
out = append(out, field.Interface().(string))
break
// And all your other types (here) ...
default:
out = append(out, field.Interface())
break
}
}
return out
}
Cheers!