Prepare for your live coding test!

Your technical interview at Upvest

So you made it to the first major stage of our interview process? Great, our tech folks are happy to meet you soon!

As you may know by now, we will have a 30 Minute-long live coding session as part of the interview. You won’t need to complete any tasks or do any homework before the session but, we can offer you these hints to give you a head start and ensure a smooth, fun session.

Code sharing setup

Go. Most of our tech roles require some Go experience. So please ensure you have go installed and working on the command line. You should have run your first main.go using go run main.go and it may help to know your way around go mod too.

IDE. We use Goland and VSCode for Go development but are happy to see you do some magic in vim, or whatever editor you prefer. It’s a good idea to make sure your Go plugins are working before the session and you can do the following in your environment:

  • navigate your files and packages
  • jump to declarations
  • find all references
  • refactor your types and variables
  • see potential errors as you type/save your code

Sharing. Please make sure your desktop and status bars are free of private content and you are ready to share whatever is on your screen. Then go to meet.google.com start your own private conference and make sure your screen sharing works. The shared code on your screen should be readable by someone using a laptop screen, so pay close attention to this if you’re used to working on a large monitor. Note that Google Meet limits the resolution of shared screens, so you should ensure that you know how to manage the visuals of your IDE to make code readable.

Tasks

Now you are set up. Let’s try some serious coding business!

In the live coding session, we will ask you to design a small system and some test code to demonstrate its functionality. While we cannot reveal our specific tech interview tasks in this post, here is an example that should give you an idea of what to expect.

Block Drop Game

The task may go something like this.

Please design the data structures and a runner for the following game:

  • The game has an 8x16 grid where 1x1 blocks of different colours are stacked from bottom to top.
  • There are five different colours: red, green, blue, black, and white.
  • Each round a new block enters the grid at the top and then descends step by step down to the bottom.
  • Once the block hits the ground or another block below the block stops the falling, the next block appears.
  • The player scores points when blocks of the same colour form a line of four or more blocks.
  • These blocks are then removed from the grid and the blocks on top will drop further downwards.
  • The player can move the currently falling block left and right one unit.
  • The player loses the game if a block cannot drop further down from the top row of the grid.

The goal of a live coding session for this task is not to complete all features or come up with a nice GUI to visualize the game. We are more interested to see how you start your project, define the needed data structures, and draft the main functions for running the game logic. We want to see some method signatures and hear your thoughts on your design choices.

Here is a basic solution for the above task.

Block Drop after 30 Minutes

./code/main.go:

package main

import (
	"fmt"
	"math/rand"
	"time"
)

// Live Coding Timeline
// --------------------
// The following is a potential timeline for a 30 Minute coding session,
// implementing the Block Drop Game task.
//
// T+0  create dummy main.go
// T+5  added Game struct and Block struct as first proposed data structures
// T+10 added addBlock, Run, and Show method stubs for showing how to manage the game state
// T+15 added Drop and Step method stub and added some first case in the game loop
// T+20 added some logic in Step function, changed color from string to Color(int)
// T+25 added ClearLines function, score variable, and "game over" return
// T+30 "finished!" and feeling sad about completing so few of the described features 😿

type Game struct {
	// grid [16][8]string // T+5 initally drafted colors as string
	grid [16][8]Color // T+20 changed to Color(int)

	currentBlock *Block
}

type Block struct {
	x int
	y int

	// color string // T+5 initally drafted colors as string
	color Color // T+20 changed to Color(int)
}

type Color int

func (g *Game) addBlock() {
	// add new block on top
	// T+10 Question: in the middle or a random place? -> Let's try random!

	// T+20: implement random block addition
	g.currentBlock = &Block{
		x:     rand.Int() % 8,
		y:     -1,                    // 0 is the top, 16 is the bottom the blocks starts above row 0
		color: Color(rand.Int() % 5), // RGB + BW
	}
}

func (g *Game) Run() {
	// start the game
	// we need some notion of time passing by or a notion of game steps
	// this will need some loop that advances the game by
	// * checking the game conditions and rules
	// * applying changes on user input
	// * recompute the new positions of falling blocks

	fmt.Println("starting game loop")

	tick := time.NewTicker(time.Second)
	steps := 0
	score := 0
	defer tick.Stop()

	for {
		select {
		case <-tick.C:
			steps += 1
			fmt.Println("advance game state to step =", steps)
			if g.Step() != nil {
				// T+25 add game over case
				fmt.Println("game over score = ", score)
				return
			}
			score += g.ClearLines() // T+25 add ClearLine and score
		}
	}
}

func (g *Game) Step() error {
	if g.currentBlock == nil {
		g.addBlock()
	}
	if err := g.Drop(g.currentBlock); err != nil {
		// cannot drop the block any further
		// * check if block is stuck and return gameover error
		// * else "move" the currentBlock to the grid and end the step
		g.currentBlock = nil
	}
	return nil
}

func (g *Game) Drop(block *Block) error {
	// try to move the given block one step downwards.
	return nil
}

func (g *Game) ClearLines() int {
	// * check grid for lines and sum up score
	return 0
}

func (g *Game) Show() {
	for _, v := range g.grid {
		fmt.Println(v)
	}
}

func main() {
	fmt.Println("starting block game")

	g := Game{}
	fmt.Println("start grid:")
	g.Show()
	g.Run()
}

The Result

This code is not a finished block drop game, but a basic draft which shows our intent and how we plan to move forward. Don’t worry about not finishing the game! As we programmed, some choices were made that would have triggered good conversations about Go programming and the design of data structures. This is the main goal of the whole exercise!

We hope this quick outline will leave you feeling better prepared for the technical interview and wish you the best of luck!