I tried below golang code to check if first string can be formed from second string. Is there any improvement that can be done on this code?
package main
import (
"fmt"
"strings"
)
func main() {
words := []string{"hello", "ellhoo"}
result := "NO"
s := words[0]
for i := 0; i < len(words[0]); i++ {
if strings.Contains(words[1], string(s[i])) == false {
result = "NO"
break
} else {
result = "YES"
words[1] = strings.Replace(words[1],string(s[i]),"",1)
}
}
fmt.Println(result)
}
Record the count of each rune in the source string in a map. For each rune in the target string, fail if count in map is zero. Decrement count.
Here's the code:
// canmake reports whether t can constructed from the runes in s.
func canmake(t, s string) bool {
m := map[rune]int{}
for _, r := range s {
m[r]++
}
for _, r := range t {
if m[r] == 0 {
return false
}
m[r]--
}
return true
}
Here's an example showing how to use it:
func main() {
fmt.Println(canmake("hello", "ellhoo"))
fmt.Println(canmake("hello", "elhoo")) // insufficent number of l
fmt.Println(canmake("hello", "elloo")) // mising h
}
package main
import "fmt"
func Reverse(str string) string {
r := ""
for i := len(str) - 1; i >= 0; i-- {
r += string(str[i])
// fmt.Println(r)
}
return r
}
func Generate(str string) string {
str = Reverse(str)
// vowel := ""
for _, rne := range str {
if rne == 'a' {
str += "A"
}
if rne == 'e' {
str += "E"
}
if rne == 'i' {
str += "I"
}
if rne == 'o' {
str += "O"
}
if rne == 'u' {
str += "U"
}
}
return Reverse(str)
}
func main() {
fmt.Println(...("haigolang123"))
}
This program will accept a logic from the previous function, then combine it with the next function.
I wondering how to invoke a function from the result of another function.
expect output is "321gnAlOgIAh"
I didn't get why you are trying to reverse the string twice if your input is haigolang123 and expected output is 321gnAlOgIAh. Let's refactor step by step.
For vowels, if all you needed to do is convert lower case to upper, you can direct subtract number 32 from rune (since 'a'=97 & 'A'=65). So, use a function to common out the check.
func in(c rune, list []rune) bool {
for _, l := range list {
if c == l {
return true
}
}
return false
}
This can check as follows:
vowelsLower := []rune{'a', 'e', 'i', 'o', 'u'}
# Some code here
if in(c, vowelsLower) {
result += string(c-32)
}
There are many ways to append strings, refer here when working particularly with strings. However, we are working with runes. It is easier to append it to a byte slice. Looking at the bigger picture, []byte can be directly converted to string when needed.
var result []byte
# Some code here
if in(c, vowelsLower) {
result = append(result, byte(c-diff))
}
While returning,
return string(result)
This is your code with these changes.
Additionally, why to iterate twice (once in Generate, and again in Reverse). Try reverse iterating and do the vowel case switching. The noticeable difference of this approach is it uses bytes directly.
Range over string gives rune. Slicing the string gives byte. Of course they can be typecasted from one another.
Since we were already using bytes in previous approach, the code looks like this.
Happy coding!!
In Go, write
package main
import "fmt"
func toUpper(r rune) rune {
switch r {
case 'a', 'e', 'i', 'o', 'u':
r &= 0b1101_1111
}
return r
}
func Generate(s string) string {
g := []rune(s)
for i, j := 0, len(g)-1; i <= j; i, j = i+1, j-1 {
g[i], g[j] = toUpper(g[j]), toUpper(g[i])
}
return string(g)
}
func main() {
s := "haigolang123"
fmt.Printf("%q\n", s)
g := Generate(s)
fmt.Printf("%q\n", g)
}
https://go.dev/play/p/pGRas6qsi8O
"haigolang123"
"321gnAlOgIAh"
Go is designed for efficient solutions.
In Go, strings are immutable. concatenating strings a and b creates a new string of length len(a) + len(b) and copies both a and b to the new string. It can get expensive.
Testing characters for all the vowels, even after you have matched one, is unnecessary.
Refactor your functional decomposition of Generate to include reversing a string while using a toUpper function for vowels.
I have the following string:
absoloute-power
As you can see, there is a "-" at position number 10 in the string. How do I write the go code to validate if the 10th position of any given string has a "-" in the string?
In Go, string character values are Unicode characters encoded in UTF-8. UTF-8 is a variable-length encoding which uses one to four bytes per character.
For your example:
package main
import (
"fmt"
"unicode/utf8"
)
func is10Hyphen(s string) bool {
for n := 1; len(s) > 0; n++ {
r, size := utf8.DecodeRuneInString(s)
if r == utf8.RuneError && (size == 0 || size == 1) {
return false
}
if n == 10 {
return r == '-'
}
s = s[size:]
}
return false
}
func main() {
s := "absoloute-power"
fmt.Println(is10Hyphen(s))
s = "absoloute+power"
fmt.Println(is10Hyphen(s))
s = "absoloute"
fmt.Println(is10Hyphen(s))
}
Playground: https://play.golang.org/p/h9rMQWWAdvb
Output:
true
false
false
If you are willing to consider encountering the Unicode replacement character an error, then for your example:
func is10Hyphen(s string) bool {
n := 0
for _, r := range s {
if r == utf8.RuneError {
return false
}
n++
if n == 10 {
return r == '-'
}
}
return false
}
Playground: https://play.golang.org/p/SHbPAnldTyw
You could use a rune-array:
text := "ifthisisyourstring"
chars := []rune(text)
if chars[0] == '1' {
// is true
}
As string is an array in fact, you can access the 10th position directly.Of course, need to avoid "out of range " error.
For the case of the non-ascii encoding, converting it to a rune array
package main
import (
"fmt"
)
func main() {
fmt.Println(Check("213123-dasdas"))
fmt.Println(Check("213123sdas"))
fmt.Println(Check("213123das-das"))
fmt.Println(Check("213123dasda-s"))
fmt.Println(Check("---------2----------"))
}
func Check(ss string) bool {
r = []rune(ss)
if len(r) < 10 {
return false
}
return ss[r] == '-'
}
I am trying to find a solution to check for equality in 2 slices. Unfortanely, the answers I have found require values in the slice to be in the same order. For example, http://play.golang.org/p/yV0q1_u3xR evaluates equality to false.
I want a solution that lets []string{"a","b","c"} == []string{"b","a","c"} evaluate to true.
MORE EXAMPLES
[]string{"a","a","c"} == []string{"c","a","c"} >>> false
[]string{"z","z","x"} == []string{"x","z","z"} >>> true
Here is an alternate solution, though perhaps a bit verbose:
func sameStringSlice(x, y []string) bool {
if len(x) != len(y) {
return false
}
// create a map of string -> int
diff := make(map[string]int, len(x))
for _, _x := range x {
// 0 value for int is 0, so just increment a counter for the string
diff[_x]++
}
for _, _y := range y {
// If the string _y is not in diff bail out early
if _, ok := diff[_y]; !ok {
return false
}
diff[_y] -= 1
if diff[_y] == 0 {
delete(diff, _y)
}
}
return len(diff) == 0
}
Try it on the Go Playground
You can use cmp.Diff together with cmpopts.SortSlices:
less := func(a, b string) bool { return a < b }
equalIgnoreOrder := cmp.Diff(x, y, cmpopts.SortSlices(less)) == ""
Here is a full example that runs on the Go Playground:
package main
import (
"fmt"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)
func main() {
x := []string{"a", "b", "c"}
y := []string{"a", "c", "b"}
less := func(a, b string) bool { return a < b }
equalIgnoreOrder := cmp.Diff(x, y, cmpopts.SortSlices(less)) == ""
fmt.Println(equalIgnoreOrder) // prints "true"
}
The other answers have better time complexity O(N) vs (O(N log(N)), that are in my answer, also my solution will take up more memory if elements in the slices are repeated frequently, but I wanted to add it because I think this is the most straight forward way to do it:
package main
import (
"fmt"
"sort"
"reflect"
)
func array_sorted_equal(a, b []string) bool {
if len(a) != len(b) {return false }
a_copy := make([]string, len(a))
b_copy := make([]string, len(b))
copy(a_copy, a)
copy(b_copy, b)
sort.Strings(a_copy)
sort.Strings(b_copy)
return reflect.DeepEqual(a_copy, b_copy)
}
func main() {
a := []string {"a", "a", "c"}
b := []string {"c", "a", "c"}
c := []string {"z","z","x"}
d := []string {"x","z","z"}
fmt.Println( array_sorted_equal(a, b))
fmt.Println( array_sorted_equal(c, d))
}
Result:
false
true
I would think the easiest way would be to map the elements in each array/slice to their number of occurrences, then compare the maps:
func main() {
x := []string{"a","b","c"}
y := []string{"c","b","a"}
xMap := make(map[string]int)
yMap := make(map[string]int)
for _, xElem := range x {
xMap[xElem]++
}
for _, yElem := range y {
yMap[yElem]++
}
for xMapKey, xMapVal := range xMap {
if yMap[xMapKey] != xMapVal {
return false
}
}
return true
}
You'll need to add some additional due dilligence, like short circuiting if your arrays/slices contain elements of different types or are of different length.
Generalizing the code of testify ElementsMatch, solution to compare any kind of objects (in the example []map[string]string):
https://play.golang.org/p/xUS2ngrUWUl
Like adrianlzt wrote in his answer, an implementation of assert.ElementsMatch from testify can be used to achieve that. But how about reusing actual testify module instead of copying that code when all you need is a bool result of the comparison? The implementation in testify is intended for tests code and usually takes testing.T argument.
It turns out that ElementsMatch can be quite easily used outside of testing code. All it takes is a dummy implementation of an interface with ErrorF method:
type dummyt struct{}
func (t dummyt) Errorf(string, ...interface{}) {}
func elementsMatch(listA, listB interface{}) bool {
return assert.ElementsMatch(dummyt{}, listA, listB)
}
Or test it on The Go Playground, which I've adapted from the adrianlzt's example.
Since I haven't got enough reputation to comment, I have to post yet another answer with a bit better code readability:
func AssertSameStringSlice(x, y []string) bool {
if len(x) != len(y) {
return false
}
itemAppearsTimes := make(map[string]int, len(x))
for _, i := range x {
itemAppearsTimes[i]++
}
for _, i := range y {
if _, ok := itemAppearsTimes[i]; !ok {
return false
}
itemAppearsTimes[i]--
if itemAppearsTimes[i] == 0 {
delete(itemAppearsTimes, i)
}
}
if len(itemAppearsTimes) == 0 {
return true
}
return false
}
The logic is the same as in this answer
I know its been answered but still I would like to add my answer. By following code here stretchr/testify we can have something like
func Elementsmatch(listA, listB []string) (string, bool) {
aLen := len(listA)
bLen := len(listB)
if aLen != bLen {
return fmt.Sprintf("Len of the lists don't match , len listA %v, len listB %v", aLen, bLen), false
}
visited := make([]bool, bLen)
for i := 0; i < aLen; i++ {
found := false
element := listA[i]
for j := 0; j < bLen; j++ {
if visited[j] {
continue
}
if element == listB[j] {
visited[j] = true
found = true
break
}
}
if !found {
return fmt.Sprintf("element %s appears more times in %s than in %s", element, listA, listB), false
}
}
return "", true
}
Now lets talk about performance of this solution compared to map based ones. Well it really depends on the size of the lists which you are comparing, If size of list is large (I would say greater than 20) then map approach is better else this would be sufficent.
Well on Go PlayGround it shows 0s always, but run this on local system and you can see the difference in time taken as size of list increases
So the solution I propose is, adding map based comparision from above solution
func Elementsmatch(listA, listB []string) (string, bool) {
aLen := len(listA)
bLen := len(listB)
if aLen != bLen {
return fmt.Sprintf("Len of the lists don't match , len listA %v, len listB %v", aLen, bLen), false
}
if aLen > 20 {
return elementsMatchByMap(listA, listB)
}else{
return elementsMatchByLoop(listA, listB)
}
}
func elementsMatchByLoop(listA, listB []string) (string, bool) {
aLen := len(listA)
bLen := len(listB)
visited := make([]bool, bLen)
for i := 0; i < aLen; i++ {
found := false
element := listA[i]
for j := 0; j < bLen; j++ {
if visited[j] {
continue
}
if element == listB[j] {
visited[j] = true
found = true
break
}
}
if !found {
return fmt.Sprintf("element %s appears more times in %s than in %s", element, listA, listB), false
}
}
return "", true
}
func elementsMatchByMap(x, y []string) (string, bool) {
// create a map of string -> int
diff := make(map[string]int, len(x))
for _, _x := range x {
// 0 value for int is 0, so just increment a counter for the string
diff[_x]++
}
for _, _y := range y {
// If the string _y is not in diff bail out early
if _, ok := diff[_y]; !ok {
return fmt.Sprintf(" %v is not present in list b", _y), false
}
diff[_y] -= 1
if diff[_y] == 0 {
delete(diff, _y)
}
}
if len(diff) == 0 {
return "", true
}
return "", false
}
I'm trying to write a function that returns the finds first character in a String that doesn't repeat, so far I have this:
package main
import (
"fmt"
"strings"
)
func check(s string) string {
ss := strings.Split(s, "")
smap := map[string]int{}
for i := 0; i < len(ss); i++ {
(smap[ss[i]])++
}
for k, v := range smap {
if v == 1 {
return k
}
}
return ""
}
func main() {
fmt.Println(check("nebuchadnezzer"))
}
Unfortunately in Go when you iterate a map there's no guarantee of the order so every time I run the code I get a different value, any pointers?
Using a map and 2 loops :
play
func check(s string) string {
m := make(map[rune]uint, len(s)) //preallocate the map size
for _, r := range s {
m[r]++
}
for _, r := range s {
if m[r] == 1 {
return string(r)
}
}
return ""
}
The benfit of this is using just 2 loops vs multiple loops if you're using strings.ContainsRune, strings.IndexRune (each function will have inner loops in them).
Efficient (in time and memory) algorithms for grabbing all or the first unique byte http://play.golang.org/p/ZGFepvEXFT:
func FirstUniqueByte(s string) (b byte, ok bool) {
occur := [256]byte{}
order := make([]byte, 0, 256)
for i := 0; i < len(s); i++ {
b = s[i]
switch occur[b] {
case 0:
occur[b] = 1
order = append(order, b)
case 1:
occur[b] = 2
}
}
for _, b = range order {
if occur[b] == 1 {
return b, true
}
}
return 0, false
}
As a bonus, the above function should never generate any garbage. Note that I changed your function signature to be a more idiomatic way to express what you're describing. If you need a func(string) string signature anyway, then the point is moot.
That can certainly be optimized, but one solution (which isn't using map) would be:
(playground example)
func check(s string) string {
unique := ""
for pos, c := range s {
if strings.ContainsRune(unique, c) {
unique = strings.Replace(unique, string(c), "", -1)
} else if strings.IndexRune(s, c) == pos {
unique = unique + string(c)
}
}
fmt.Println("All unique characters found: ", unique)
if len(unique) > 0 {
_, size := utf8.DecodeRuneInString(unique)
return unique[:size]
}
return ""
}
This is after the question "Find the first un-repeated character in a string"
krait suggested below that the function should:
return a string containing the first full rune, not just the first byte of the utf8 encoding of the first rune.