Day 1: Not Quite Lisp (Part 1)

Damien Sedgwick - Aug 28 '22 - - Dev Community

Today we are going to take a look at solving "Not Quite Lisp" - The first problem from Advent of Code 2015. We are going to do this, using Test Driven Development.

For those of you who have not heard of Advent of Code before, you can read more about it here: About Advent of code

In short, it is an annual event that publishes fun, holiday-themed puzzles every day from December 1 to December 25. Thousands of people each year take part in Advent of Code.

First things first, lets take a look at the problem.

--- Day 1: Not Quite Lisp ---

Santa was hoping for a white Christmas, but his weather
machine's "snow" function is powered by stars, and he's
fresh out!

To save Christmas, he needs you to collect fifty stars
by December 25th.

Collect stars by helping Santa solve puzzles. Two puzzles
will be made available on each day in the Advent calendar;
the second puzzle is unlocked when you complete the first.
Each puzzle grants one star. Good luck!

Here's an easy puzzle to warm you up.

Santa is trying to deliver presents in a large apartment
building, but he can't find the right floor - the directions
he got are a little confusing. He starts on the ground floor
(floor 0) and then follows the instructions one character
at a time.

An opening parenthesis, (, means he should go up one floor,
and a closing parenthesis, ), means he should go down
one floor.

The apartment building is very tall, and the basement is
very deep; he will never find the top or bottom floors.

For example:

    (()) and ()() both result in floor 0.
    ((( and (()(()( both result in floor 3.
    ))((((( also results in floor 3.
    ()) and ))( both result in floor -1.
    ))) and )())()) both result in floor -3.

To what floor do the instructions take Santa?
Enter fullscreen mode Exit fullscreen mode

With every problem, there is an accompanying puzzles input. The input for this problem is below.

()()(()()()(()()((()((()))((()((((()()((((()))()((((())(((((((()(((((((((()(((())(()()(()((()()(()(())(()((((()((()()()((((())((((((()(()(((()())(()((((()))())(())(()(()()))))))))((((((((((((()())()())())(())))(((()()()((((()(((()(()(()()(()(()()(()(((((((())(())(())())))((()())()((((()()((()))(((()()()())))(())))((((())(((()())(())(()))(()((((()())))())((()(())(((()((((()((()(())())))((()))()()(()(()))))((((((((()())((((()()((((()(()())(((((()(()())()))())(((()))()(()(()(()((((()(())(()))(((((()()(()()()(()(((())())(((()()(()()))(((()()(((())())(()(())())()()(())()()()((()(((()(())((()()((())()))((()()))((()()())((((()(()()(()(((()))()(()))))((()(((()()()))(()(((())()(()((()())(()(()()(()())(())()(((()(()())()((((()((()))))())()))((()()()()(())()())()()()((((()))))(()(((()()(((((((())()))()((((()((())()(()())(())()))(()(()())(((((((())))(((()))())))))()))())((())(()()((())()())()))))()((()()())(())((())((((()())())()()()(((()))())))()()))())(()()()(()((((((()()))())()))()(((()(((())((((()()()(()))())()()))))())()))())((())()())(((((())())((())())))(((())(((())(((((()(((((())(()(()())())(()(())(()))(()((((()))())()))))())))((()(()))))())))(((((())()))())()))))()))))(((()))()))))((()))((()((()(()(())()())))(()()()(())()))()((((())))))))(())(()((()()))(()))(()))(()((()))))))()()((((()()))()())()))))))()()()))(()((())(()))((()()()())()(((()((((())())))()((((()(()))))))())))()()())()))(()))))(()())()))))))((())))))))())()))()((())())))(()((()))()))(())))))(()))()())()()))((()(()))()()()()))))())()()))())(())()()))()))((()))))()()(()())))))()()()))((((()))()))))(()(())))(()())))((())())(()))()))))()())))()())()())))))))))()()))))())))((())((()))))())))(((()())))))))(()))()()))(()))()))))()())))))())((((()())))))))())))()()))))))))()))()))))()))))))(())))))))))())))))))))))))))())())((())))))))))()))((())))()))))))))())()(()))))))())))))()()()())()(()()()(()())(()))()()()(()())))())())))()))))())))))))()()()()())(())())()())()))))(()()()()()))))()))())())))((()())()())))()))()))))(()())))()))))))))(((()))()()))))))))))))))))))))(()))(()((()))())))())(()))(()(()(())))))()(()))()))()()))))))))))))()((()())(())())()(())))))())()())((()()))))(()()))))())()(())()))))))))))))))))))))()))(()(()())))))))()()((()))()))))))((())))()))))))))((()))())()()))())()()))((()))())))))))))))(()())()))(())((()(()()))(()())(())))()())(()(())()()))))()))()(()))))))(()))))))))))(()))())))))))))())))))())))(())))))()))))(())())))))))))()(()))))()())))())(()))()())))))))))))))())()()))))()))))))())))))()))))(())(()()()()((())()))())(()))((())()))())())(())(()()))))()))(())()()((())(())))(())))()))())))))))))()(((((())())))(())()))))(())))((()))()(((((((()))))()()))(())))))()(()))))(()()))()))())))))))(()())()))))))))())))(()))())()))(())()((())())()())())(()(()))))()))))))((()())(())()()(()())))()()))(())(())(()))())))()))(()))()()))((((()))))()))((()()()))))()))()))())))(()))()))))(())))()))())()(()))()())))())))))))())))())))()()))))))(()))())())))()))()()())())))))))))))))())))()))(()()))))())))())()(())))())))))))))))))))))()()())())))))()()()((()(()))()()(())()())()))()))))()()()))))))((()))))))))()(()(()((((((()()((()())))))))))))()))())))))((())())(()))())))())))))())()()())(())))())))()())())(())))))))()()(())))()))())))())())())()))))))))()))(()()()())())())))(())())))))))()()())()))))())))())()(())())))))))()())()))(()()(())())))()(()((()()((()()(((((())(()())()))(())()))(())))(())))))))()))()))((()))()))()))))))))()))))))))((()()())(()))(((()))(())))()))((())(((())))()())))())))))((())))))(())())((((((())())()(()))()(()((()())))((())()(()(()))))(())(()()())(())))())((()(((())())))(((()())())))())()(())())((((()()))))())((()))()()()()(())(((((((()()()((()))())(()())))(())())((((()()(()))))()((())))((())()))()(((()))())))()))((()(()))(())(()((((())((((()()(()()))(((())(()))))((((()(()))(())))))((()))(()))((()(((()(()))(()(()((()(())(()(()(()(()()((()))())(((())(()(()))))(()))()()))(())))(())()(((())(()))()((((()()))))())(()))))((())()((((()(((()))())())(((()))()())((())(())())(())()(())()(()()((((((()()))))()()(((()()))))()())()(((()(()))(()(()())(()(()))))(((((()(((())())))))(((((()((()()((())())((((((()(())(()()((()()()()()()()(()()))()(((()))()))(((((((())(((()((()())()((((())(((()(())))()((()(()()()((())((()())()))()))())))())((((((()))(()(()()()))(()((()(()(()))()((()(((()()()((())(((((())()(()))())())((()(())))(()(()())(())((())())())(((()()()(())))))())(()))))))()))))))())((()()()))((()((((((()))(((()((((()()()(((()))())()(()()(((()((()()()()())()()))()()()(()(())((()))))(()))())))))))()(()()(((((())()(()(((((()((()(()()())(()((((((((()((((((())()((((()()()((()((()((((((()))((())))))))())()))((()(()))()(()()(()((())((()()((((((((((((()())(()()()))((((()((((((())(()))())(()()((()()))()(((((((()((()()((((((()(((())))((())))((((((((()()(((((((())(((((()())(((())((())()((((()(((((((()(()(((()((((((()(((()(((((((((((()()((()()(()))((()()(((()(((())))((((())()(()(((())()(()(((())(((((((((((()))())))((((((())((()()((((()())())((((()()))((())(((((()(()()(()()()((())(()((()()((((()(((((()((()(()((((()())((((((()(((((()()(()(()((((())))(())(())(())((((()(()()((((()((((()()((()((((((())))(((((()))))()))(()((((((((()(((())())(((())))(()(()((())(((()((()()(((((()((()()(((())()(()))(((((((())(()(((((()))((()((()((()))(())())((((()((((())()(()))(((()(((((((((((((((())(((((((((()))(((()(()()()()((((((()((())()((((((((()(())(((((((((((()(()((())()((()()(()(()()((((()()((())(()((()()(()()((((()(((((((())))((((())(())()(((()()((()()((((()((()(((()((())(((()()()((((()((((()()(()(()((((((((())(()(((((())(()())(((((((()())()(()((((()((())(()()())((((()()(((()((((())(())(()()(((((((((()()))()(((())(()(()((((((())(()()())(()))()()(((()(((()((())(()(((((((()(()(()((()(((((()(()((()(()((((((()((((()()((((()(((()((())(()(()((()()((((()()(())()(())(((())(()((((((((()())(((((((((()(())()((((())))()))()()(((((()()((((((())(()()(((()(()(((((((()(()(((((((())(())((((()((()(())))((((()()())(()))((()())((((()(((((()(()(())(()(()()())(((((()(((((()((((()()((((((((()()))(()((((((())((((())()(()(((()()()(((()(()(())(())(((((()(())())((((())(())(()(((()(((((())((((())())((()(((((((()(((())(()(()))(((((((((()((()((()()(()((((())(((()((())((((())(()(((()(((()(()((((()(((())(()(((()(()()(()(()((()()(()())(())())((()(()(((()(((()(((()()(((((((((()(((((((((()()(((()(((()())((((()(()(((()()()((())((((((((((())(()(((()((((()())((((()((()))(((()()()(((((()(((((((())((()())(()((((())((((((((())(()((()((((((((((()()((()((()()))(((()())()())()(((()())()()(()(()(((((((())()))(())()))())()()((())()((()((((()((()((())(((((()((((((()(())))(()))())(((()))((()()(()(((()))((((())()(((()))))()(()(())()(((((())(()(()(())(())()((()()()((((()(())((()())(()(()))(()(()(()()(())()()(()((())()((()))))()))((()(()()()()((()())(()))())()(()(((((((((())())((()((()((((((())()((((())(((())((()(()()()((())(()((())(((()((((()()((()(()(((((())()))()((((((()))((())(((()()))(((())(())()))(((((((())(())())()(())(((((()))()((()))()(()()((()()()()()())(((((((
Enter fullscreen mode Exit fullscreen mode

My first impressions are that this challenge is fairly simple, we need to start at 0 and depending on each character of the string, increment or decrement by 1.

So lets get started.

We are going to write two functions. One that increments by 1 and one that decrements by 1.

Before we do that however, we are going to write two tests, one for each of the above functions.

func TestIncrementByOne(t *testing.T) {
    assert.Equal(t, 1, IncrementByOne(0))
    assert.Equal(t, 200, IncrementByOne(199))
    assert.Equal(t, 0, IncrementByOne(-1))
}

func TestDecrementByOne(t *testing.T) {
    assert.Equal(t, 0, DecrementByOne(1))
    assert.Equal(t, 199, DecrementByOne(200))
    assert.Equal(t, -1, DecrementByOne(0))
}
Enter fullscreen mode Exit fullscreen mode

If we try to run these tests, we are going to see that they fail.

# github.com/damiensedgwick/aoc2015/day_1 [github.com/damiensedgwick/aoc2015/day_1.test]
./main_test.go:9:21: undefined: IncrementByOne
./main_test.go:10:23: undefined: IncrementByOne
./main_test.go:11:21: undefined: IncrementByOne
./main_test.go:15:21: undefined: DecrementByOne
./main_test.go:16:23: undefined: DecrementByOne
./main_test.go:17:22: undefined: DecrementByOne
FAIL    github.com/damiensedgwick/aoc2015/day_1 [build failed]
Enter fullscreen mode Exit fullscreen mode

This is because the code to make the tests pass, does not exist.

So the next step is to create the two functions I mentioned earlier.

func IncrementByOne(n int) int {
    return n + 1
}

func DecrementByOne(n int) int {
    return n -1
}
Enter fullscreen mode Exit fullscreen mode

Very simple stuff, lets run the tests again.

PASS
ok      github.com/damiensedgwick/aoc2015/day_1 0.177s
Enter fullscreen mode Exit fullscreen mode

Perfect!

Next up, I think we could really do with a function that takes a string, and turns it into a string slice so that we are able to iterate over it.

As always, we will write the test first.

func TestCreateStringSlice(t *testing.T) {
    assert.Equal(t, []string{
        "a",
        "b",
        "c",
        "d",
        "e",
        "f",
    }, CreateStringSlice("abcdef"))
}
Enter fullscreen mode Exit fullscreen mode

Running the tests will now cause a failure, so we need to write a function to make our new test pass.

func CreateStringSlice(str string) []string {
    return strings.Split(str, "")
}
Enter fullscreen mode Exit fullscreen mode

Great, another passing test!

At the top of main.go, I created a quick function to load the input of a text file, I could have just pasted the string straight into the file but I wanted to keep it as tidy as possible.

That function is below.

func LoadInput(path string) string {
    input, err := os.ReadFile(path)
    if err != nil {
        log.Fatal(err)
    }

    return string(input)
}
Enter fullscreen mode Exit fullscreen mode

So now that we have all of the pieces we need to attempt the problem, lets add the pieces together and iterate over the string slice to see if we can generate the correct result.

In our main function, we can write.

func main() {
    var result = 0

    input := LoadInput("./input.txt")
    slice := strings.Split(input, "")

    for _, v := range slice {
        switch v {
        case "(":
            result = IncrementByOne(result)
        case ")":
            result = DecrementByOne(result)
        }
    }

    fmt.Println(result)
}
Enter fullscreen mode Exit fullscreen mode

Now if we run go run main.go we get 280 as the result. Entering 280 in to Advent of Code for this problem gives us the correct result.

That's the right answer! You are one gold star closer to powering the weather machine. [Continue to Part Two]
Enter fullscreen mode Exit fullscreen mode

I'll be looking to complete part 2 in the coming days as well as other Advent of Code problems.

. . . . . . . . . . . . . . . . . . . . . .