import (
"fmt"
)
func Rotate(s string) []string {
slice := make([]string, len(s))
for i := range s {
slice[i] = s[i:] + s[:i]
}
return slice
}
func main() {
var input string
fmt.Scan(&input)
slice := Rotate(input)
for _, element := range slice {
fmt.Println(element)
}
}```
The following code is supposed to rotate the first character to the last position and execute evert possible rotation, it works fine with the "normal letters" ( letters of the Latin alphabet ) but puts some unexpected new lines when using non-European letters such as "ŽǯƅƅŦŘ" and I was wondering why this occurs?
#BEGINNER - Acting weird when using special characters
50 messages · Page 1 of 1 (latest)
Try checking the byte format of such character, it may be because there are more than one character at the same place
you are working under the assumption that i is incremented by 1 on every iteration, this is not the case.
i will be the index of the first byte of the current code point, in this particular case it will be 0, 2, 4, ... leaving slice[1], slice[3], etc as empty strings
if you change your approach to use append instead of direct assignment you will see the expected results.
Note that the underlying issue of "a character is not a byte" is still there, there are "characters" that can be comprised of multiple code points
I'm sorry, I see what you mean but still didn't understand why from i = 0 it went to i = 2?
because a range loop over a string iterates through its code points not the bytes. Ž is one code point but it's represented as two bytes
€ for instance is encoded as 3 bytes, so if the string were a€b you'd see 0, 1, 4 where 0 is the start of a, 1 is the start of € and 4 is the start of b
I understand, from this explanation I've applied the following correction:
slice := make([]string, len(s))
for i := 0; i < len(s); i++ {
slice[i] = s[i:] + s[:i]
}
return slice
}```
that's more incorrect
see this
wow discord scrolled at once
slice := make([]string, len(s))
for i := range s {
slice = append(slice, s[i:]+s[:i])
}
return slice
}```
this way?
that's subtly incorrect, give it a try to see if you can spot your mistake
it seems that it increases the lenght of the slice instead of appending on free spots
var slice []string
for i := range s {
slice = append(slice, s[i:]+s[:i])
}
return slice
}```
like this works fine
That's the thing, there are no "free spots", a "free spot" in the context of append is the space between the length and the capacity of the slice.
You are creating a slice with N elements, then appending to it.
It's reasonable to just var slice []string if efficiency is not paramount
exactly
hmmmmm
maybe it's a dumb thought but it makes me wonder why using slice := make([]string, len(s)) instead of var slice []string
like not only in this particulare context but in general while programming in Go
if I'm saying stupid stuff don't mind me, I've just came back from an exam
and my mind is not working good
creating a slice with a >0 length or capacity is usually a matter of efficiency.
append may need to re-allocate the slice's backing array if it is too small to add another element, this is sometimes undesirable
one last thing, why using append was better than my previous approach
if you've already explained it just ignore the message
in this context, it is better to append instead of doing direct assignment because append is simpler, that's about it
you could do direct assignment, but you'd have to manage the index variable yourself
something like this
func Rotate(s string) []string {
l := len(s)
j := l - 1
slice := make([]string, l)
for i, val := range s {
slice[j-i] = string(val)
}
return slice
}
ah, range also returns the value in that position.
and this Ž letters have their own data type and it is called rune in go.
hmmm, not the right solution
did you try the code?
ŽǯƅƅŦŘ
ǯƅƅŦŘŽ
ƅƅŦŘŽǯ
ƅŦŘŽǯƅ
ŦŘŽǯƅƅ
ŘŽǯƅƅŦ
this is what I've wanted as output
your code does something else
this is not correct. Even disregarding the fact that it does not do what the OP wants to do, it is still incorrectly doing what it is doing. Any code point that is encoded as 2 or more bytes will cause the slice to have empty values
func Rotate(s string) []string {
l := len(s)
slice := make([]string, l)
for i, val := range s {
if i == 0 {
slice[l-1] = string(val)
continue
}
slice[i-1] = string(val)
}
return slice
}
this works
it does not
the length of a string is the amount of bytes it encodes as, not the number of code points it contains
this isn't accurate, a rune represents a unicode code point, anything that is a unicode code point is a valid rune (in the conceptual sense) be it a or Ž
I'd encourage you both to read https://go.dev/blog/strings it goes into a fair bit of detail about the intricacies of characters, strings, unicode etc
the problem with the Rotate function remains, namely #1072891182729932800 message
you're just hiding it with strings.Join
given this has led to an unprompted discussion this is a correct, albeit not recommended by me, solution go func Rotate(s string) []string { slice := make([]string, len(s)) var n int for i := range s { slice[n] = s[i:] + s[:i] n++ } return slice[:n] }
My recommendation remains: use append