Marketing Pitch and Impressions#

The Nim website describes the language like this:

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula.

nim-lang.org

There are a few additional interesting points worth noting:

  • Compiles to C, C++, or JavaScript, presumably making targeting new architectures easier.
  • Automatic memory management via ARC or ORC, where ORC is ARC with cycles.
  • Compile-time Function Execution (CTFE), which permits compile-time computation and AST manipulation.
  • Syntax is similar to Python, using indentation for code blocks.

I quite like the ideas behind Nim. It has a decent library, automatic memory management, modern tooling and compiles to native code. The syntax is easy to read and pleasant to work with.

Unfortunately though, I can’t really see a compelling reason to use it over more mainstream languages. Perhaps the more compelling use cases would take advantage of Nim’s very strong metaprogramming features.

Visual Studio Code support for Nim is excellent.

The Code#

The code itself is straightforward and easy to read. Having the euclMod function available in the base library is a nice touch. Also note the indexing from the end of the string using ^ in positions(…).

The code itself is pretty straightforward. It generates a list of start and unwrapped end positions for each move. For part 1 we just count the cases where end mod 100 == 0. For part 2, we count the number of revolutions made, with an additional adjustment for passing zero turning to the left.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import std/[strutils, sequtils, math, strformat]

proc positions(moves: seq[string], start: int): seq[(int, int)] =
  var
    currentC = start

  for move in moves:
    let p = currentC.euclMod(100)
    currentC = p + (if move[0] == 'L': -1 else: 1) * parseInt(move[1 .. ^1])
    result.add((p, currentC))

proc main() =
  let posns = readFile("y25d01.txt").splitLines().positions(start = 50)

  let result1 = posns.countIt(it[1].euclMod(100) == 0)
  echo fmt"Result1: {result1}"

  let result2 = posns.mapIt(
    abs(it[1]) div 100 + (if it[0] != 0 and it[1] <= 0: 1 else: 0)
  ).sum
  echo fmt"Result2: {result2}"

when isMainModule:
  main()

Install Nim and run#

The recommended way to install Nim is via choosenim, though most package managers work as well. I used Homebrew.

# I installed via Homebrew
brew install nim

# Website recommends "choosenim"
curl https://nim-lang.org/choosenim/init.sh -sSf | sh

# Compile and run
nim r d01.nim