Digitize function return the indices of the bins to which each value in input array belongs.
Below code is from python -
x = np.array([0.8, 6.9, 3.5, 1.9])
bins = np.array([0.0, 1.0, 2.5, 4.0, 10.0])
inds = np.digitize(x, bins)
print(inds)
array([1, 4, 3, 2])
This does it:
package main
import (
"fmt"
"sort"
)
func digitize(x, bins []float64) []int {
inds := make([]int, len(x))
for k, v := range x {
inds[k] = sort.SearchFloat64s(bins, v)
}
return inds
}
func main() {
x := []float64{0.8, 6.9, 3.5, 1.9}
bins := []float64{0, 1, 2.5, 4, 10}
inds := digitize(x, bins)
fmt.Println(inds) // [1 4 3 2]
}
https://golang.org/pkg/sort#SearchFloat64s
package main
import (
"errors"
"fmt"
"sort"
)
type arr []float64
func (a arr) Less(i, j int) bool {
return a[i] < a[j]
}
func (in arr) digitize(bins arr) ([]int, error) {
if !sort.SliceIsSorted(bins, bins.Less) {
return nil, errors.New("bins array is not sorted")
}
indices := make([]int, len(in))
for i, x := range in {
indices[i] = sort.SearchFloat64s(bins, x)
}
return indices, nil
}
func main() {
var (
x = arr{0.8, 6.9, 3.5, 1.9}
bins = arr{0.0, 1.0, 2.5, 4.0, 10.0}
)
indices, err := x.digitize(bins)
if err != nil {
panic(err)
}
fmt.Println(indices)
}
Ref: https://golang.org/pkg/sort#SearchFloat64s
SearchFloat64s searches for x in a sorted slice of float64s and returns the index as specified by Search. The return value is the index to insert x if x is not present (it could be len(a)). The slice must be sorted in ascending order.
Related
I'm trying to traverse a map in decreasing order of the values stored against keys. I've tried:
func frequencySort(s string) string {
var frequency map[string]int
chararray := strings.Split(s , "")
var a []int
var arranged map[int]string
for k , v := range frequency {
arranged[v] = k
}
for k := range arranged {
a = append(a , k)
}
sort.Sort(sort.Reverse(sort.IntSlice{a}))
}
Let's say the Map structure is :
"a" : 9
"b" : 7
"c" : 19
"d" : 11
and I'm trying to traverse it such that the output is :
"c" : 19
"d" : 11
"a" : 9
"b" : 7
The two map approach you have in your example will break as soon as you have more than one key in frequency with the same value, say "a":7 and "b":7, then you would lose data in arranged since keys have to be unique.
To avoid this you could create a helper type that will hold the map's contents temporarily, just for sorting purposes. Something like this:
package main
import (
"fmt"
"sort"
)
var m = map[string]int{
"a": 9,
"b": 7,
"c": 19,
"d": 11,
}
type entry struct {
val int
key string
}
type entries []entry
func (s entries) Len() int { return len(s) }
func (s entries) Less(i, j int) bool { return s[i].val < s[j].val }
func (s entries) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func main() {
var es entries
for k, v := range m {
es = append(es, entry{val: v, key: k})
}
sort.Sort(sort.Reverse(es))
for _, e := range es {
fmt.Printf("%q : %d\n", e.key, e.val)
}
}
https://play.golang.org/p/TPb0zNCtXO
For example,
package main
import (
"fmt"
"sort"
)
type frequncy struct {
c string
f int
}
func frequencies(s string) []frequncy {
m := make(map[string]int)
for _, r := range s {
m[string(r)]++
}
a := make([]frequncy, 0, len(m))
for c, f := range m {
a = append(a, frequncy{c: c, f: f})
}
sort.Slice(a, func(i, j int) bool { return a[i].f > a[j].f })
return a
}
func main() {
s := "aaaaabcbcbcbzxyyxzzsoaz"
fmt.Println(s)
f := frequencies(s)
fmt.Println(f)
}
Playground: https://play.golang.org/p/d9i3yL1x4K
Output:
aaaaabcbcbcbzxyyxzzsoaz
[{a 6} {b 4} {z 4} {c 3} {x 2} {y 2} {s 1} {o 1}]
I am trying to learn Go, so here is my very simple function for removing adjacent duplicates from slice for exercise from the book by Donovan & Kernighan.
Here is the code: https://play.golang.org/p/avHc1ixfck
package main
import "fmt"
func main() {
a := []int{0, 1, 1, 3, 3, 3}
removeDup(a)
fmt.Println(a)
}
func removeDup(s []int) {
n := len(s)
tmp := make([]int, 0, n)
tmp = append(tmp, s[0])
j := 1
for i := 1; i < n; i++ {
if s[i] != s[i-1] {
tmp = append(tmp, s[i])
j++
}
}
s = s[:len(tmp)]
copy(s, tmp)
}
It should print out [0 1 3] - and I checked, actually tmp at the end of the function it has desired form. However, the result is [0 1 3 3 3 3]. I guess there is something with copy function.
Can I somehow replace input slice s with the temp or trim it to desired length?
Option 1
Return a new slice as suggested by #zerkms.
https://play.golang.org/p/uGJiD3WApS
package main
import "fmt"
func main() {
a := []int{0, 1, 1, 3, 3, 3}
a = removeDup(a)
fmt.Println(a)
}
func removeDup(s []int) []int {
n := len(s)
tmp := make([]int, 0, n)
tmp = append(tmp, s[0])
for i := 1; i < n; i++ {
if s[i] != s[i-1] {
tmp = append(tmp, s[i])
}
}
return tmp
}
Option 2
Use pointers for pass-by-reference.
The same thing in effect as that of option1.
https://play.golang.org/p/80bE5Qkuuj
package main
import "fmt"
func main() {
a := []int{0, 1, 1, 3, 3, 3}
removeDup(&a)
fmt.Println(a)
}
func removeDup(sp *[]int) {
s := *sp
n := len(s)
tmp := make([]int, 0, n)
tmp = append(tmp, s[0])
for i := 1; i < n; i++ {
if s[i] != s[i-1] {
tmp = append(tmp, s[i])
}
}
*sp = tmp
}
Also, refer to following SO thread:
Does Go have no real way to shrink a slice? Is that an issue?
Here's two more slightly different ways to achieve what you want using sets and named types. The cool thing about named types is that you can create interfaces around them and can help with the readability of lots of code.
package main
import "fmt"
func main() {
// returning a list
a := []int{0, 1, 1, 3, 3, 3}
clean := removeDup(a)
fmt.Println(clean)
// creating and using a named type
nA := &newArrType{0, 1, 1, 3, 3, 3}
nA.removeDup2()
fmt.Println(nA)
// or... casting your orginal array to the named type
nB := newArrType(a)
nB.removeDup2()
fmt.Println(nB)
}
// using a set
// order is not kept, but a set is returned
func removeDup(s []int) (newArr []int) {
set := make(map[int]struct{})
for _, n := range s {
set[n] = struct{}{}
}
newArr = make([]int, 0, len(set))
for k := range set {
newArr = append(newArr, k)
}
return
}
// using named a typed
type newArrType []int
func (a *newArrType) removeDup2() {
x := *a
for i := range x {
f := i + 1
if f < len(x) {
if x[i] == x[f] {
x = x[:f+copy(x[f:], x[f+1:])]
}
}
}
// check the last 2 indexes
if x[len(x)-2] == x[len(x)-1] {
x = x[:len(x)-1+copy(x[len(x)-1:], x[len(x)-1+1:])]
}
*a = x
}
I have an array like:
a:= [1,2,3,4,5]
b:= [5,6,7,8,9]
How to know array b have contain element in array a without using foreach?
How to know array b have contain element in array a without using foreach?
You can't. And you should not try as this is pointless restriction.
If the arrays are sorted (as they appear to be in your question) there is an algorithm that works better than going through each element.
Pick the first element of a, call it x.
Binary search b for the first element equal or greater than x. If they are equal, you found an element that is contained in both arrays, if not, make that your new x. Now search a for x in the same way. Repeat until you run out of elements in one of the arrays.
This can be trivially extended to an arbitrary number of arrays (in fact, it's easier to write with an arbitrary number of arrays).
Here's a quick and dirty implementation:
package main
import (
"fmt"
"sort"
)
func inter(arrs ...[]int) []int {
res := []int{}
x := arrs[0][0]
i := 1
for {
off := sort.SearchInts(arrs[i], x)
if off == len(arrs[i]) {
// we emptied one slice, we're done.
break
}
if arrs[i][off] == x {
i++
if i == len(arrs) {
// x was in all the slices
res = append(res, x)
x++ // search for the next possible x.
i = 0
}
} else {
x = arrs[i][off]
i = 0 // This can be done a bit more optimally.
}
}
return res
}
func main() {
a := []int{1, 2, 3, 4, 5, 7}
b := []int{5, 6, 7, 8, 9}
fmt.Println(inter(a, b))
}
package main
import (
set "github.com/deckarep/golang-set"
)
func array_intersect(a, b []interface{}) []interface{} {
return set.NewSetFromSlice(a).Intersect(set.NewSetFromSlice(b)).ToSlice()
}
func main() {
a := []interface{}{1, 2, 3, 4, 5, 7}
b := []interface{}{5, 6, 7, 8, 9}
println(array_intersect(a, b))
}
package main
import (
"fmt"
"sort"
)
func array_intersect(a, b []int) []int {
ret := []int{}
lenA := len(a)
lenB := len(b)
if lenA == 0 || lenB == 0 {
return ret
}
sort.Ints(a)
sort.Ints(b)
var i, j int
for {
a = a[i:]
if i = sort.SearchInts(a, b[j]); i >= len(a) {
break
}
if a[i] == b[j] {
ret = append(ret, a[i])
}
if j++; j >= lenB {
break
}
}
return ret
}
func main() {
a := []int{5, 7, 1, 1, 2, 3, 4, 5, 7}
b := []int{1, 1, 5, 6, 7, 8, 9}
fmt.Printf("a=%v, b=%v", a, b)
fmt.Printf("%v\n", array_intersect(a, b))
fmt.Printf("a=%v, b=%v", a, b)
}
I'm trying to implement a string shuffle function in Go that uses crypto/rand instead of math/rand. The Fisher-Yates Shuffle requires random integers so I've tried to implement that functionality, without having to use crypto/rand Int which relies on math/big. Below is the best I've come up with so far but is there a better method? The fact that I can't find existing examples leads me to wonder if there's a good reason why nobody does this!
package main
import "crypto/rand"
import "fmt"
import "encoding/binary"
func randomInt(max int) int {
var n uint16
binary.Read(rand.Reader, binary.LittleEndian, &n)
return int(n) % max
}
func shuffle(s *[]string) {
slice := *s
for i := range slice {
j := randomInt(i + 1)
slice[i], slice[j] = slice[j], slice[i]
}
*s = slice
}
func main() {
slice := []string{"a", "b", "c", "d", "e", "f", "h", "i", "j", "k"}
shuffle(&slice)
fmt.Println(slice)
}
Go's math/rand library has good facilities for producing random numerical primitives from a Source.
// A Source represents a source of uniformly-distributed
// pseudo-random int64 values in the range [0, 1<<63).
type Source interface {
Int63() int64
Seed(seed int64)
}
NewSource(seed int64) returns the builtin, deterministic PRNG, but New(source Source) will allow anything that satisfies the Source interface.
Here is an example of a Source that is backed by crypto/rand.
type CryptoRandSource struct{}
func NewCryptoRandSource() CryptoRandSource {
return CryptoRandSource{}
}
func (_ CryptoRandSource) Int63() int64 {
var b [8]byte
rand.Read(b[:])
// mask off sign bit to ensure positive number
return int64(binary.LittleEndian.Uint64(b[:]) & (1<<63 - 1))
}
func (_ CryptoRandSource) Seed(_ int64) {}
You can use it like this:
r := rand.New(NewCryptoRandSource())
for i := 0; i < 10; i++ {
fmt.Println(r.Int())
}
The math/rand library has a properly implemented Intn() method which ensures a uniform distribution.
func (r *Rand) Intn(n int) int {
if n <= 0 {
panic("invalid argument to Intn")
}
if n <= 1<<31-1 {
return int(r.Int31n(int32(n)))
}
return int(r.Int63n(int64(n)))
}
func (r *Rand) Int31n(n int32) int32 {
if n <= 0 {
panic("invalid argument to Int31n")
}
if n&(n-1) == 0 { // n is power of two, can mask
return r.Int31() & (n - 1)
}
max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
v := r.Int31()
for v > max {
v = r.Int31()
}
return v % n
}
func (r *Rand) Int63n(n int64) int64 {
if n <= 0 {
panic("invalid argument to Int63n")
}
if n&(n-1) == 0 { // n is power of two, can mask
return r.Int63() & (n - 1)
}
max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
v := r.Int63()
for v > max {
v = r.Int63()
}
return v % n
}
Cryptographic hash functions also can be wrapped as a Source for alternate means of randomness.
The numbers from n % max are not distributed uniformly. For example,
package main
import (
"fmt"
"math"
)
func main() {
max := 7
size := math.MaxUint8
count := make([]int, size)
for i := 0; i < size; i++ {
count[i%max]++
}
fmt.Println(count[:max])
}
Output:
[37 37 37 36 36 36 36]
Based on the comments received, I think I can improve on the example in my question by adding a uniformInt function, populating a uint32 instead of a uint16 and removing the pointer to the slice.
package main
import "crypto/rand"
import "fmt"
import "encoding/binary"
func randomInt() int {
var n uint32
binary.Read(rand.Reader, binary.LittleEndian, &n)
return int(n)
}
func uniformInt(max int) (r int) {
divisor := 4294967295 / max // Max Uint32
for {
r = randomInt() / divisor
if r <= max {
break
}
}
return
}
func shuffle(slice []string) {
for i := range slice {
j := uniformInt(i + 1)
slice[i], slice[j] = slice[j], slice[i]
}
}
func main() {
slice := []string{"a", "b", "c", "d", "e", "f", "h", "i", "j", "k"}
shuffle(slice)
fmt.Println(slice)
}
How do I reverse an arbitrary slice ([]interface{}) in Go? I'd rather not have to write Less and Swap to use sort.Reverse. Is there a simple, builtin way to do this?
The standard library does not have a built-in function for reversing a slice. Use a for loop to reverse a slice:
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
Use type parameters to write a generic reverse function in Go 1.18 or later:
func reverse[S ~[]E, E any](s S) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
Use reflect.Swapper to write a function that works with arbitrary slice types in Go version 1.8 or later:
func reverse(s interface{}) {
n := reflect.ValueOf(s).Len()
swap := reflect.Swapper(s)
for i, j := 0, n-1; i < j; i, j = i+1, j-1 {
swap(i, j)
}
}
Run the code on the Go playground.
The functions in this answer reverse the slice inplace. If you do not want to modify the original slice, copy the slice before reversing the slice.
Here's another possible way to reverse generic slice (go 1.18)
// You can edit this code!
// Click here and start typing.
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int64{10, 5, 15, 20, 1, 100, -1}
ReverseSlice(nums)
fmt.Println(nums)
strs := []string{"hello", "world"}
ReverseSlice(strs)
fmt.Println(strs)
runes := []rune{'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'}
ReverseSlice(runes)
for _, r := range runes {
fmt.Print(string(r), " ")
}
}
func ReverseSlice[T comparable](s []T) {
sort.SliceStable(s, func(i, j int) bool {
return i > j
})
}
Running the program above should output:
[-1 100 1 20 15 5 10]
[world hello]
d l r o w o l l e h
Program exited.
go playground
This will return a reversed slice without modifying the original slice.
Algorithm used from official wiki page: https://github.com/golang/go/wiki/SliceTricks#reversing
func reverse(s []interface{}) []interface{} {
a := make([]interface{}, len(s))
copy(a, s)
for i := len(a)/2 - 1; i >= 0; i-- {
opp := len(a) - 1 - i
a[i], a[opp] = a[opp], a[i]
}
return a
}
There are my code example, you can run it in playground
package main
import (
"fmt"
"reflect"
"errors"
)
func ReverseSlice(data interface{}) {
value := reflect.ValueOf(data)
if value.Kind() != reflect.Slice {
panic(errors.New("data must be a slice type"))
}
valueLen := value.Len()
for i := 0; i <= int((valueLen-1)/2); i++ {
reverseIndex := valueLen - 1 - i
tmp := value.Index(reverseIndex).Interface()
value.Index(reverseIndex).Set(value.Index(i))
value.Index(i).Set(reflect.ValueOf(tmp))
}
}
func main() {
names := []string{"bob", "mary", "sally", "michael"}
ReverseSlice(names)
fmt.Println(names)
}
Here is the function I'm using with generics (go 1.18+). You can use it to reverse any kind of slice or even a string (using the split/join trick). It doesn't change the original slice.
package main
import (
"fmt"
"strings"
)
func Reverse[T any](original []T) (reversed []T) {
reversed = make([]T, len(original))
copy(reversed, original)
for i := len(reversed)/2 - 1; i >= 0; i-- {
tmp := len(reversed) - 1 - i
reversed[i], reversed[tmp] = reversed[tmp], reversed[i]
}
return
}
func main() {
a := []string{"a", "b", "c"}
fmt.Println(a, Reverse(a))
b := []uint{0, 1, 2}
fmt.Println(b, Reverse(b))
c := "abc"
fmt.Println(c, strings.Join(Reverse(strings.Split(c, "")), ""))
}
Better Go Playground
This generic slice reversal function should do it for you:
func ReverseSlice[T comparable](s []T) []T {
var r []T
for i := len(s) - 1; i >= 0; i-- {
r = append(r, s[i])
}
return r
}