As an exercise to practice Go everyday, I attempt one of the daily challenges on r/dailyprogrammer, each day.
Currently, I'm implementing the intermediate challenge, #362 (https://www.reddit.com/r/dailyprogrammer/comments/8n8tog/20180530_challenge_362_intermediate_route/), which is a simple encryption/decryption challenge.
So in my approach, I have a basic struct to represent the input:
type Vector struct {
x, y int
}
type Input struct {
text string
vector Vector
method string
}
and a slice of the structs for the challenge inputs:
inputs := []Input{
{"WE ARE DISCOVERED. FLEE AT ONCE", Vector{9, 3}, "clockwise"},
{"why is this professor so boring omg", Vector{6, 5}, "counter-clockwise"},
{"Solving challenges on r/dailyprogrammer is so much fun!!", Vector{8, 6}, "counter-clockwise"},
{"For lunch let's have peanut-butter and bologna sandwiches", Vector{4, 12}, "clockwise"},
{"I've even witnessed a grown man satisfy a camel", Vector{9, 5}, "clockwise"},
{"Why does it say paper jam when there is no paper jam?", Vector{3, 14}, "counter-clockwise"},
}
So far, so good.
I have a function to simplify the input string as outlined in the challenge (ie. a function removes all punctuation and pads the string with 'X's to the length of the required grid).
After that, I feed the string into this function, to create the matrix grid:
func makeGrid(s string, v Vector) [][]byte {
g := make([][]byte, v.y, v.x)
for k, c := range s {
g[k/v.x] = append(g[k/v.x], byte(c))
}
return g
}
So for the first input for example, running the program will produce a grid like the following (strings instead of bytes included below for ease of reading):
[[W E A R E D I S C]
[O V E R E D F L E]
[E A T O N C E X X]]
However, when the program reaches this input:
{"For lunch let's have peanut-butter and bologna sandwiches", Vector{4, 12}, "clockwise"},
The following error is thrown:
panic: runtime error: makeslice: cap out of range
The same for this input:
{"Why does it say paper jam when there is no paper jam?", Vector{3, 14}, "counter-clockwise"},
I can totally get why the error is at runtime and not at compile, since there is no way for the compiler to know the size of the grid during compilation, so the panic can only occur at runtime.
What I don't understand is that is I reverse the vectors in the inputs:
{"For lunch let's have peanut-butter and bologna sandwiches", Vector{12, 4}, "clockwise"},
{"Why does it say paper jam when there is no paper jam?", Vector{14, 3}, "counter-clockwise"},
The error no longer occurs. The program runs fine.
It only occurs in situations where the x value in the vector is smaller than the y value.
Debugging and following the code through, I can't quite see why a grid with lots of short rows will throw an error, while a grid with few long rows won't.
There seem to be a couple of other answers on here that might be related, but I can't see how I should modify my method to avoid the error.
Any ideas?
As per the reply from Tim Cooper, this was a simple fix.
Just changed the make statement to use it correctly:
func makeGrid(s string, v Vector) [][]byte {
g := make([][]byte, v.y)
for k, c := range s {
g[k/v.x] = append(g[k/v.x], byte(c))
}
return g
}
Working fine now.