Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Solving the Baseball Game in Go
Munene Ndereba
Munene Ndereba

Posted on

     

Solving the Baseball Game in Go

Below is an interpretation of how to solve the Baseball Game Challenge in Go. Below are the instructions:

You are keeping score for a baseball game with strange rules. The game consists of several rounds, where the scores of past rounds may affect future rounds' scores.
At the beginning of the game, you start with an empty record. You are given a list of strings ops, where ops[i] is the ith operation you must apply to the record and is one of the following:

  1. An integer x - Record a new score of x.
  2. "+" - Record a new score that is the sum of the previous two scores. It is guaranteed there will always be two previous scores.
  3. "D" - Record a new score that is double the previous score. It is guaranteed there will always be a previous score.
  4. "C" - Invalidate the previous score, removing it from the record. It is guaranteed there will always be a previous score.Return the sum of all the scores on the record.

Here is how I solved the challenge in Go. Below are the test cases to help us check our answer.

  1. Given input as{"1"} should return1
  2. Input:{"5", "2", "C", "D", "+"}. Output:30
  3. Input:{"5", "-2", "4", "C", "D", "9", "+", "+"}. Output:27

In themain.go file, we create a function that takes a string slice as a parameter and returns an int representing the sum of the resulting slice of scores.

package mainfunc main(){}func CalculatePoints(ops []string) int {    var res int = 0    return res}
Enter fullscreen modeExit fullscreen mode

Second, we need to do the following:

  • Loop through the slice
  • For every operator, perform the necessary operation
  • Append the result to a new slice of numbers
  • From the resulting slice of numbers, return their sum

Let's take the first step. We declare a new slice to hold our numbers.

numbers := []int{}for i, op := range ops {    switch op {        }}
Enter fullscreen modeExit fullscreen mode

We check for each condition and then append the result to the numbers as shown below.

  • If the operator is a+, the position will be held by a number that is the result of adding the previous two numbers
  • If the operator is aD, we will double the previous number
  • The default expectation is that this is a normal number which we will append to the list
case "+":    numbers = append(numbers, numbers[i-1]+numbers[i-2])case "D":    numbers = append(numbers, numbers[i-1]*2)default:    num, _ := strconv.Atoi(op)    numbers = append(numbers, num)
Enter fullscreen modeExit fullscreen mode

Notice that there is one condition missing. But for the three other conditions, this should work. Given an input for instance:{"5", "2", "D", "+"}, we get expect17.

Let's add the loop to sum, so we can test with the sample above:

for _, num := range numbers {    res += num}
Enter fullscreen modeExit fullscreen mode

In themain function, let's call our function with the above sample. Running the code withgo run . should give17

func main() {    ops := []string{"5", "2", "D", "+"}    fmt.Println(CalculatePoints(ops))}
Enter fullscreen modeExit fullscreen mode

Let's now consider the unimplemented condition where we haveC, which should delete the previous number from the slice. Given the following sample{"5", "2", "C", "D", "+"}, we expect the output slice of numbers to look like this{5, 10, 15}:

  • First, add the number 5 to the slice, resulting in{5}
  • Add 2, resulting in{5, 2}
  • "C" means we remove the previous number, hence, our slice now looks like{5}
  • "D" means we double the previous number, resulting in{5, 10}
  • "+" means we add the previous two numbers, resulting in{5, 10, 15}
  • The sum of the elements in the resulting slice would give30Now, note that the operation "C" actually reduces the length of the numbers slice, so that while theops slice haslen of 5, our slice ofnumbers has only 3. This means that the result of "C" actually deletes its own position, as well as the previous position, reducing the length by 2.

Below is the updated function:

numbers := []int{}removed, j := 0, 0for i, op := range ops {    j = i - removed    switch op {    case "+":        numbers = append(numbers, numbers[j-1]+numbers[j-2])    case "D":        numbers = append(numbers, numbers[j-1]*2)    case "C":        numbers = numbers[:j-1]        removed += 2    default:        num, _ := strconv.Atoi(op)        numbers = append(numbers, num)    }}
Enter fullscreen modeExit fullscreen mode

We add two int variablesremoved andj initialized to0.removed will hold how many positions have been removed by the "C" operation. For every "C" operation, two positions are removed from thenumbers slice.j holds the current position of the numbers slice. The value ofj is the result of subtracting the current value ofi with the number of positionsremoved. If no position has beenremoved,i andj will have the same value.

Note that the othercases have also been updated to now usej, otherwise we would have anout of bounds index error.

Testing with the test cases now gives the correct results. The full code filemain.go now looks like below:

package mainimport (    "fmt"    "strconv")func CalculatePoints(ops []string) int {    var res int = 0    numbers := []int{}    removed, j := 0, 0    for i, op := range ops {        j = i - removed        switch op {        case "+":            numbers = append(numbers, numbers[j-1]+numbers[j-2])        case "D":            numbers = append(numbers, numbers[j-1]*2)        case "C":            numbers = numbers[:j-1]            removed += 2        default:            num, _ := strconv.Atoi(op)            numbers = append(numbers, num)        }    }    for _, num := range numbers {        res += num    }    return res}func main() {    ops := []string{"5", "2", "C", "D", "+"}    fmt.Println(CalculatePoints(ops))}
Enter fullscreen modeExit fullscreen mode

Let's add some tests. Create a file calledmain_test.go and paste the following code:

package mainimport (    "fmt"    "testing")func TestCalculatePoints(t *testing.T) {    var tests = []struct {        ops []string        sum int    }{        {[]string{"5", "2", "C", "D", "+"}, 30},        {[]string{"1"}, 1},        {[]string{"5", "-2", "4", "C", "D", "9", "+", "+"}, 27},    }    for i, test := range tests {        ops := test.ops        sum := test.sum        testname := fmt.Sprintf("running test %d", i)        t.Run(testname, func(t *testing.T) {            res := CalculatePoints(ops)            if res != sum {                t.Errorf(`Calculate Points(%s), expected result to be %d, got %d`, ops, sum, res)            }        })    }}
Enter fullscreen modeExit fullscreen mode

To execute the tests, run the following:go test -v . All the tests should pass.

The full source of the solution can be found on GitHubBaseball Game.

Thanks for reading. Leave a comment on any optimizations you suggest. Let's go!

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Some comments may only be visible to logged-in visitors.Sign in to view all comments.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I code
  • Location
    Nairobi, Kenya
  • Education
    Africa Nazarene University; University of Maryland, College Park
  • Work
    Senior Temenos T24 Application Specialist
  • Joined

Trending onDEV CommunityHot

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp