Generating combinatorial string from map - go

I have a map as such:
// map[int] position in string
// map[rune]bool characters possible at said position
func generateString(in map[int]map[rune]bool) []string {
// example: {0: {'A':true, 'C': true}, 1: {'E': true}, 2: {'I': true, 'X': true}}
result := []string{"AEI", "AEX", "CEI", "CEX"} // should generate these
return result
}
The difference with all possible permutations is that we are specifying which permutations are possible by index and I think that's the real head-breaker here.

First, we need to convert map[int]map[rune]bool to []map[rune]bool since map iteration isn't guaranteed to be sorted by key's
After that, this is a recursive approach
var res []string
func dfs(curString string, index int, in []map[rune]bool) {
if index == len(in) {
res = append(res, curString)
return
}
for ch, is := range in[index] {
if !is { // I assume booleans can be false
return
}
dfs(curString+string(ch), index+1, in)
}
}
and we can call it with dfs("", 0, arr) where arr is given map converted to slice and answer will be in res variable

Related

Reading from a slice of unknown length in Golang

I'm trying to replicate this algorithm for finding duplicates in an array in Golang. Here's the javascript version:
function hasDuplicateValue(array) {
let existingNumbers = [];
for(let i = 0; i < array.length; i++) {
if(existingNumbers[array[i]] === 1) {
return true;
} else {
existingNumbers[array[i]] = 1;
}
}
return false;
}
On line 2, the algorithm creates an empty array of unknown length, and then adds 1 to an index in the array corresponding with each number that it finds (e.g. if it finds the number 3 in the array, it will add a 1 to index 3 in existing numbers.
I'm wondering — how do I replicate this in Golang (since we need to have slots allocated in the slice before reading it). Would I first need to find the max value in the array and then declare the existingNumbers slice to be of that same size?
Or is there a more efficient way of doing this (instead of searching through the array and finding the max value before constructing the slice).
Thanks!
Edit:
I realized that I can't do this with a slice because I can't read from an empty value. However, as #icza suggested, it will work with a map:
func findDuplicates(list []int)(bool) {
temp := make(map[int]int)
for _, elem := range list {
if temp[elem] == 1 {
return true
} else {
temp[elem] = 1
}
}
return false
}
As comments, I would also suggest using a map to keep the state of the duplications, but we can use map[int]struct{} because empty structs are not consumed any memory in Go.
And also I have simplified the code a bit and it is as follows.
func findDuplicates(list []int) bool {
temp := make(map[int]struct{})
for _, elem := range list {
if _, ok := temp[elem]; ok {
return true
}
temp[elem] = struct{}{}
}
return false
}
Full code can be executed here

GOLANG Delete a slice from Slice of Slice

I want to create function to delete a slice from slice of slice. It should take two inputs: 1. slice of slice (list var) and 2. slice to be deleted (eachsvc) as input. And return updated slice of slice (list var).
I am having issues with this code as it is not working with slice of slice. Any help is appreciated. Thanks.
func truncate_slice(list [][]string, eachsvc []string) [][]string {
//find index of eachsvc in list
i := indexOf(eachsvc, list)
copy(list[i:], list[i+1:]) // Shift a[i+1:] left one index.
list[len(list)-1] = "" // Erase last element (write zero value).
list = list[:len(list)-1] // Truncate slice.
return list
}
Func to get index of slice to be deleted from slice of slice
func indexOf(element []string, data [][]string) int {
for k, v := range data {
if element == v {
return k
}
}
return -1 //not found.
}
Since you want to compare slices based on their elements (as you commented), you will first need to define a function to check equality of 2 given slices. Something like this:
func eq(s1, s2 []string) bool {
if len(s1) != len(s2) {
return false
}
s2Map := make(map[string]int)
s1Map := make(map[string]int)
for _, str := range s2 {
s2Map[str] += 1
}
for _, str := range s1 {
s1Map[str] += 1
}
for key, count := range s1Map {
if count != s2Map[key] {
return false
}
}
return true
}
So in this case, ["John", "Doe"] is equal to ["Doe", "John"]. If you also want to check order, I would suggest you to use reflect.DeepEqual(slice1, slice2) instead of implementing one. By the way, using == to compare slices, means if they have the same reference, since slices are views over arrays basically.
As AminMal has said, you can use "reflect.DeepEqual(slice1, slice2)" to compare the slices.
As per documentation:
Slice values are deeply equal when all of the following are true: they are both nil or both non-nil, they have the same length, and either they point to the same initial entry of the same underlying array (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal. Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil)) are not deeply equal.
package main
import (
"errors"
"fmt"
"reflect"
)
func main() {
sl := [][]string{[]string{"test1"}, []string{"test1", "test2"}, []string{"test3"}}
truncSlic, err := truncate_slice(sl, []string{"test3"})
if err != nil {
fmt.Println(err)
return
}
fmt.Println(truncSlic)
}
func indexOf(element []string, data [][]string) int {
for i, v := range data {
if reflect.DeepEqual(element, v) { //compare two silces
return i
}
}
return -1
}
func truncate_slice(list [][]string, eachsvc []string) ([][]string, error) {
//find index of eachsvc in list
i := indexOf(eachsvc, list)
if i == -1 {
return nil, errors.New("Not Found")
}
copy(list[i:], list[i+1:]) // Shift a[i+1:] left one index.
list[len(list)-1] = nil // Erase last element (write zero value).
list = list[:len(list)-1] // Truncate slice.
return list, nil
}
Output: [[test1] [test1 test2]]
element == v is invalid, because the operator == is not defined on []string, so you should define it:
func truncate_slice(list [][]string, eachsvc []string) [][]string {
//find index of eachsvc in list
i := indexOf(eachsvc, list)
copy(list[i:], list[i+1:]) // Shift a[i+1:] left one index.
list[len(list)-1] = nil // Erase last element (write zero value).
list = list[:len(list)-1] // Truncate slice.
return list
}
func indexOf(element []string, data [][]string) int {
for k, v := range data {
if equals(element, v) {
return k
}
}
return -1 //not found.
}
func equals(l1, l2 []string) bool {
if len(l1) != len(l2) {
return false
}
for i := 0; i < len(l1); i++ {
if l1[i] != l2[i] {
return false
}
}
return true
}

How do i remove duplicate valeus in push?

This might be noob question...
How to remove the duplicate values instead pushing values?
When the values was:("lorem", "ipsum", 1, 1, 1, "jack", "jill", "felix", "donking")
It should print:("lorem", "ipsum", 1, "jack", "jill", "felix", "donking")
How to remove this duplicated values in push function like above?
// Push values
func (q *Data) Push(n interface{}) *Data {
if q.Len() < q.size {
q.data = append(q.data, n)
if q.data[q.Len()] == q.data[q.Len()+1] {
q.Pop()
q.Push(n)
}
} else {
q.Pop()
q.Push(n)
}
return q
}
Every data structure uses an underlying primitive data structure for implementation, and it looks like you are using a slice. If you only want to save unique data, you should use a map. In order to be as efficient as possible when using a map only for finding duplicates, you can use a map[interface{}]struct{}.
One needs to check the data in the queue against the pushed value. If the data was already in the queue it should returned.
for i := range q.data {
if q.data[i] == n {
return q // return q when n value is found equal to one of q.data values.
}
}
q.data = append(q.data, n)

Find the minimum value in golang?

In the language there is a minimum function https://golang.org/pkg/math/#Min But what if I have more than 2 numbers? I must to write a manual comparison in a for loop, or is there another way? The numbers are in the slice.
No, there isn't any better way than looping. Not only is it cleaner than any other approach, it's also the fastest.
values := []int{4, 20, 0, -11, -10}
min := values[0]
for _, v := range values {
if (v < min) {
min = v
}
}
fmt.Println(min)
EDIT
Since there has been some discussion in the comments about error handling and how to handle empty slices, here is a basic function that determines the minimum value. Remember to import errors.
func Min(values []int) (min int, e error) {
if len(values) == 0 {
return 0, errors.New("Cannot detect a minimum value in an empty slice")
}
min = values[0]
for _, v := range values {
if (v < min) {
min = v
}
}
return min, nil
}
General answer is: "Yes, you must use a loop, if you do not know exact number of items to compare".
In this package Min functions are implemented like:
// For 2 values
func Min(value_0, value_1 int) int {
if value_0 < value_1 {
return value_0
}
return value_1
}
// For 1+ values
func Mins(value int, values ...int) int {
for _, v := range values {
if v < value {
value = v
}
}
return value
}
You should write a loop. It does not make sense to create dozens of function in standard library to find min/max/count/count_if/all_of/any_of/none_of etc. like in C++ (most of them in 4 flavours according arguments).

How to check the uniqueness inside a for-loop?

Is there a way to check slices/maps for the presence of a value?
I would like to add a value to a slice only if it does not exist in the slice.
This works, but it seems verbose. Is there a better way to do this?
orgSlice := []int{1, 2, 3}
newSlice := []int{}
newInt := 2
newSlice = append(newSlice, newInt)
for _, v := range orgSlice {
if v != newInt {
newSlice = append(newSlice, v)
}
}
newSlice == [2 1 3]
Your approach would take linear time for each insertion. A better way would be to use a map[int]struct{}. Alternatively, you could also use a map[int]bool or something similar, but the empty struct{} has the advantage that it doesn't occupy any additional space. Therefore map[int]struct{} is a popular choice for a set of integers.
Example:
set := make(map[int]struct{})
set[1] = struct{}{}
set[2] = struct{}{}
set[1] = struct{}{}
// ...
for key := range(set) {
fmt.Println(key)
}
// each value will be printed only once, in no particular order
// you can use the ,ok idiom to check for existing keys
if _, ok := set[1]; ok {
fmt.Println("element found")
} else {
fmt.Println("element not found")
}
Most efficient is likely to be iterating over the slice and appending if you don't find it.
func AppendIfMissing(slice []int, i int) []int {
for _, ele := range slice {
if ele == i {
return slice
}
}
return append(slice, i)
}
It's simple and obvious and will be fast for small lists.
Further, it will always be faster than your current map-based solution. The map-based solution iterates over the whole slice no matter what; this solution returns immediately when it finds that the new value is already present. Both solutions compare elements as they iterate. (Each map assignment statement certainly does at least one map key comparison internally.) A map would only be useful if you could maintain it across many insertions. If you rebuild it on every insertion, then all advantage is lost.
If you truly need to efficiently handle large lists, consider maintaining the lists in sorted order. (I suspect the order doesn't matter to you because your first solution appended at the beginning of the list and your latest solution appends at the end.) If you always keep the lists sorted then you you can use the sort.Search function to do efficient binary insertions.
Another option:
package main
import "golang.org/x/tools/container/intsets"
func main() {
var (
a intsets.Sparse
b bool
)
b = a.Insert(9)
println(b) // true
b = a.Insert(9)
println(b) // false
}
https://pkg.go.dev/golang.org/x/tools/container/intsets
This option if the number of missing numbers is unknown
AppendIfMissing := func(sl []int, n ...int) []int {
cache := make(map[int]int)
for _, elem := range sl {
cache[elem] = elem
}
for _, elem := range n {
if _, ok := cache[elem]; !ok {
sl = append(sl, elem)
}
}
return sl
}
distincting a array of a struct :
func distinctObjects(objs []ObjectType) (distinctedObjs [] ObjectType){
var output []ObjectType
for i:= range objs{
if output==nil || len(output)==0{
output=append(output,objs[i])
} else {
founded:=false
for j:= range output{
if output[j].fieldname1==objs[i].fieldname1 && output[j].fieldname2==objs[i].fieldname2 &&......... {
founded=true
}
}
if !founded{
output=append(output,objs[i])
}
}
}
return output
}
where the struct here is something like :
type ObjectType struct {
fieldname1 string
fieldname2 string
.........
}
the object will distinct by checked fields here :
if output[j].fieldname1==objs[i].fieldname1 && output[j].fieldname2==objs[i].fieldname2 &&......... {

Resources