Difficulty looping over non-ASCII characters - go

I was trying to complete this coding exercise of searching palindrome strings in a bigger string, but when I run the code I have noticed that the characters that are not ASCII behave differently. The thing is I am just comparing the reverse of the string to the string to establish if is palindrome or not.
func main() {
s := "aaäabca"
sl := make([]string, 0)
for i := 0; i < len(s)-1; i++ {
for j := i + 1; j < len(s); j++ {
if Palindrome(s[i : j+1]) {
sl = append(sl, s[i:j+1])
}
}
}
fmt.Println(sl)
}
func Palindrome(s string) bool {
copyrev := ""
for _, valore := range s {
copyrev = string(valore) + copyrev
}
return copyrev == s
}
The output is :
[aa aäa ä]
But it should be:
[aa aäa]

Related

Find largest score word

package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type word struct {
str string
score int
}
func main() {
fmt.Print("Enter a string of words: ")
reader := bufio.NewReader(os.Stdin)
str, _ := reader.ReadString('\n')
strin := strings.Trim(str, "\n")
high_word := get_word(strin)
fmt.Println(high_word)
}
func get_word(in string) []word {
rune_word := strings.Split(in, " ")
stru_sl := make([]word, len(rune_word))
for i := 0; i < len(rune_word); i++ {
stru_sl[i] = word{str: rune_word[i], score: (get_score(rune_word[i]))}
}
return stru_sl
}
func get_score(in_w string) int {
var num int
score_map := make(map[string]int)
alpha := "abcdefghijklmnopqrstuvwxyz"
alpha_run := strings.Split(alpha, "")
for i, a := range alpha_run {
score_map[a] = i + 1
}
for i := 0; i < len(in_w); i++ {
if m, ok := score_map[string(in_w[i])]; ok {
num += m
}
}
return num
}
I've got the code above that gives me a list of structs corresponding to the words you put in, and its score calculated by adding up positions of each letter in the alphabet (1-26). My next step here is to find the word with the highest score. I can do the swap method and sort the structs, but what's the smartest way to achieve this?
If you want to find only the word with the highest score of course sorting isn't necessary, you can scan linearly and update what is highest on every step.
something like that:
highestScoreWord = words[0];
for i := 1; i < len(words); i++ {
if words[i].score > highestScoreWord.score {
highestScoreWord = words[i];
}
}
return highestScoreWord;

cannot assign to v[i], reference to array problem?

I am trying to solve a puzzle to practice my Go. But, I am a little stuck and the error is not very helpful.
./prog.go:22:23: cannot assign to v[j]
./prog.go:22:23: cannot assign to v[wLen - 1 - j]
func SpinWords(str string) string {
ws := strings.Split(str, " ")
for i := 0; i < len(ws); i++ {
v := ws[i]
wLen := len(v)
if wLen > 4 {
for j := 0; j < wLen/2; j++ {
v[j], v[wLen-1-j] = v[wLen-1-j], v[j]
}
ws[i] = v
}
}
return strings.Join(ws, " ")
}
Almost working code here: https://play.golang.org/p/j9BYk642bFa
You can't assign to elements of v because v is a string and strings are immutable. You can convert the string to a []byte first, and then work with the elements of it, but it is not safe if your strings contain multi-byte characters.
v:=[]byte(ws[i])
Or you can convert the string to a []rune and work with it:
v:=[]rune(ws[i])
Then you can assign to elements of v, and when you're done, convert it back to a string:
str:=string(v)
If you want to performed the action then you have to convert word from string to []rune
This code works :)
package main
import (
"fmt"
"strings"
)
func main() {
result := SpinWords("Welcome to the jungle we got fun and games")
fmt.Println(result)
}
func SpinWords(str string) string {
ws := strings.Split(str, " ")
for i := 0; i < len(ws); i++ {
v := ws[i]
wLen := len(v)
if wLen > 4 {
vinrune := []rune(v)
for j := 0; j < wLen/2; j++ {
vinrune[j], vinrune[wLen-1-j] = vinrune[wLen-1-j], vinrune[j]
}
v = string(vinrune)
ws[i] = v
}
}
return strings.Join(ws, " ")
}

Generate combinations from a given range

I'm trying to create a program capable to generate combinations from a given range.
I started editing this code below that generates combinations:
package main
import "fmt"
func nextPassword(n int, c string) func() string {
r := []rune(c)
p := make([]rune, n)
x := make([]int, len(p))
return func() string {
p := p[:len(x)]
for i, xi := range x {
p[i] = r[xi]
}
for i := len(x) - 1; i >= 0; i-- {
x[i]++
if x[i] < len(r) {
break
}
x[i] = 0
if i <= 0 {
x = x[0:0]
break
}
}
return string(p)
}
}
func main() {
np := nextPassword(2, "ABCDE")
for {
pwd := np()
if len(pwd) == 0 {
break
}
fmt.Println(pwd)
}
}
This is the Output of the code:
AA
AB
AC
AD
AE
BA
BB
BC
BD
BE
CA
CB
CC
CD
CE
DA
DB
DC
DD
DE
EA
EB
EC
ED
EE
And this is the code I edited:
package main
import "fmt"
const (
Min = 5
Max = 10
)
func nextPassword(n int, c string) func() string {
r := []rune(c)
p := make([]rune, n)
x := make([]int, len(p))
return func() string {
p := p[:len(x)]
for i, xi := range x {
p[i] = r[xi]
}
for i := len(x) - 1; i >= 0; i-- {
x[i]++
if x[i] < len(r) {
break
}
x[i] = 0
if i <= 0 {
x = x[0:0]
break
}
}
return string(p)
}
}
func main() {
cont := 0
np := nextPassword(2, "ABCDE")
for {
pwd := np()
if len(pwd) == 0 {
break
}
if cont >= Min && cont <= Max{
fmt.Println(pwd)
} else if cont > Max{
break
}
cont += 1
}
}
Output:
BA
BB
BC
BD
BE
CA
My code works, but if I increase the length of the combination and my range starts from the middle, the program will generate even the combinations that I don't want (and of course that will take a lot of time).
How can I solve this problem?
I really didn't like how nextPassword was written, so I made a variation. Rather than starting at 0 and repeatedly returning the next value, this one takes an integer and converts it to the corresponding "password." E.g. toPassword(0, 2, []rune("ABCDE")) is AA, and toPassword(5, ...) is BA.
From there, it's easy to loop over whatever range you want. But I also wrote a nextPassword wrapper around it that behaves similarly to the one in the original code. This one uses toPassword under the cover and takes a starting n.
Runnable version here: https://play.golang.org/p/fBo6mx4Mji
Code below:
package main
import (
"fmt"
)
func toPassword(n, length int, alphabet []rune) string {
base := len(alphabet)
// This will be our output
result := make([]rune, length)
// Start filling from the right
i := length - 1
// This is essentially a conversion to base-b, where b is
// the number of possible letters (5 in the case of "ABCDE")
for n > 0 {
// Filling from the right, put the right digit mod b
result[i] = alphabet[n%base]
// Divide the number by the base so we're ready for
// the next digit
n /= base
// Move to the left
i -= 1
}
// Fill anything that's left with "zeros" (first letter of
// the alphabet)
for i >= 0 {
result[i] = alphabet[0]
i -= 1
}
return string(result)
}
// Convenience function that just returns successive values from
// toPassword starting at start
func nextPassword(start, length int, alphabet []rune) func() string {
n := start
return func() string {
result := toPassword(n, length, alphabet)
n += 1
return result
}
}
func main() {
for i := 5; i < 11; i++ {
fmt.Println(toPassword(i, 2, []rune("ABCDE")))
} // BA, BB, BC, BD, BE, CA
// Now do the same thing using nextPassword
np := nextPassword(5, 2, []rune("ABCDE"))
for i := 0; i < 6; i++ {
fmt.Println(np())
} // BA, BB, BC, BD, BE, CA
}

Go : longest common subsequence to print result array

I have implemented Longest Common Subsequence algorithm and getting the right answer for longest but cannot figure out the way to print out what makes up the longest common subsequence.
That is, I succeeded to get the length of longest commond subsequence array but I want to print out the longest subsequence.
The Playground for this code is here
http://play.golang.org/p/0sKb_OARnf
/*
X = BDCABA
Y = ABCBDAB => Longest Comman Subsequence is B C B
Dynamic Programming method : O ( n )
*/
package main
import "fmt"
func Max(more ...int) int {
max_num := more[0]
for _, elem := range more {
if max_num < elem {
max_num = elem
}
}
return max_num
}
func Longest(str1, str2 string) int {
len1 := len(str1)
len2 := len(str2)
//in C++,
//int tab[m + 1][n + 1];
//tab := make([][100]int, len1+1)
tab := make([][]int, len1+1)
for i := range tab {
tab[i] = make([]int, len2+1)
}
i, j := 0, 0
for i = 0; i <= len1; i++ {
for j = 0; j <= len2; j++ {
if i == 0 || j == 0 {
tab[i][j] = 0
} else if str1[i-1] == str2[j-1] {
tab[i][j] = tab[i-1][j-1] + 1
if i < len1 {
fmt.Printf("%c", str1[i])
}
} else {
tab[i][j] = Max(tab[i-1][j], tab[i][j-1])
}
}
}
fmt.Println()
return tab[len1][len2]
}
func main() {
str1 := "AGGTABTABTABTAB"
str2 := "GXTXAYBTABTABTAB"
fmt.Println(Longest(str1, str2))
//Actual Longest Common Subsequence: GTABTABTABTAB
//GGGGGTAAAABBBBTTTTAAAABBBBTTTTAAAABBBBTTTTAAAABBBB
//13
str3 := "AGGTABGHSRCBYJSVDWFVDVSBCBVDWFDWVV"
str4 := "GXTXAYBRGDVCBDVCCXVXCWQRVCBDJXCVQSQQ"
fmt.Println(Longest(str3, str4))
//Actual Longest Common Subsequence: ?
//GGGTTABGGGHHRCCBBBBBBYYYJSVDDDDDWWWFDDDDDVVVSSSSSBCCCBBBBBBVVVDDDDDWWWFWWWVVVVVV
//14
}
When I try to print out the subsequence when the tab gets updates, the outcome is duplicate.
I want to print out something like "GTABTABTABTAB" for the str1 and str2
Thanks in advance.
EDIT: It seems that I jumped the gun on answering this. On the Wikipedia page for Longest Common Subsequnce they give the pseudocode for printing out the LCS once it has been calculated. I'll put an implementation in go up here as soon as I have time for it.
Old invalid answer
You are forgetting to move along from a character once you have registered it as part of the subsequence.
The code below should work. Look at the two lines right after the fmt.Printf("%c", srt1[i]) line.
playground link
/*
X = BDCABA
Y = ABCBDAB => Longest Comman Subsequence is B C B
Dynamic Programming method : O ( n )
*/
package main
import "fmt"
func Max(more ...int) int {
max_num := more[0]
for _, elem := range more {
if max_num < elem {
max_num = elem
}
}
return max_num
}
func Longest(str1, str2 string) int {
len1 := len(str1)
len2 := len(str2)
//in C++,
//int tab[m + 1][n + 1];
//tab := make([][100]int, len1+1)
tab := make([][]int, len1+1)
for i := range tab {
tab[i] = make([]int, len2+1)
}
i, j := 0, 0
for i = 0; i <= len1; i++ {
for j = 0; j <= len2; j++ {
if i == 0 || j == 0 {
tab[i][j] = 0
} else if str1[i-1] == str2[j-1] {
tab[i][j] = tab[i-1][j-1] + 1
if i < len1 {
fmt.Printf("%c", str1[i])
//Move on the the next character in both sequences
i++
j++
}
} else {
tab[i][j] = Max(tab[i-1][j], tab[i][j-1])
}
}
}
fmt.Println()
return tab[len1][len2]
}
func main() {
str1 := "AGGTABTABTABTAB"
str2 := "GXTXAYBTABTABTAB"
fmt.Println(Longest(str1, str2))
//Actual Longest Common Subsequence: GTABTABTABTAB
//GGGGGTAAAABBBBTTTTAAAABBBBTTTTAAAABBBBTTTTAAAABBBB
//13
str3 := "AGGTABGHSRCBYJSVDWFVDVSBCBVDWFDWVV"
str4 := "GXTXAYBRGDVCBDVCCXVXCWQRVCBDJXCVQSQQ"
fmt.Println(Longest(str3, str4))
//Actual Longest Common Subsequence: ?
//GGGTTABGGGHHRCCBBBBBBYYYJSVDDDDDWWWFDDDDDVVVSSSSSBCCCBBBBBBVVVDDDDDWWWFWWWVVVVVV
//14
}

How to compare two version number strings in golang

I have two strings (they are actually version numbers and they could be any version numbers)
a := "1.05.00.0156"
b := "1.0.221.9289"
I want to compare which one is bigger. How to do it in golang?
There is a nice solution from Hashicorp - https://github.com/hashicorp/go-version
import github.com/hashicorp/go-version
v1, err := version.NewVersion("1.2")
v2, err := version.NewVersion("1.5+metadata")
// Comparison example. There is also GreaterThan, Equal, and just
// a simple Compare that returns an int allowing easy >=, <=, etc.
if v1.LessThan(v2) {
fmt.Printf("%s is less than %s", v1, v2)
}
Some time ago I created a version comparison library: https://github.com/mcuadros/go-version
version.CompareSimple("1.05.00.0156", "1.0.221.9289")
//Returns: 1
Enjoy it!
Here's a general solution.
package main
import "fmt"
func VersionOrdinal(version string) string {
// ISO/IEC 14651:2011
const maxByte = 1<<8 - 1
vo := make([]byte, 0, len(version)+8)
j := -1
for i := 0; i < len(version); i++ {
b := version[i]
if '0' > b || b > '9' {
vo = append(vo, b)
j = -1
continue
}
if j == -1 {
vo = append(vo, 0x00)
j = len(vo) - 1
}
if vo[j] == 1 && vo[j+1] == '0' {
vo[j+1] = b
continue
}
if vo[j]+1 > maxByte {
panic("VersionOrdinal: invalid version")
}
vo = append(vo, b)
vo[j]++
}
return string(vo)
}
func main() {
versions := []struct{ a, b string }{
{"1.05.00.0156", "1.0.221.9289"},
// Go versions
{"1", "1.0.1"},
{"1.0.1", "1.0.2"},
{"1.0.2", "1.0.3"},
{"1.0.3", "1.1"},
{"1.1", "1.1.1"},
{"1.1.1", "1.1.2"},
{"1.1.2", "1.2"},
}
for _, version := range versions {
a, b := VersionOrdinal(version.a), VersionOrdinal(version.b)
switch {
case a > b:
fmt.Println(version.a, ">", version.b)
case a < b:
fmt.Println(version.a, "<", version.b)
case a == b:
fmt.Println(version.a, "=", version.b)
}
}
}
Output:
1.05.00.0156 > 1.0.221.9289
1 < 1.0.1
1.0.1 < 1.0.2
1.0.2 < 1.0.3
1.0.3 < 1.1
1.1 < 1.1.1
1.1.1 < 1.1.2
1.1.2 < 1.2
go-semver is a semantic versioning library for Go. It lets you parse and compare two semantic version strings.
Example:
vA := semver.New("1.2.3")
vB := semver.New("3.2.1")
fmt.Printf("%s < %s == %t\n", vA, vB, vA.LessThan(*vB))
Output:
1.2.3 < 3.2.1 == true
Here are some of the libraries for version comparison:
https://github.com/blang/semver
https://github.com/Masterminds/semver
https://github.com/hashicorp/go-version
https://github.com/mcuadros/go-version
I have used blang/semver.
Eg: https://play.golang.org/p/1zZvEjLSOAr
import github.com/blang/semver/v4
v1, err := semver.Make("1.0.0-beta")
v2, err := semver.Make("2.0.0-beta")
// Options availabe
v1.Compare(v2) // Compare
v1.LT(v2) // LessThan
v1.GT(v2) // GreaterThan
This depends on what you mean by bigger.
A naive approach would be:
package main
import "fmt"
import "strings"
func main() {
a := strings.Split("1.05.00.0156", ".")
b := strings.Split("1.0.221.9289", ".")
for i, s := range a {
var ai, bi int
fmt.Sscanf(s, "%d", &ai)
fmt.Sscanf(b[i], "%d", &bi)
if ai > bi {
fmt.Printf("%v is bigger than %v\n", a, b)
break
}
if bi > ai {
fmt.Printf("%v is bigger than %v\n", b, a)
break
}
}
}
http://play.golang.org/p/j0MtFcn44Z
Based on Jeremy Wall's answer:
func compareVer(a, b string) (ret int) {
as := strings.Split(a, ".")
bs := strings.Split(b, ".")
loopMax := len(bs)
if len(as) > len(bs) {
loopMax = len(as)
}
for i := 0; i < loopMax; i++ {
var x, y string
if len(as) > i {
x = as[i]
}
if len(bs) > i {
y = bs[i]
}
xi,_ := strconv.Atoi(x)
yi,_ := strconv.Atoi(y)
if xi > yi {
ret = -1
} else if xi < yi {
ret = 1
}
if ret != 0 {
break
}
}
return
}
http://play.golang.org/p/AetJqvFc3B
Striving for clarity and simplicity:
func intVer(v string) (int64, error) {
sections := strings.Split(v, ".")
intVerSection := func(v string, n int) string {
if n < len(sections) {
return fmt.Sprintf("%04s", sections[n])
} else {
return "0000"
}
}
s := ""
for i := 0; i < 4; i++ {
s += intVerSection(v, i)
}
return strconv.ParseInt(s, 10, 64)
}
func main() {
a := "3.045.98.0832"
b := "087.2345"
va, _ := intVer(a)
vb, _ := intVer(b)
fmt.Println(va<vb)
}
Comparing versions implies parsing so I believe these 2 steps should be separate to make it robust.
tested in leetcode: https://leetcode.com/problems/compare-version-numbers/
func compareVersion(version1 string, version2 string) int {
len1, len2, i, j := len(version1), len(version2), 0, 0
for i < len1 || j < len2 {
n1 := 0
for i < len1 && '0' <= version1[i] && version1[i] <= '9' {
n1 = n1 * 10 + int(version1[i] - '0')
i++
}
n2 := 0
for j < len2 && '0' <= version2[j] && version2[j] <= '9' {
n2 = n2 * 10 + int(version2[j] - '0')
j++
}
if n1 > n2 {
return 1
}
if n1 < n2 {
return -1
}
i, j = i+1, j+1
}
return 0
}
import (
"fmt"
"strconv"
"strings"
)
func main() {
j := ll("1.05.00.0156" ,"1.0.221.9289")
fmt.Println(j)
}
func ll(a,b string) int {
var length ,r,l int = 0,0,0
v1 := strings.Split(a,".")
v2 := strings.Split(b,".")
len1, len2 := len(v1), len(v2)
length = len2
if len1 > len2 {
length = len1
}
for i:= 0;i<length;i++ {
if i < len1 && i < len2 {
if v1[i] == v2[i] {
continue
}
}
r = 0
if i < len1 {
if number, err := strconv.Atoi(v1[i]); err == nil {
r = number
}
}
l = 0
if i < len2 {
if number, err := strconv.Atoi(v2[i]); err == nil {
l = number
}
}
if r < l {
return -1
}else if r> l {
return 1
}
}
return 0
}
If you can guarantee version strings have same format (i.e. SemVer), you can convert to int and compare int. Here is an implementation for sorting slices of SemVer:
versions := []string{"1.0.10", "1.0.6", "1.0.9"}
sort.Slice(versions[:], func(i, j int) bool {
as := strings.Split(versions[i], ".")
bs := strings.Split(versions[j], ".")
if len(as) != len(bs) || len(as) != 3 {
return versions[i] < versions[j]
}
ais := make([]int, len(as))
bis := make([]int, len(bs))
for i := range as {
ais[i], _ = strconv.Atoi(as[i])
bis[i], _ = strconv.Atoi(bs[i])
}
//X.Y.Z
// If X and Y are the same, compare Z
if ais[0] == bis[0] && ais[1] == bis[1] {
return ais[2] < bis[2]
}
// If X is same, compare Y
if ais[0] == bis[0] {
return ais[1] < bis[1]
}
// Compare X
return ais[0] < bis[0]
})
fmt.Println(versions)
tested in go playground
// If v1 > v2 return '>'
// If v1 < v2 return '<'
// Otherwise return '='
func CompareVersion(v1, v2 string) byte {
v1Slice := strings.Split(v1, ".")
v2Slice := strings.Split(v2, ".")
var maxSize int
{ // Make them both the same size.
if len(v1Slice) < len(v2Slice) {
maxSize = len(v2Slice)
} else {
maxSize = len(v1Slice)
}
}
v1NSlice := make([]int, maxSize)
v2NSlice := make([]int, maxSize)
{
// Convert string to the int.
for i := range v1Slice {
v1NSlice[i], _ = strconv.Atoi(v1Slice[i])
}
for i := range v2Slice {
v2NSlice[i], _ = strconv.Atoi(v2Slice[i])
}
}
var result byte
var v2Elem int
for i, v1Elem := range v1NSlice {
if result != '=' && result != 0 { // The previous comparison has got the answer already.
return result
}
v2Elem = v2NSlice[i]
if v1Elem > v2Elem {
result = '>'
} else if v1Elem < v2Elem {
result = '<'
} else {
result = '='
}
}
return result
}
Convert "1.05.00.0156" to "0001"+"0005"+"0000"+"0156", then to int64.
Convert "1.0.221.9289" to "0001"+"0000"+"0221"+"9289", then to int64.
Compare the two int64 values.
Try it on the Go playground

Resources