Skip to content

Instantly share code, notes, and snippets.

@CarpeNoctem
Last active December 10, 2018 09:43
Show Gist options
  • Save CarpeNoctem/5b05cf59d44b6ff28aba4a14c3a3f0f7 to your computer and use it in GitHub Desktop.
Save CarpeNoctem/5b05cf59d44b6ff28aba4a14c3a3f0f7 to your computer and use it in GitHub Desktop.
Advent of Code 2018
File.read!("advent_input_day1.txt")
|> String.split
|> Enum.map(&String.to_integer/1)
#|> Enum.reduce(&(&1 + &2))
|> Enum.sum
|> IO.puts
offset=0; for line in $(cat advent_input_day1.txt); do offset=$(echo "$offset $line" | bc); done; echo $offset
inputs = File.read!("advent_input_day1.txt") |> String.split |> Enum.map(&String.to_integer/1) #String.to_integer appears to be no slower than Integer.parse.
stream = Stream.cycle(inputs)
# Why does Stream.cycle appear to be so slow, compared to my iteration in Go,
# and compared to a single 'for' iteration in elixir??
# I could visually see this when replacing the below with a simple
# a simple Enum.each(inputs, &IO.puts/1)
# Update: I found a bottleneck below in using Enum.any? with an anonymous function,
# and it at least completes now.
# But with that replaced, this is still taking twice as long as the Go implementation...
# Thoughts?
# Update 2: Thanks, @josevalim for pointing out MapSet vs the linked list!
# Now it runs in 1/10th the time of my Go implementation. ^__^'
#Enum.reduce(stream, [0], fn(input, offsets) ->
# new_offset = input + List.first(offsets)
# # if Enum.any?(offsets, &(new_offset == &1)) do #<- FOUND MY BOTTLENECK!
# if new_offset in offsets do
# IO.puts "Found repeat offset: #{new_offset}"
# exit(:normal)
# end
# [new_offset | offsets]
#end)
# Or I guess I could use reduce_while...
#Enum.reduce_while(stream, [0], fn(input, offsets) -> #<- FOUND BOTTLENECK #2
Enum.reduce_while(stream, {0, MapSet.new([0])}, fn(input, {prev_offset, offsets}) ->
new_offset = input + prev_offset
# if Enum.any?(offsets, &(new_offset == &1)) do #<- FOUND MY BOTTLENECK!
if new_offset in offsets do
{:halt, new_offset}
else
{:cont, {new_offset, MapSet.put(offsets, new_offset)}}
end
end) |> IO.puts
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
var inputs = get_inputs("advent_input_day1.txt")
offsets := []int{0}
input_index := 0
for {
new_offset := offsets[len(offsets) -1] + inputs[input_index]
for _, prev_offset := range offsets {
if prev_offset == new_offset {
fmt.Printf("Found repeat: %v\n", new_offset)
os.Exit(0)
}
}
offsets = append(offsets, new_offset) #The longer the search takes, the slower each iteration...
input_index += 1
if input_index >= len(inputs) {
input_index = 0
}
}
}
func get_inputs(filename string) []int {
file, _ := os.Open(filename)
defer file.Close()
inputs := []int{}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
input, _ := strconv.Atoi(scanner.Text())
inputs = append(inputs, input)
}
return inputs
}
File.read!("advent_input_day1.txt")
|> String.split
|> Enum.map(&String.to_integer/1) #This seems no slower than Integer.parse, and doesn't have the extra by-product.
|> Stream.cycle
|> Enum.reduce_while({0, MapSet.new([0])}, fn(input, {prev_offset, offsets}) ->
new_offset = input + prev_offset
if new_offset in offsets do
{:halt, new_offset}
else
{:cont, {new_offset, MapSet.put(offsets, new_offset)}}
end
end)
|> IO.puts
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
var inputs = get_inputs("advent_input_day1.txt")
new_offset := 0
offsets := map[int]bool{0: true}
input_index := 0
for {
new_offset = new_offset + inputs[input_index]
if _, exists := offsets[new_offset]; exists {
fmt.Printf("Found repeat: %v\n", new_offset)
os.Exit(0)
}
offsets[new_offset] = true
input_index += 1
if input_index >= len(inputs) {
input_index = 0
}
}
}
func get_inputs(filename string) []int {
file, _ := os.Open(filename)
defer file.Close()
inputs := []int{}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
input, _ := strconv.Atoi(scanner.Text())
inputs = append(inputs, input)
}
return inputs
}
defmodule Day2 do
defp get_checksum([], twos, threes) do
twos * threes
end
defp get_checksum([id | ids], twos, threes) do
stats = parse_id(String.split(id, ""), %{}) |> Map.values
twos = 2 in stats && twos + 1 || twos
threes = 3 in stats && threes + 1 || threes
get_checksum(ids, twos, threes)
end
def get_checksum(ids) do
get_checksum(ids, 0, 0)
end
defp parse_id([], stats) do
stats
end
defp parse_id([char | chars], stats) do
parse_id(chars, Map.update(stats, char, 1, &(&1 + 1)))
end
end
File.read!("input.txt") |> String.split |> Day2.get_checksum |> IO.puts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment