At first, it looks pretty easy, but then I ended up inside the rabbit hole, for example, should it also work for strings pasted below as well? Don’t worry, only test examples are blurred.
@examples = [
{
string: "aabb",
expected: 1,
},
{
string: "aaaabbbb",
expected: 6,
},
{
string: "aaab",
expected: -1,
},
# Extra examples
{
string: "baaa",
expected: -1,
},
{
string: "ab",
expected: 0,
},
{
string: "aab",
expected: 1,
},
{
string: "aabbb",
expected: 3,
},
{
string: "aaabb",
expected: 3,
},
{
string: "aabbaabab",
expected: 3,
},
]
I managed to have code to pass all but the last example, and I also managed to not read your solution @eayurt—and I am also on the brink of consulting with the AI, as this seems like a real-world problem that somebody somewhere somehow most definitely solved.
BTW, maybe it would be cool to use “Blur spoiler” functionality of this forum platform to blur the solution code (like I did with the code above) or put code inside “Hide details” (like I did with the solution code below)?
I instinctively (hard)coded this, but I have a feeling that there is some kind of more general pattern hidden inside this…will cook it up for a few more days to see if some Eureka will show up… 
SOLUTION! UNHIDE AT YOUR OWN RISK! :P
def min_swaps_to_alternate(string)
chars = string.chars
iterate = string.size - 1
swaps = 0
string.size.times
iterate.times do |index|
next unless chars[index] != chars[index + 1] &&
(chars[index + 1] == chars[index + 2] ||
(chars[index + 2].nil? && chars[index] == chars[index - 1]))
chars[index], chars[index + 1] = chars[index + 1], chars[index]
swaps += 1
next unless index > 1 && chars[index - 1] == chars[index - 2] && chars[index] != chars[index - 1]
chars[index], chars[index - 1] = chars[index - 1], chars[index]
swaps += 1
end
iterate -= 1
end
chars[0] == chars[1] ? -1 : swaps
end