DEV Community

Caleb Weeks
Caleb Weeks

Posted on • Edited on

Advent of Code #1 (in Crystal)

Wow! This year started out hard...

I am attempting to solve Advent of Code this year in Crystal. Although I am new to the language, the problem for day 1 was intrinsically difficult, particularly part 2.

Well, I got there in the end. It's interesting to use Crystal as a scripting language. Typically it is used in an OOP style with code organized in classes and methods.

Since Crystal is a compiled language, going from making a change to testing the code isn't all that fast, especially compared to Lua which I was just using earlier today. I've heard that there is a somewhat functional interpreter for Crystal, so maybe I'll give that a try.

It's really frustrating to me when I have code that I'm certain works, but it's giving me the wrong answer. Usually that means that I missed something in the question, or made a bad assumption about the input data. Sure enough, there are some edge cases in part 2 that I didn't consider, and I had to consult the subreddit for a hint.

Anyway, here's my final solution in all its glory:

require "string_scanner"

input = File.read("input").strip

part1 = input.split("\n").map do |line|
  digits = line.scan(/\d/).map(&.[0])
  (digits[0] + digits[digits.size - 1]).to_i
end.sum

puts part1

ordinal = {
  "one" => "1",
  "two" => "2",
  "three" => "3",
  "four" => "4",
  "five" => "5",
  "six" => "6",
  "seven" => "7",
  "eight" => "8",
  "nine" => "9"
}

part2 = input.split("\n").map do |line|
  digits = [] of String
  scanner = StringScanner.new(line)
  while !scanner.eos?
    match = scanner.scan_until(/\d|one|two|three|four|five|six|seven|eight|nine/)
    digit = scanner[0]?
    break if digit.nil?
    if digit.size > 1
      scanner.offset = scanner.offset - digit.size + 1
    end
    digits.push(ordinal[digit]? || digit)
  end
  (digits[0] + digits[digits.size - 1]).to_i
end.sum

puts part2
Enter fullscreen mode Exit fullscreen mode

Top comments (0)