 # AoC Day 1: Chronal Calibration Ryan Palo Updated on ・3 min read

## Overview

After my post last night, @aspittel suggested that we start a daily discussion post chain for these challenges. I think that's a neat idea, and significantly more efficient than everyone saying "Hey check out my git repo!"

I'm excited about this year's Advent mission, time traveling to save Christmas! This will be a place for discussing today's problem, Chronal Calibration. We're tasked with calibrating our time travel device by adding up sequential integers.

On a side note, if you get some extra time, it's probably a good idea to set up some infrastructure for reading input text from a file, because almost all of last year's challenges gave a few simpler examples (good for writing some basic tests) and then a huge-ish input given as a multiline plaintext file.

If you haven't solved today's puzzle yet, stop reading now, because I'm going to post my solution here. If you have finished a solution, post it in the comments! Also feel free to give (loving, instructional, nice) feedback to others' solutions to help them read better or run faster. I've seen a few people that are using this opportunity to learn a new language, so if you see something that works but isn't idiomatic to your favorite language, go ahead and offer suggestions! This includes me, since I'm just learning Rust, so I'm sure it's going to be a mixture of poorly translated Python-isms and gobbledygook.

## My Solution

``````// day1.rs

/// Given a bunch of integers (changes in frequency), one per line,
/// calculate the final sum
pub fn final_frequency(text: &str) -> i32 {
text.lines()
.map(|value: &str| -> i32 {value.parse().expect("Not a number")})
.sum()
}

/// Given a bunch of integers (changes in frequency), one per line,
/// calculate the running sum until you hit a cumulative sum that you've
/// seen before.  Return that first repeated cumulative sum.
pub fn first_duplicate_frequency(text: &str) -> i32 {
let mut history = vec!;
let mut total = 0;
for line in text.lines().cycle() {
let value: i32 = line.parse().expect("Not a number.");
total += value;
if history.contains(&total) {
}
history.push(total);
}
return 0;
}

#[cfg(test)]
mod tests {
use super::final_frequency;
use super::first_duplicate_frequency;

#[test]
fn final_all_positives() {
assert_eq!(3, final_frequency("+1\n+1\n+1"));
}

// More tests...
``````
``````// main.rs

// This file will change day to day as I just use it to exercise each day's module.

use std::fs::File;
use std::io::prelude::*;

mod day1;

fn main() {

let mut contents = String::new();
println!("{}", day1::first_duplicate_frequency(&contents));
}
``````

Lastly, I created a "private" leaderboard for DEV.to, in case anyone's interested. Apparently, they only hold 200 people per leaderboard, though, so first-come-first serve. Obviously, there are waaaay more than 200 people in the DEV family, so if you get there and the room is full, feel free to create your own on the Advent of Code site and post your room code in the comments. If I see somebody post a room code, I'll do my best to edit my post and copy it below, but read through the comments just in case I miss it.

Happy-- I mean, Merry Coding! I'm excited to see what people think.

@rpalo : 224198-25048a19

## Discussion  Ali Spittel

### Python

Part 1

``````data = open('input.txt', 'r')
total = 0
for line in data:
total += int(line)
print(total)
``````

Part 2

``````data = [int(i) for i in open('input.txt', 'r')]

def get_first_duplicate_total(data):
total = 0
prev_totals = set()
while True:
for i in data:
total += i
if total in prev_totals:

print(get_first_duplicate_total(data))
``````

I also learned about itertools.cycle through reading the Reddit solutions, that would make it so that I don't need the `while True:` Ryan Palo

Ah! So good. The clean-ness of Python never stops making me happy!

Using a `set` was a good idea. I didn't think of that, but it would be a lot faster for checking whether or not an item was present.

I'm going to offer unsolicited suggestions, but feel free to totally ignore them if you already knew about them (probable) or don't like them, since your solution already looks really nice.

1. For part one, generator expressions could be your friend:
``````data = open('input.txt', 'r')
total = sum(int(line) for line in data)
print(total)
``````
1. For the second part, check out itertools.cycle. Ali Spittel

Awesome! Yes, thank you! Found out about itertools.cycle this morning -- feels super niche but still really cool.

Part one could also be a one-liner!

``````print(sum(int(line for line in open('input.txt', 'r'))))
`````` Florian Rohrer

I'd also suggest to use a context manager (the `with` keyword) for clean opening and closing of files.

Part 1:

``````with open("input.txt") as f:
freq = sum(int(i.strip()) for i in f)
freq
``````

Part 2:

``````from itertools import cycle

with open("input.txt") as f:
freqs = [int(i.strip()) for i in f]

seen = set()
current = 0
for f in cycle(freqs):
if current in seen:
print(current)
break
else:
current += f
``````

Also: "Hey checkout my Github Repo!" jess unrein

Golang solution

Part 1

``````package main

import (
"bufio"
"os"
"strconv"
)

func freq(f *os.File)(sum int) {
scanner := bufio.NewScanner(f)
for scanner.Scan() {
i, err := strconv.Atoi(scanner.Text())
if err != nil {
panic(err)
}
sum += i
}
return
}

func main() {
f, err := os.Open("input1.txt")
if err != nil {
panic(err)
}
freq(f)
}
``````

Part 2

``````package main

import (
"io/ioutil"
"strconv"
"container/ring"
"strings"
)

func dup(x string)(sum int) {
list := strings.Split(x, "\n")
r := ring.New(len(list))
seen := map[int]bool{0: true}
for i := 0; i < r.Len(); i++ {
num, err := strconv.Atoi(list[i])
if err != nil {
panic(err)
}
r.Value = num
r = r.Next()
}
for true {
sum += r.Value.(int)
if (seen[sum] == true) {
return sum
}
seen[sum] = true
r = r.Next()
}
return
}

func main() {
if err != nil {
panic(err)
}
dup(string(f))
}
``````

I also wrote solutions in Python that look very similar to Ali's, so I decided to run a little benchmark test using today's input from the Advent of Code website. Here are the results

```````python3 1_1.py` 100 times
real    0m4.261s
user    0m2.845s
sys 0m0.936s

`go run 1_1.go` 100 times
real    0m34.169s
user    0m26.057s
sys 0m13.171s

go build 1_1.go

`./1_1` 100 times
real    0m0.641s
user    0m0.216s
sys 0m0.253s

`python3 1_2.py` 100 times
real    0m8.347s
user    0m6.126s
sys 0m1.477s

`go run 1_2.go` 100 times
real    0m38.925s
user    0m31.556s
sys 0m14.668s

go build 1_2.go

`./1_2` 100 times
real    0m3.891s
user    0m3.067s
sys 0m0.657s
`````` jess unrein

Python is significantly faster than running `go run myfile.go`. However, that's not Go's intended use case, really. That's more for debugging along the way, since `go run` does include the compilation each time.

I think it's interesting to compare the difference between `go run` and executing the compiled go executable, so the third set of each (ex: `./1_1`) is go running the resulting compiled executable 100 times. rhymes

Is it normal that part 2 is killing my CPU :D ? It's been running for minutes in Elixir but nada.

Anyhow, I've tried day 1 with all three languages which is not a great idea!

I just googled the parts of the various languages I needed

# Clojure

## part 1

``````(def numbers-as-strings (clojure.string/split (slurp "input.txt") #"\n"))
(defn sum [coll] (reduce + coll))
(println (sum numbers))
``````

I kind of hated it, I still don't have syntax highlighting nor formatting for some reason in VSCode and the REPL is quite slow to start (I didn't try with ClojureScript)

## part 2

``````(def repeated-numbers (cycle numbers))

(loop
[known-totals (set nil), total 0]
(if (contains? known-totals total)
(println total)
(recur (conj known-totals total) (+ total (first (take 1 repeated-numbers))))))
``````

I'm not sure it's correct, I had to kill it because it was hogging the CPU

# Elixir

## part 1

``````numbers_as_strings = String.split(String.trim(File.read!("input.txt")), "\n")
numbers = Enum.map(numbers_as_strings, fn x -> String.to_integer(x) end)
IO.puts(Enum.sum(numbers))
``````

Well, this was the easiest one

## part 2

``````defmodule Part2 do
def find_total(repeated_numbers, totals, sum) do
unless MapSet.member?(totals, sum) do
MapSet.put(totals, sum)
sum = sum + hd(Enum.take(repeated_numbers, 1))
find_total(repeated_numbers, totals, sum)
end

IO.puts sum
end
end

Part2.find_total(Stream.cycle(numbers), MapSet.new, 0)
``````

Again, I'm not sure it's correct, it just kills my computer

# Rust

## part 1

``````use std::fs;

fn main() {
let numbers_as_strings = data.split("\n").collect::<Vec<&str>>();
let numbers = numbers_as_strings.iter().filter_map(|n| n.parse::<i32>().ok()).collect::<Vec<i32>>();
let sum: i32 = numbers.iter().sum();
println!("{}", sum);
}
``````

There's a bit of fiddling with types and syntax but the compiler it's quite helpful when you type stuff that doesn't make sense. It can get in the way of me doing the excercises :D

## part 2

Well, this ran for half a second a produced the correct answer

``````use std::fs;
use std::collections::HashSet;

fn main() {
// part 1
let numbers_as_strings = data.split("\n").collect::<Vec<&str>>();
let numbers = numbers_as_strings.iter().filter_map(|n| n.parse::<i32>().ok()).collect::<Vec<i32>>();
let sum: i32 = numbers.iter().sum();
println!("{}", sum);

// part 2
let mut totals: HashSet<i32> = HashSet::new();
let repeated_numbers = numbers.iter().cycle();
let mut repeated_sum: i32 = 0;
for num in repeated_numbers {
if totals.contains(&repeated_sum) {
println!("{}", repeated_sum);
break;
}
totals.insert(repeated_sum);
repeated_sum += num
}
}
``````

What am I doing wrong with Clojure and Elixir :D ?

I've put Day 1 on Github: github.com/rhymes/aoc2018/tree/mas... Ryan Will

At a glance, in the Elixir part two solution it looks like the list of numbers is just being passed through as is. So, it is never moving on to the rest of the numbers and instead the sum is just adding the first number in the list over and over.

Because `repeated_numbers` is never reassigned the recursive call `find_total(repeated_numbers, totals, sum)` is passing the unchanged list of all the numbers through to the next iteration. rhymes

At a glance, in the Elixir part two solution it looks like the list of numbers is just being passed through as is. So, it is never moving on to the rest of the numbers and instead the sum is just adding the first number in the list over and over.

That's probably it, I thought that:

``````hd(Enum.take(repeated_numbers, 1))
``````

would take 1 number (and hence move the cursor). Ryan Will

It does, but because Elixir is immutable it returns a new list with the first element from `repeated_numbers` instead of mutating (changing in place) `repeating_numbers`

Also, this line `hd(Enum.take(repeated_numbers, 1))` could be rewritten as `hd(repeated_numbers)` to get the same functionality. The more "Elixir way to write that would be to use pattern matching. Something like `[head | tail] = repeated_numbers` Here is some more info on pattern matching, if you're interested. I think it is super cool! Pavel Gurkov

On the Clojure pt 2, you're effectively running an endless loop. You always take the first element from the cycled number collection, so you'll never hit the exit condition.
To avoid this while using the approach you chose, add a third `numbers` binding to the loop, and pass `(rest numbers)` when recuring, while computing total using `(first numbers)`. rhymes

Please do, I found a solution at the end, using `reduce_while`, instead of recursion:

``````repeated_numbers = Stream.cycle(numbers)
repeated_sum = Enum.reduce_while(repeated_numbers, {0, MapSet.new()}, fn i, {current, totals} ->
sum = current + i

if MapSet.member?(totals, sum) do
{:halt, sum}
else
{:cont, {sum, MapSet.put(totals, sum)}}
end
end)
IO.puts(repeated_sum)
``````

I feel like I should get through the tutorial at least :D M. Shemayev

First version, with Elixir, was ~15 seconds, to do what ended up being 130+ iterations on part two.

After some careful matching down to a more or less more-than-binary tree, I got it to about 10 seconds.

... then I went nuts and decided to see if I could do it with JUST sending messages aaaaaaand boy does Elixir do well with that, because I got it to 1.5 seconds total.

I just doublechecked and it is still hitting that loop the same number of times. 137991. M. Shemayev

Yeah, that's what I started with and definitely what I would like actually use for anything. It's soooooooo much more readable like how you have it! The trick with named Processes I did totally works here but I suspect would become insanely complex or fail as soon as you needed data that relied on the other data too, instead of just "has this been seen before" :D Juan Pablo Yamamoto

Also, I suspect there's a way to do the second part with Streams and avoid having so much information in memory as I did with my approach. Maybe something that takes advantage of `Stream.cycle` and `Stream.scan`. But not sure how to implement it. I'll let you know if I figure it out. 😀 Harriet

I wanted to solve these ones in bash, which I've been focussing on learning lately. First challenge was great, found a simple oneliner:

``````echo \$(( 0\$(tr -d '\n' < ./day1/input.txt) ))
``````

But part 2 was a nightmare. Super slow. Ended up using JS in the end, but would still love to know anyone's thoughts on how this could be optimised. Wasn't watching the clock but think it took >20 mins to run!

It's collecting previously computed frequencies in an array, and checking for the frequency in the array each time a new frequency is computed. Is it the maths that's likely to be so slow, or the looping, or both?

``````declare -i total=0
seen=()
found=

array_contains () {
for i in "\${seen[@]}"; do
if [[ "\$i" == "\$1" ]]; then
return 0
fi
done
return 1
}

while [[ ! \$found ]]; do
for line in \$(cat \$1); do
total=\$(( \${total}\${line} ))

if array_contains "\$total"; then
echo "FOUND " \$total
found=1
break
else
fi

seen+=(\$total)
done
done

# ./main.sh input.txt
`````` Yordi Verkroost

Awesome, this is a nice place to discuss the solutions! This is mine, in Elixir:

Common code (used by both part 1 and part 2):

``````defmodule AoC.DayOne.Common do
File.stream!(path)
|> Stream.map(&String.trim/1)
|> Stream.filter(fn x -> x != "" end)
|> Stream.map(&String.trim_trailing/1)
|> Stream.map(&String.to_integer/1)
|> Enum.to_list()
end
end
``````

Part 1

``````
defmodule AoC.DayOne.PartOne do
alias AoC.DayOne.Common

def main() do
|> calculate_sum()
|> IO.puts()
end

def calculate_sum(numbers) do
Enum.sum(numbers)
end
end
``````

Part 2

``````defmodule AoC.DayOne.PartTwo do
alias AoC.DayOne.Common

def main() do
|> calculate_result()
|> IO.puts()
end

def calculate_result(numbers, frequencies \\ [], base \\ 0, index \\ 0)

def calculate_result(numbers, frequencies, base, index) when index == length(numbers) do
calculate_result(numbers, frequencies, base, 0)
end

def calculate_result(numbers, frequencies, base, index) do
base = base + Enum.at(numbers, index)
if (Enum.member?(frequencies, base)) do
base
else
frequencies = [base | frequencies]
calculate_result(numbers, frequencies, base, index + 1)
end
end
end
``````

If you want, you could check out my full repo on GitHub. Ryan Will

Thanks for making this post and sharing your solutions!

Here are my solutions in Elixir and JavaScript.

To start a couple functions to parse the input.

``````def parse(input) do
input
|> String.split("\n")
|> Enum.map(&(String.trim(&1)
|> String.to_integer())
)
end
``````
``````function parse() {
return input()
.split('\n')
.map(Number);
}
``````

Part one's solutions.

``````def part_1 do
input()
|> parse()
|> Enum.sum()
end
``````
``````function partOne() {
return parse()
.reduce((total, current) => total + current, 0);
}
``````

Part two's solutions.

This solution takes advantage of Elixir's recursion, pattern matching, and multiple function clauses.

``````def part_2 do
input()
|> parse()
|> part_2(0, %{})
end

def part_2([current | rest] = _frequencies, total, record) do
total = current + total
record = Map.update(record, total, 1, &(&1 + 1))

case record[total] do
n when n > 1 ->
total

_ ->
part_2(rest, total, record)
end
end

def part_2([], total, record) do
input()
|> parse()
|> part_2(total, record)
end
``````

I made two solutions to part two in JavaScript the first uses a more imperative approach, and the second was meant to mimic the Elixir solution using recursion. The issue with that is JavaScript not being tail call optimized. In order to get around that I used a trampoline function and a while loop. Though, that approach is insanely slow.

``````function partTwoImperative() {
let record = {};
let frequency = 0;
let index = 0;
let frequencyList = parse();
let totalLoops = 0;

const found = (record, frequency) =>
(record[frequency] || 0) > 1;
const getFrequencyRecordValue = (record, frequency) =>
(record[frequency] || 0) + 1;

while (!found(record, frequency)) {
if (index === frequencyList.length) index = 0;

frequency += frequencyList[index];
record[frequency] = getFrequencyRecordValue(record, frequency);
index += 1;
totalLoops += 1;
}

return [frequency, totalLoops];
}

function partTwoTrampoline() {
const found = (record, frequency) => (record[frequency] || 0) > 1;

const getFrequencyRecordValue = (record, frequency) =>
(record[frequency] || 0) + 1;

const partTwoRecursive = ([current, ...rest], total, record) => {
const newTotal = total + current;

const newRecord = {
...record,
[newTotal]: getFrequencyRecordValue(record, newTotal)
};

return !found(newRecord, newTotal)
? () =>
partTwoRecursive(
rest.length ? rest : [3, 3, 4, -2, -4],
newTotal,
newRecord
)
: newTotal;
};

let ret = partTwoRecursive([3, 3, 4, -2, -4], 0, {});

while (typeof ret === 'function') {
ret = ret();
}

return ret;
}
`````` Dāvis Namsons

That's a good idea !

## Ruby

Part 1

``````input = File.open('./freqs.in').read

frequency = 0

input.each_line do |line|
frequency += line.to_i
end

puts frequency
``````

Part 2

``````input = File.open('./freqs.in').read

frequency_changes = input.scan(/[-+]\d+/).collect! &:to_i

frequency = 0
frequencies = []
i = 0

until frequencies.include?(frequency)
frequencies << frequency
frequency += frequency_changes[i]
i == frequency_changes.length - 1 ? i = 0 : i += 1
end

puts frequency
`````` Arjun Rajkumar

Hi Davis.. Just starting on the #adventofcode series.

Just curious how you are reading the inputs. E.g. first problem says the input is on adventofcode.com/2018/day/1/input

Will you be using Nokigiri or something similar to read the URL and parse the page to get the inputs?
Sorry if this sounds dumb.. But am wondering how you going to download the file?

Thanks Milton Mazzarri

Thanks for sharing, here are my solutions in Elixir and Racket.

I'm not sure if the Racket code is idiomatic, so, any advice is more than welcome.

## Elixir

``````# https://adventofcode.com/2018/day/1
#
# To run each exercise, you can do the following:
#
# elixir -r exercise.exs -e "IO.inspect(Frequency.first_exercise())"
# elixir -r exercise.exs -e "IO.inspect(Frequency.second_exercise())"
#
defmodule Frequency do
def first_exercise, do: frequency(process_file())

def second_exercise, do: first_frequency_reached_twice(process_file())

@spec frequency([integer]) :: integer
def frequency(freq_changes), do: Enum.sum(freq_changes)

@spec first_frequency_reached_twice([integer], {integer, MapSet.t()} | integer) :: integer
def first_frequency_reached_twice(frequency_changes, acc \\ {0, MapSet.new()})

def first_frequency_reached_twice(_, acc) when is_integer(acc), do: acc

def first_frequency_reached_twice(frequency_changes, acc) do
result =
Enum.reduce_while(frequency_changes, acc, fn digit, {current, past} ->
next = current + digit

if MapSet.member?(past, next) do
{:halt, next}
else
{:cont, {next, MapSet.put(past, next)}}
end
end)

first_frequency_reached_twice(frequency_changes, result)
end

defp process_file do
"input"
|> File.stream!()
|> Stream.map(fn x -> x |> String.trim() |> String.to_integer() end)
|> Enum.to_list()
end
end

ExUnit.start()

defmodule FrequencyTest do
use ExUnit.Case

import Frequency

test "should calculate frequency" do
test_cases = [
{[1, -2, 3, 1], 3},
{[1, 1, 1], 3},
{[1, 1, -2], 0},
{[-1, -2, -3], -6}
]

Enum.each(test_cases, fn {changes, expected} ->
assert frequency(changes) == expected
end)
end

test "should stop when a frequency is reached twice" do
test_cases = [
{[1, -2, 3, 1, 1, -2], 2},
{[1, -1], 0},
{[3, 3, 4, -2, -4], 10},
{[-6, 3, 8, 5, -6], 5},
{[7, 7, -2, -7, -4], 14}
]

Enum.each(test_cases, fn {changes, expected} ->
assert first_frequency_reached_twice(changes) == expected
end)
end
end
``````

## Racket

``````#lang racket/base

#|

If you want to test the results:

λ racket
> (require (file "exercise.rkt"))
> (frequency (file->list "input"))
520
> (first-frequency-reached-twice (file->list "input"))
394
|#

(require racket/set)
(require racket/match)

(provide frequency first-frequency-reached-twice)

(define (frequency changes)
(foldl + 0 changes))

(define (first-frequency-reached-twice changes)
(find-frequency (cons 0 (set 0)) changes))

(define (find-frequency acc changes)
(match acc
[result
#:when (integer? result)
result]
[(cons current previous-frequencies)
(find-frequency (reduce-while changes previous-frequencies current) changes)]))

(define (reduce-while changes previous-frequencies current)
(match changes
[changes
#:when (eq? '() changes)
(cons current previous-frequencies)]
(if (set-member? previous-frequencies next)
next
(reduce-while tail (set-add previous-frequencies next) next))]))
``````

Unit tests for Racket:

``````#lang racket/base

(require rackunit
"exercise.rkt")

(define exercise-tests
(test-suite
"Tests for exercise day 1"

(test-case
"Should calculate frequency"

(check-equal? (frequency '(1 -2 3 1)) 3)
(check-equal? (frequency '(1 1 1)) 3)
(check-equal? (frequency '(1 1 -2)) 0)
(check-equal? (frequency '(-1 -2 -3)) -6))

(test-case
"Should find first frequency reached twice"

(check-equal? (first-frequency-reached-twice '(1 -1)) 0)
(check-equal? (first-frequency-reached-twice '(1 -2 3 1 1 -2)) 2)
(check-equal? (first-frequency-reached-twice '(3 3 4 -2 -4)) 10)
(check-equal? (first-frequency-reached-twice '(-6 3 8 5 -6)) 5)
(check-equal? (first-frequency-reached-twice '(7 7 -2 -7 -4)) 14))))

(require rackunit/text-ui)
(run-tests exercise-tests)
`````` Ben Lovy

F# - this is my first brush with F# and .NET in general, so pointers are more'n welcome!

Common code:

``````let getFrequencies fileName =
lines
|> Seq.map Convert.ToInt32
|> Seq.toList
``````

Part 1:

``````let rec addFreq acc s =
match s with
| [] -> acc
| freq::freqs -> addFreq (acc + freq) freqs

let day1Part1 fileName =
``````

part 2:

``````let rec addFreqWithState acc visited whole remaining =
match remaining with
| [] -> addFreqWithState acc visited whole whole
let newval = acc + head
if Array.contains newval visited then
newval
else
addFreqWithState newval (Array.append visited [| newval |]) whole tail

let day1Part2 fileName =
let freqs = getFrequencies fileName
addFreqWithState 0 [| |] freqs freqs
``````

Entry point:

``````open System
open Library

[<EntryPoint>]
let main argv =
day1Part1 argv. |> printfn "Part 1 result: %i"
day1Part2 argv. |> printfn "Part 2 result: %i"

0 // return an integer exit code
``````

Part 2 is sloooow. How would you optimize this? Ben Lovy

Aha! Thanks so much, it's blazingly fast now:

``````let rec addFreqWithState acc visited whole remaining =
match remaining with
| [] -> addFreqWithState acc visited whole whole
let newval = acc + head
if Set.contains newval visited then
newval
else

let day1Part2 fileName =
let freqs = getFrequencies fileName
addFreqWithState 0 (new Set<int> (Seq.empty)) freqs freqs
``````

I guess the Tour of F# page shouldn't be my only learning resource :) Shritesh Bhattarai

I'm doing AoC with Rust too and the solution I came up with looks almost exactly like yours.

Part 1

``````pub fn callibrate(input: &[&str]) -> i32 {
input.iter().map(|s| s.parse::<i32>().unwrap()).sum()
}
``````

Part 2: I used a HashSet

``````pub fn twice(input: &[&str]) -> i32 {
let mut numbers = input.iter().map(|s| s.parse::<i32>().unwrap()).cycle();

let mut seen_results = HashSet::new();
seen_results.insert(0);

let mut sum = 0;

loop {
let num = numbers.next().unwrap();
sum += num;

if seen_results.contains(&sum) {
return sum;
} else {
seen_results.insert(sum);
}
}
}
``````

Instead of changing the main.rs file every day, I'll suggest creating a separate file for each day inside `src/bin` directory. That way, you can execute them using `cargo run --bin day_1`. Small but well thought out features like this is why I love Rust so much. For example, you can look at my repo at github.com/shritesh/advent-of-code

I hope to get through all of the challenges this year and learn from everyone here. Christopher Kruse

Ali's tweet and the Advent of Code project inspired me to update a long-latent blog, and make my first actual post on DEV! Thanks to both of you for the inspiration, and here's a not-quite-fully successful implementation in Clojure w/ write-up: dev.to/ballpointcarrot/advent-of-c... Matt Morgis

## Node.js

First, I created an async generator that read the input file stream chunk by chunk and `yield` each number line by line.

``````async function* streamToFrequencies(stream) {
let previous = "";
for await (const chunk of stream) {
previous += chunk;
let eolIndex;
while ((eolIndex = previous.indexOf("\n")) >= 0) {
// exclude the EOL
const number = previous.slice(0, eolIndex);
yield parseInt(number);
previous = previous.slice(eolIndex + 1);
}
}
if (previous.length > 0) {
yield parseInt(previous);
}
}
``````

Then part 1 was pretty straight forward:

``````const addFrequencies = async frequencies => {
let sum = 0;
for await (const frequency of frequencies) {
sum += frequency;
}
return sum;
};

const sum = stream => {
};
``````

This approach made part 2 ugly because I had to find a way to re-open the file stream and loop back through the inputs. Using a set over an array really helped with performance.

``````const calibrate = async stream => {
let currentFrequency = 0;
const frequenciesFound = new Set();

while (true) {
// clone stream and put in cold storage
// in case we need to re-read inputs.
let frozenStream = clone(stream);

for await (const frequency of streamToFrequencies(stream)) {
currentFrequency += frequency;
if (frequenciesFound.has(currentFrequency)) {
return currentFrequency;
}

}
stream = frozenStream;
}
};
``````

Putting it all together:

``````const frequencyStream = () => {
encoding: "utf-8",
highWaterMark: 256
});
};

const main = async () => {
const frequencySum = await sum(frequencyStream());
console.log({frequencySum})
const frequencyCalibration = await calibrate(frequencyStream());
console.log({frequencyCalibration});
};

main();
`````` Tiago Romero Garcia

I also did mine in JS but I decided to use the `readline` interface to read each line individually and spend less memory by not loading the entire file in the memory at once.

I haven't trying using `for await (... of ...)` with the `readline` interface. Maybe I'll try that next. If anyone would like to try it please post it here.

Here are my solutions:

My solution in JavaScript / Node 11, using the `readline` interface:

``````const fs = require('fs');

const readLines = (file, onLine) => {
crlfDelay: Infinity
});

return new Promise(resolve => reader.on('close', resolve));
};

const readFile = async file => {
const lines = [];
return lines;
}

module.exports = {
};
``````

01a.js

``````const { readFile } = require('./readLines');

(async () => {

const frequency = lines.reduce((frequency, line) => frequency + Number(line), 0);

console.log(`The final frequency is \${frequency}`);
})();
``````

01b.js

``````const { readFile } = require('./readLines');

(async () => {

const frequencySet = new Set();

let frequency = 0;
let didAFrequencyReachTwice = false;

while (!didAFrequencyReachTwice) {
for (let line of lines) {
frequency += Number(line);
if (frequencySet.has(frequency)) {
didAFrequencyReachTwice = true;
break;
}
else {
}
}
}

console.log(`The first frequency reached twice is \${frequency}`);
})();
`````` Matt Morgis

Readline doesn't work with async iterators and `for await` yet, but it just landed in 11.x staging.

Once it is released, my `streamToFrequencies` generator won't be needed.

Also, `createReadStream` only reads the file in 256 byte chunks at a time (or whatever you set the `highwatermark` to be, it does not read the entire file into memory. `readFile` would, however.

To read more about async iterators and generators and the `for await` syntax, check out 2ality.com/2018/04/async-iter-node... Jon Bristow

Kotlin Solution!

### Part 1

Please exuse my tricked out kotlin, I've added some personal extension functions to let me think about list comprehensions more simply.

``````private fun String.parseN() = let { (head, tail) ->
'+' -> 1
'-' -> -1
else -> throw Exception("Illegal input!")
} * tail.toInt()
}

``````

### Part 2

I made a silly mistake, and lost about an hour trying to figure out where I went wrong. I should set up my test runners ahead of day 2 so I don't end up with this same kind of typo.

``````fun answer2(input: List<String>): Int {
val ns = input.map(String::parseN).scan(Int::plus)
val ending = ns.last
return (sequenceOf(listOf(0)) + generateSequence(ns) {
it.map(ending::plus)
}).findFirstDupe(emptySet())
}

tailrec fun Sequence<List<Int>>.findFirstDupe(seen: Set<Int>): Int {
val intersections = head intersect seen
return when {
intersections.isNotEmpty() -> head.find { it in intersections }!!
}
}

/**
* My prewritten `scan` function... it's just a `fold` that keeps every step.
*/
fun <A, B> Sequence<A>.scan(initial: B, operation: (B, A) -> B) =
fold(sequenceOf(initial)) { scanList, curr ->
scanList + operation(scanList.last(), curr)
}

``````

Part 2 is "slow", but it's still under a minute 5 seconds to brute force through 150 iterations (or so) of the cycle. Paula Gearon

I made my way here by following @ASpittel. Thanks Ali.

I just finished at Clojure/conj, so it made sense to do today in Clojure. I should consider another language though, since AoC is always a good way to stretch yourself in something new.

### Clojure

As per Ryan's suggestions, I pulled the read-file/split operation into it's own `lines` operation. I also pulled each puzzle into it's own function.

``````(ns day1
(:require [clojure.string :refer [split]]))

(defn lines [input-file]
(split (slurp input-file) #"\n"))

(defn star
[input-file]
(->> (lines input-file)
(map #(Integer/parseInt %))
(apply +)))

(println (star "input1.txt"))
``````

This highlights something that bugs me about Clojure... there is no built-in function to read a number from a string. It's simple to call out to Java like I just did, but I think there should be something built into the language.

``````(defn star2
[input-file]
(let [numbers (->> (lines input-file) (map #(Integer/parseInt %)))]
(loop [[n & rn] (cycle numbers) f 0 acc #{}]
(let [f (+ f n)]
(if (acc f)
f
(recur rn f (conj acc f)))))))

(println (star2 "input1.txt"))
``````

This second puzzle needed something more than a single operation. My first thought was using a `reduce` function, but then I realized that I needed to keep going through the input over and over until completion, and `reduce` works on the entire input... unless I created a transducer, which is too much work for something this simple. I probably should have thought about using `loop` in the first place. Carly Ho 🌈

PHP

Part 1:

``````<?php
\$freq = 0;
\$list = file_get_contents(\$argv);
\$changes = explode("\n", trim(\$list));
foreach (\$changes as \$change) {
\$freq += intval(\$change);
}
echo \$freq;
die(1);
``````

Part 2:

``````<?php
\$freq = 0;
\$seen = array(0);
\$current = 0;
\$newfreq = null;
\$list = file_get_contents(\$argv);
\$changes = explode("\n", trim(\$list));
do {
if (\$newfreq) {
array_push(\$seen, \$newfreq);
}
\$freq += intval(\$changes[\$current]);
\$newfreq = \$freq;
\$current++;
if (\$current == count(\$changes)) {
\$current = 0;
}
} while (!in_array(\$newfreq, \$seen));
echo \$freq;
die(1);
`````` Pavel Gurkov

Clojure:

(`utils/read-file` just slurps and splits by newlines)

Part 1:

``````(->>
(map #(Integer. ^String %))
(apply +))

``````

Part 2:

``````(->>
(map #(Integer. ^String %))
(cycle)
(reduce
(fn [{:keys [freq seen]} freq-change]
(if (seen freq)
(reduced freq)
{:freq (+ freq freq-change) :seen (conj seen freq)}))
{:freq 0 :seen #{}}))
`````` Ashley Maria

Pt 2 JS/Node Solution:

``````const fs = require('fs');

let currFrequency = new Set();

const changes = datas.split(/\n|\r/m)
.map(Number);

let frequency = 0;
let i = 0;

while (true) {
frequency += changes[i];
if (currFrequency.has(frequency)) {
console.log(frequency);
break;
}
i = i === changes.length - 1 ? 0 : i + 1;
}
`````` Neil Gall

I'm enjoying reading everyone's solutions. After doing last year's in Haskell I'm using Kotlin to try to improve my knowledge of the language and libraries. I'm also avoiding using an IDE, as auto-suggest and magic building don't teach you what's really going on under the hood.

``````package adventofcode2018.day1

import java.io.File

/** Infinitely repeat a sequence */
fun <T> Sequence<T>.repeat() = generateSequence { asIterable() }.flatten()

/** Like fold() but returns a sequence of all the accumulator values,
*  not just the last one. `seq.scanl(i, f).last() == seq.fold(i, f)` */
fun <T, U> Sequence<T>.scanl(initial: U, f: (U, T) -> U): Sequence<U> {
var acc: U = initial
return map { x -> acc = f(acc, x); acc }
}

fun main(args: Array<String>) {

// part 1
val result = input.sum()
println("Part 1 result: \${result}")

// part 2
val repeatedInput = input.asSequence().repeat()
val accumulatedInput = repeatedInput.scanl(0, Int::plus)
println("Part 2 result: \${unconsumed.first()}")
}
``````

I know the idea is to avoid everyone's github but I'm writing notes on my solutions at github.com/neilgall/adventofcode2018 Bjarne Magnussen

I am using Advent of Code to learn Golang, and here is the solution I came up with. Suggestions for improvements are always welcome!

Part 1:

``````package main

import (
"bufio"
"fmt"
"os"
"strconv"
)

// and returns a slice of its lines.
func readLines(path string) ([]int, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()

var lines []int
scanner := bufio.NewScanner(file)
for scanner.Scan() {
// string to int
i, err := strconv.Atoi(scanner.Text())
if err != nil {
return nil, err
}
lines = append(lines, i)
}
return lines, scanner.Err()
}

func main() {
if err != nil {
panic(err)
}

var sum int
for _, line := range lines {
sum += line
}
fmt.Printf("Sum is: %d\n", sum)
}
``````

Part 2:

``````package main

import (
"bufio"
"fmt"
"os"
"strconv"
)

// and returns a slice of its lines.
func readLines(path string) ([]int, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()

var lines []int
scanner := bufio.NewScanner(file)
for scanner.Scan() {
// string to int
i, err := strconv.Atoi(scanner.Text())
if err != nil {
return nil, err
}
lines = append(lines, i)
}
return lines, scanner.Err()
}

func main() {
if err != nil {
panic(err)
}

occurences := map[int]int{0: 1}
var freq, j int
for occurence := 1; occurence < 2; j++ {
freq += lines[j%len(lines)]
_, ok := occurences[freq]
if ok {
occurence = 2
}
occurences[freq] = 1
}
fmt.Printf("%d\n", freq)
}
``````

I am also using Python that I have more experience with to cross check solutions.

Part 1:

``````def chronal_calibration(fname):
with open(fname) as f:
return sum([int(x.strip()) for x in content])

chronal_calibration('input')
``````

Part 2

``````import itertools

def chronal_calibration_cycle(fname):
with open(fname) as f:
content = [int(x.strip()) for x in content]
freq = 0
occurences = {freq: 1}
for change in itertools.cycle(content):
freq += change
occurences[freq] = occurences.get(freq, 0) + 1
if occurences[freq] > 1:
break
return freq

print(chronal_calibration_cycle('input'))
`````` Josh Wisenbaker

Hmm... I just took the input and stuck it in an array rather than reading it from disk. That's not hard to do in Swift though, maybe I'll go back and add in the file loading.

In any case, here is what I did in my Playground!

### Swift

##### Part 1

This one was super easy in Swift via it's `reduce(_:_:)` function. Given that I had the `Ints` in an `Array`, it was a one liner. I added some context to the output because why not?

``````print("The final calculated frequency is: \(frequencyInput.reduce(0,+))")
``````

For those of you new to Swift, this version of `reduce` has two inputs. The first one is the starting value for the accumulator and the second is the closure of what to do with the values from the collection. This is simply a shorthand syntax for adding all the values in a collection together and returning it. The long version looks like this:

``````let frequency = frequencyInput.reduce(0, { x, y in
x + y
})
``````
##### Part 2

This part was a bit tougher and my first attempt had all kinds of bad smells like breaking to function labels and such. Eventually I wrapped it all up in a closure that takes an `Array` of `Int` values and then returns a single `Int` with the first repeated number.

``````/// A closure that takes an `Array` of `Int` values and adds them together in a loop. Upon finding the first repeated
/// value it breaks and returns.
let findRepeatedFrequency = {(_ inputArray: [Int]) -> Int in
var accumilated = 0
var frequencies = Set<Int>()
while true {
for skew in inputArray {
accumilated += skew
if frequencies.contains(accumilated) {
return accumilated
}
frequencies.insert(accumilated)
}
}
}

print("The first repeated frequency is: \(findRepeatedFrequency(frequencyInput))")
``````

Essentially this is a for-loop version of the `reduce` operation, but then I also maintain a history of the values in a `Set` and check to see if this is a value we've run into before.

I solved the second one with a closure instead of a regular function because I've been teaching myself more about them lately. Antonello Galipò

Hi there!
I've used Javascript.
Here's my part one solution:

``````const fs = require('fs');

// Parse to a int array
let diffs = contents.split("\n").map(item => parseInt(item));

// Reduce
let result = diffs.reduce((a,b) => a+b);

// Profit!
console.log(result);
``````

I just read the input from file, parsed to a int array and used the `reduce` function.

Talking about the second part, I've user a dictionary to store frequencies and retrieve them quickly (access is O(1)), cycling in a circular manner through the provided diffs:

``````const fs = require('fs');

function duplicateFinder(diffs) {
// Init an empty memo. We'll store here frequency values for easy retrieval
let memo = {};

let currentFrequency = 0;
let i = 0;

// Loop until currentFrequency is already in the memo.
// When the loop breaks, it will be because currentFrequency got a value that had before.
// This means it's the second time it appears
while (!(currentFrequency in memo)) {
memo[currentFrequency] = currentFrequency.toString();

currentFrequency += diffs[i];
i = ++i % diffs.length
}
return currentFrequency;
}

// Parse to a int array
let diffs = contents.split("\n").map(item => parseInt(item));

// Do the work
let result = duplicateFinder(diffs);

// Profit!
console.log(result);
``````

I'm planning to do this in Go too, since I'd love to practice this language, but I haven't much time for now :( cloudyhug

I'm doing this in C++ this year, but as we are proposing original solutions with very expressive languages, I'll show a solution in OCaml :)

#### OCaml

Part 1

``````let rec f freq ic =
try f (freq + int_of_string (input_line ic)) ic
with End_of_file -> freq

let () = Printf.printf "%d\n" (f 0 stdin)
``````

Part 2

``````let rec read_changes changes ic =
let next_line = try Some (input_line ic) with End_of_file -> None in
match next_line with
| None -> List.rev changes
| Some c -> read_changes (int_of_string c :: changes) ic

let rec f freq freqs changes_done = function
| [] -> f freq freqs [] (List.rev changes_done)
| c :: r ->
let freq' = freq + c in
if List.mem freq' freqs then freq'
else f freq' (freq' :: freqs) (c :: changes_done) r

let () = Printf.printf "%d\n" (f 0  [] (read_changes [] stdin))
``````

Using lists is not very efficient but the code is quite short, that is nice. Pascal

1.1

A bit overcomplicated. Didn't know parseInt parses signs too 😅

``````const data = document.querySelector('pre').innerText

const frequencies = data.split('\n')

function getFrequency (freqs) {
return freqs.reduce((acc, val) => {
const sign = val === '+' ? 1 : -1
const number = val.substring(1)

return acc + sign * number
}, 0)
}

const result = getFrequency(frequencies)
console.log(result)
``````

1.2

The first result is the solution, not quite sure why it prints so many other results after that even if I set matchFound = true though 🤔

``````const data = document.querySelector('pre').innerText

const frequencies = data.split('\n')
let sums = []

function getFrequency (freqs, acc=0, callback) {
return freqs.reduce((acc, val) => {
const sign = val === '+' ? 1 : -1
const number = val.substring(1)
const current = acc + sign * number
callback(current)
return current
}, acc)
}

let startFreq = getFrequency(frequencies, 0, current => sums.push(current))

function isMatch (arr, el) {
return arr.find(element => element === el)
}

function findMatch () {
let matchFound = false

while(!matchFound) {
startFreq = getFrequency(frequencies, startFreq, current => {
if (isMatch(sums, current)) {
matchFound = true
console.log('The match is', current)
}
})
}
}

findMatch()
`````` Michael Kohl

This is my code for parts 1 & 2 in Ruby:

``````require 'set'

STARTING_FREQUENCY = 0

puts frequencies.reduce(STARTING_FREQUENCY, :+)

seen = Set.new([STARTING_FREQUENCY])
puts frequencies.cycle.reduce(STARTING_FREQUENCY) { |sum, n|
sum += n
break sum if seen.include?(sum)

}

__END__
-5
-2
+1
+14
# data section abbreviated
`````` roeekl

#### C#

Part 1

``````Console.WriteLine(File.ReadAllLines(@".\day1_input.txt").Sum(s => int.Parse(s)));
``````

Part 2

``````int[] input = File.ReadAllLines(@".\day1_input.txt").Select(s => int.Parse(s)).ToArray();
HashSet<int> set = new HashSet<int>();
int freq = 0;
for (int i = 0; set.Add(freq = freq + input[i % input.Length]); i++) ;
Console.WriteLine(freq);
`````` Ian Kirker

This seemed easiest to do in `awk`:

##### Part 1
``````BEGIN {
f = 0
}

{
f += \$1
}

END {
print f
}
``````
``````awk -f 1.1.awk 1.1.input
``````
##### Part 2

`awk`'s arrays are basically hashes/associative arrays, so you can just use the frequencies as keys much like the Python dictionary solutions. Because `awk` is really focused on processing a list of files, this uses a hack on the built-in variable that tracks where on that list `awk` has gotten to, so it only stops once it's found the duplicate.

``````BEGIN {
f = 0
a = 1
}

{
f += \$1
if (f in a) {
a[f] += 1
} else {
a[f] = 1
}
if (a[f] == 2) {
print(f)
exit 0
}
# Resets what file is the next to process
ARGIND=0
}
``````
``````awk -f 1.2.awk 1.2.input
`````` Phil Nash

Thanks for this Ryan! I've joined the leaderboard. Good luck to everyone!

Here's my solution in Crystal, both parts are included as one class:

``````class Device
getter frequency : Int32
getter duplicate : Int32 | Nil

def initialize
@frequency = 0
@duplicate = nil
@frequencies = Set{@frequency}
end

def update(input : Array(String))
@frequency = input.map { |string| string.to_i }.reduce(@frequency) do |acc, i|
frequency = acc + i
@duplicate = frequency if @frequencies.includes?(frequency) && @duplicate.nil?
frequency
end
end

def find_duplicate(input : Array(String))
while @duplicate.nil?
update(input)
end
end
end

puts "--- Day 1: Chronal Calibration ---"
device = Device.new
device.update(input)
puts "Frequency result: #{device.frequency}"
device.find_duplicate(input)
puts "Frequency first duplicates at: #{device.duplicate}"
``````

There are also tests here. Conlin Durbin

A little late to starting on this, but I am excited to get going!

JS

Part 1 (A little bit trolly)

``````var fs = require('fs');

console.log(eval(contents));
});

``````

Part 2 (could probably use some optimizations)

``````var fs = require('fs');

const hash = {};

const lines = contents.split('\n');
let current = 0;
let i = 0;
while(true) {
if(i === lines.length-1) {
i = 0;
}
const line = lines[i];
const old = current;
const num = Number(line)
current += num;
if(hash[current]) {
console.log(current);
break;
}
hash[current] = true;
console.log(old, '+', num, '->', current);
i++;
}
});

`````` Arjun Rajkumar

Hi Ryan.. Just starting on the #adventofcode series.

Just curious how you are reading the inputs. E.g. first problem says the input is on adventofcode.com/2018/day/1/input

Do you parse the page to get the inputs?
Or copy/paste and store it as a file? Sorry if this sounds dumb.. But am wondering how you are downloading the file?

Thanks Ryan Palo

No problem! That would be slick to have it download the page for me, but I just go to the link and copy the text. I've got a directory in my project called `data`, and each day's input as `day1.txt`, `day2.txt`, etc. Then I just change the filename that I'm reading.

Let me know if this helps or if you have other questions :)