Solve your sudoku puzzles with Elixir

Introduction

Why this project ?

I started learning Elixir few months ago and after finishing the Elixir channel on Exercism.io, I was looking for a bigger project. I had this Euler project in my head for a long time and the timing was excellent to start it.

Why Sudoku ?

Sudoku is maybe not the most exciting thing but everybody knows what it is and probably already tried once to solve one. So people will be more likely to understand me if I write an article or show the project for job interviews.

Get started

First things first, You need to install Elixir on your computer. Then you should see something like this:

Use mix to create and test your project

Before we start, I will try to let you the choice of just reading the article or coding the project. Here you will find the source code and the tests. When all the tests are green for a module you can continue.

Part-1: Create the board and apply values

At the end of this part you will be able to generate an empty board, apply initial values on it and generate this:

Introduction

  • There are 9 rows from 0 to 8 and this one is the first one (be careful this is 0 based)
    [{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {8, 1}]
  • There are 9 columns from 0 to 8 and this one is the first one
    [{1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}]
  • There are 9 boxes and this one is the number zero
    [{0,0} {1,0} {2,0} {0,1} {1,1} {2,1} {0,2} {1,2} {2,2}]

Rows, columns, boxes are also called units.

We will create 2 modules Sudoku.Board and Sudoku.ApplyValues.
I will follow the Programming Elixir 1.2 book conventions to create the structure of the project.

├── _build
...
├── config
│ └── config.exs
├── index.js
├── lib
│ ├── sudoku
│ │ ├── board.ex <--
│ │ ├── data_structure_utils.ex <--
│ │ ├── strategies
│ │ │ ├── apply_values.ex <--
│ └── sudoku.ex
├── mix.exs
├── package.json
├── README.md
├── stuff.js
└── test
├── sudoku_board_test.exs <--
├── sudoku_test.exs
└── test_helper.exs

Board

source code
test file

Generating a row:

Notice the default parameter and the way we define our range, by starting at the end, we don’t have to Enum.reversethe list. If you want to test your work you can use iex.

Cool ! Let’s use our test file:

Did you notice the difference between source code file extension and test one ? *.ex files are source files and will be compiled while *.exs will not be compiled ! They are scripts.

At the root of your project invoke mix test to run your test.

Generating rows

We have to do the same from 0 to 8.

and test it

Logic is the same for columns and boxes. Here you can code a bit to generate columns and boxes and run your code against my test file or check out my version here.
We will finish this part by the init function which will generate our empty board. We will basically map every coordinates with all the possibilities.

Try it in iex !

Applying values

source code

This is our puzzle:

input_str = 003020600900305001001806400008102900700000008006708200002609500800203009005010300

We will create a map (input_map) that represents our input.

then apply the input_map to our board

Let’s see that in action:

UGLY right ?! Let’s fix that

Bonus: The Display module

source code

├── _build
...
├── config
│ └── config.exs
├── index.js
├── lib
│ ├── sudoku
│ │ ├── board.ex
│ │ ├── display.ex <--
│ │ ├── strategies
│ │ │ ├── apply_values.ex
│ └── sudoku.ex
├── mix.exs
├── package.json
├── README.md
├── stuff.js
└── test
├── sudoku_board_test.exs
├── sudoku_test.exs
└── test_helper.exs

This part is not mandatory to run our project but if something goes wrong it’s will be helpful !

If you want to code this part, one thing to know is that every item has to have the same size. For that you can useString.pad_trailing.
Then try to:

  • drawing a item
  • drawing a line of items
  • drawing a line of separation

If everything goes well, you will see a less ugly representation now ;) using iex

That all for Part-1 ! And we don’t even solve a puzzle :(. In Part-2 we will start for real by using the backtracking algorithm.