Each character just after its consecutive occurrences - algorithm

I'm solving this problem using Go:
https://www.geeksforgeeks.org/printing-frequency-of-each-character-just-after-its-consecutive-occurrences/
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
str := "GeeeEEKKKss"
strArr := strings.Split(str, "")
for i := 0; i < len(strArr); i++ {
count := 1
nxtIdx := i + 1
for nxtIdx < len(strArr) && strArr[nxtIdx] == strArr[i] {
i++
count++
}
fmt.Print(strArr[i], strconv.Itoa(count))
}
fmt.Println()
}
When I'm directly using i+1 in place of "nxtIdx" variable, I'm getting expected result
: G1e3E2K3s2
https://play.golang.org/p/wJBpNbIzlNd
But when I'm using "nxtIdx" variable, I'm getting unexpected result
: G1E4E1s4s1
https://play.golang.org/p/g8hejYTv2-0

Because you do not increment nxtIdx inside the loop that affects loop iteration.
nxtIdx := i + 1
for nxtIdx < len(strArr) && strArr[nxtIdx] == strArr[i] {
i++ // Here
count++
}
You should increment the nxtIdx also
nxtIdx := i + 1
for nxtIdx < len(strArr) && strArr[nxtIdx] == strArr[i] {
i++
nxtIdx++
count++
}

Related

What is the correct terminating condition for swapping in bubble sort?

I am learning golang, and I am trying to work through writing bubblesort and working with pointers.
package main
import (
"fmt"
"math/rand"
)
func main() {
testTwo := make([]int, 10)
for i := 0; i <= len(testTwo)-1; i++ {
fmt.Print("\n")
testTwo[i] = rand.Intn(10)
}
for i := 0; i <= len(testTwo)-1; i++ {
for j := i + 1; j <= len(testTwo)-1; j++ {
testTwo[i], testTwo[i+1] = swap(testTwo[i], testTwo[i+1])
}
}
}
/*
Swaps the pointers of two adjacent elements in an array
*/
func swap(valOne, valTwo int) (int, int) {
valAddress := &valOne
valAddressTwo := &valTwo
if valOne <= valTwo {
temp_address := *valAddressTwo
*valAddressTwo = valOne
*valAddress = temp_address
} else {
temp_address := *valAddress
*valAddress = valTwo
*valAddressTwo = temp_address
}
return valOne, valTwo
}
This is an example of what is being done so far. The input slice might be
[4 1 2 9 8 4 1 5 7 6]. But it stops short of sorting everything.[1 4 9 2 4 8 5 1 6 7]. Is there another condition I should add or is there something wrong with how I am using the pointers in the swap function?
package main
import (
"fmt"
"math/rand"
)
func main() {
testTwo := make([]int, 10)
for i := 0; i <= len(testTwo)-1; i++ {
fmt.Print("\n")
testTwo[i] = rand.Intn(10)
}
for i := 0; i <= len(testTwo)-1; i++ {
for j := i + 1; j <= len(testTwo)-1; j++ {
if testTwo[i] > testTwo[j] {
// here we swap pointers
testTwo[i], testTwo[j] = swap(testTwo[i], testTwo[j])
}
}
}
fmt.Print(testTwo)
}
/*
GO always sends arguments by value. Pointers cannot be swapped here, unless we use *int
*/
func swap(valOne, valTwo int) (int, int) {
if valOne <= valTwo {
return valOne, valTwo
} else {
return valTwo, valOne
}
}
You forgot to compare 2 variables and you have mistaken using i+1 instead of j.
for i := 0; i <= len(testTwo)-1; i++ {
for j := i + 1; j <= len(testTwo)-1; j++ {
if testTwo[i] < testTwo[j] {
testTwo[i], testTwo[j] = swap(testTwo[i], testTwo[j])
}
}
}

why does bufio.NewReader does not work proprely when input come from redirection?

I am currently trying to solve this challenge on the website CodeChef when entering input manually I get the expected answer for the problem like stated in the problem.
But when I tried to use cat in.txt | go run my_program.go the output from my program is different.
As you can see I tried to debug using fmt.Printf and it look like bufio.NewReader randomly miss the input from the pipe.
I would like to know what I am doing wrong and if there are alternative approach to read a whole line containing multiple integrers in Golang.
Thanks you for helping me !
content of in.txt :
4
3
1 2 3
3
3 2 1
3
0 0 0
3
1 3 2
normal output when entering input manually :
1 1
3 3
1 1
1 2
output with debug message when entering text using cat in.txt | go run my_program.go
debug <1 2 3
>
1 1
debug <>
1 1
debug <>
1 1
debug <>
1 1
my program :
package main
import (
"fmt"
"os"
"strings"
"bufio"
"strconv"
)
func main() {
t, n := 0, 0
fmt.Scanf("%d", &t)
for i := 0; i < t; i++ {
fmt.Scanf("%d\n", &n)
v := make([]int, n)
rd := bufio.NewReader(os.Stdin)
text, _ := rd.ReadString('\n')
fmt.Printf("debug <%s>\n", text)
arr := strings.Split(strings.TrimSuffix(text, "\n"), " ")
for k := 0; k < len(arr); k++ {
v[k], _ = strconv.Atoi(arr[k])
}
fmt.Println(calc_intersect(v))
}
}
func calc_intersect(v []int) (int, int) {
smt, lgt := 100, 0
scenario := make([]int, len(v))
for sc := 0; sc < len(v); sc++ {
infect := make([]bool, len(v))
infect[sc] = true
scenario[sc] = simulate(v, infect)
}
for i := 0; i < len(scenario); i++ {
if scenario[i] <= smt {
smt = scenario[i]
}
if scenario[i] > lgt {
lgt = scenario[i]
}
}
return smt, lgt
}
func simulate(v []int, infect []bool) int {
var nb_inf int = 1
pos := make([]int, len(v))
for time := 0; time < 25; time++ {
for p := 0; p < len(v); p++ {
pos[p] = (v[p] * time) + p
}
for a := 0; a < len(v); a++ {
check_intersect(pos, infect, &nb_inf, a)
}
}
return nb_inf
}
func check_intersect(pos []int, infect []bool, nb_inf *int, a int) {
for b := 0; b < len(pos); b++ {
if a == b {
continue
}
if pos[a] == pos[b] && (infect[a] || infect[b]) && !(infect[a] && infect[b]) {
*nb_inf += 1
infect[a], infect[b] = true, true
}
}
}
Your use of bufio.NewReader is wrong. You create a new buffered reader each time through the i loop. The reader may read ahead if input is available, and when you don't re-use the reader that buffered input is unused.
Simply move rd := bufio.NewReader(os.Stdin) outside of the loop to fix the problem.
Your code works when you read from the console via stdin because you can't type fast enough for the reader to try to buffer input.

How to write to the console before a function panics?

In C you can use the function write() from the unistd.h library.
write() is faster than printf(), and allows you to write to the standard output (or a file) before a Segfault breaks your code.
When debugging, I wish to write to the standard output before my Go code panics. In general, how do I do that?
I have the following code (to find the shortest word in a string of words) which is panicking and I want to isolate where, by inserting write methods.
func FindShort(s string) int {
i := 0
j := 0
min := math.MaxInt32
for true {
for s[i] == ' ' {
i++
j++
}
for s[j] != ' ' && j < len(s) {
j++
}
if j > i && (j - i) < min {
min = j - i
}
i = j
if j == len(s) {
break
}
}
return min
}
you could use a defered function that calls the recover function, the function below will result in "Recovered panic here"
defer func() {
r := recover()
if r != nil {
fmt.Println("Recovered", r)
}
}()
panic("panic here")
Your code checks all lines if it contains a space, but it isn't checking if the line ends (end of line / end of file / line feed). There is a easier way to check what the shortest word is :
package main
import (
"fmt"
"math"
"strings"
)
func main() {
min := math.MaxInt32
shortest := math.MaxInt32
s := strings.Split("this is a test", " ")
for key, value := range s {
if len(value) < min {
min = len(value)
shortest = key
}
}
fmt.Print(s[shortest])
}

Passing a 2D slice to a Golang function argument

I'm trying to scan a matrix from the stdin and simply print it using following code.
package main
import (
"fmt"
)
func print2D(arr [][]int) {
for i:=0; i< len(arr); i++{
for j := 0; j< len(arr[0]); j++{
fmt.Printf("%d ", arr[i][j])
}
fmt.Println()
}
}
func main() {
var arr [6][6]int
for i:= 0 ; i < 6 ;i++ {
for j := 0; j< 6; j++{
fmt.Scanf("%d", &arr[i][j])
}
}
print2D(arr[:])
}
It throws the following error
./main.go:23: cannot use arr[:] (type [][6]int) as type [][]int in
argument to print2D
Is there a way to pass a 2D slice without defining sizes in the function arguments?
Try to write the data directly to the slice and pass it later to the function. Remember array and slices are different types. Moreover, the type [3]int is also different from [4]int (size matters).
package main
import (
"fmt"
)
func print2D(arr [][]int) {
for i := 0; i < len(arr); i++ {
for j := 0; j < len(arr[0]); j++ {
fmt.Printf("%d ", arr[i][j])
}
fmt.Println()
}
}
func main() {
var arr [][]int
for i := 0; i < 6; i++ {
tmp := make([]int, 6)
for j := 0; j < 6; j++ {
fmt.Scanf("%d", &tmp[j])
}
arr = append(arr, tmp)
}
print2D(arr)
}

Golang Calculator -- Can't divide by 0 error

I'm actually in a bit of a trouble...
I have a calculator, but when I want to divide nubers with them, I have a panic err saying that you can't divide by 0.
Well, I know that in maths we can't divide by 0, but I don't put 0 in my ints.
Any idea of the problem ?
Here is the code :
package main
import (
"fmt"
"os"
"strconv"
)
func mult(nums ...int) {
result := 0
total := 1
for _, num := range nums {
result = total * num
total = result
}
fmt.Println(result)
}
func add(nums ...int){
result := 0
total := 0
for _, num := range nums {
result = total + num
total = result
}
fmt.Println(result)
}
func sub(nums ...int){
result := 0
total := 0
for _, num := range nums {
result = num - total
total = result
}
fmt.Println(result)
}
func div(nums ...int){
result := 1
total := 1
for _, num := range nums {
result = num / total
total = result
}
fmt.Println(result)
}
func main() {
var d [] int
var args= os.Args[1:]
nums := make([]int, len(args))
for i := 0; i < len(args); i++ {
nums[i], _ = strconv.Atoi(args[i]);
strconv.Atoi(args[i])
d = append(d, nums[i])
}
num := d
if os.Args[1] == "*"{
mult(num...)
} else if os.Args[1] == "+"{
add(num...)
} else if os.Args[1] == "-"{
sub(num...)
} else if os.Args[1] == "/"{
div(num...)
} else {
fmt.Println("Well well well, you didn't entered a right operand ! Try with +, -, /, or * between double quotes")
}
}
The command I want to run this go code is :
go run calc.exe / 3 2 [Infinite args,...]
If your first parameter will always be a operator select, you can do something like that in your main func, you have a two problems in your main, you are ignoring the convertion error of a string to int and then this index of your array are setted with 0, and you are defining the array larger than you need because your first parameter it's not a number to your div func
nums := make([]int, len(args)-1)
for i := 0; i < len(args); i++ {
ret, errAtoi := strconv.Atoi(args[i])
if errAtoi != nil {
fmt.Println(errAtoi.Error())
} else {
nums[i-1] = ret
d = append(d, nums[i-1])
}
}

Resources