Skip to content

Instantly share code, notes, and snippets.

@marekciupak
Last active January 28, 2019 21:50
Show Gist options
  • Save marekciupak/27dbe48d3f011129b905865e3a86fc61 to your computer and use it in GitHub Desktop.
Save marekciupak/27dbe48d3f011129b905865e3a86fc61 to your computer and use it in GitHub Desktop.
Day 3 Part 1 - Advent of Code 2017
defmodule Day3 do
require Integer
def part1(location) do
width = width(location)
steps = steps(location, width)
distance(steps, width)
end
def width(location) do
:math.sqrt(location - 1)
|> trunc()
|> floor_to_odd()
|> Kernel.+(1)
end
defp steps(location, width) do
location - (width - 1) * (width - 1)
end
defp floor_to_odd(integer) when Integer.is_odd(integer), do: integer
defp floor_to_odd(integer) when Integer.is_even(integer), do: integer - 1
def distance(steps, width) do
distance_to_the_perimeter(width) + distance_on_the_perimeter(steps, width)
end
defp distance_to_the_perimeter(width), do: div(width, 2)
def distance_on_the_perimeter(0, 0), do: 0
def distance_on_the_perimeter(steps, width) do
steps
|> rem(width)
|> distance_on_the_side(width)
end
def distance_on_the_side(steps, width) do
abs(steps - div(width, 2))
end
end
defmodule Day3Test do
use ExUnit.Case
test "calculates answers for part 1" do
assert Day3.part1(1) == 0
assert Day3.part1(12) == 3
assert Day3.part1(23) == 2
assert Day3.part1(1024) == 31
end
# 17 16 15 14 13
# 18 . . . 12
# 19 . . . 11
# 20 . . . 10
# 21 22 23 24 25
#
# 16 / 4 = 4 = width
#
test "calculates the width (number of locations in the square divided by 4) based on the given location" do
assert Day3.width(1) == 0
assert Day3.width(2) == 2
assert Day3.width(9) == 2
assert Day3.width(10) == 4
assert Day3.width(25) == 4
assert Day3.width(26) == 6
assert Day3.width(49) == 6
assert Day3.width(50) == 8
end
# Day3.distance(steps, width)
#
# Example for width = 6 and steps:
#
# 12 11 10 9 8 7 6
# 13 5
# 14 4
# 15 3
# 16 2
# 17 1
# 18 19 20 21 22 23 24
#
# =>
#
# 6 5 4 3 4 5 6
# 5 5
# 4 4
# 3 3
# 4 4
# 5 5
# 6 5 4 3 4 5 6
#
test "calculates the distance from the center of the spiral based on steps and width" do
assert Day3.distance(5, 6) == 5
end
# Day3.distance_on_the_perimeter(steps, width)
#
# Example for width = 6 and steps:
#
# 12 11 10 9 8 7 6
# 13 5
# 14 4
# 15 3
# 16 2
# 17 1
# 18 19 20 21 22 23 24
#
# =>
#
# 3 2 1 0 1 2 3
# 2 2
# 1 1
# 0 0
# 1 1
# 2 2
# 3 2 1 0 1 2 3
#
test "calculates the distance from the center of the side of the square based on steps and width" do
assert Day3.distance_on_the_perimeter(2, 2) == 1
assert Day3.distance_on_the_perimeter(1, 6) == 2
assert Day3.distance_on_the_perimeter(2, 6) == 1
assert Day3.distance_on_the_perimeter(3, 6) == 0
assert Day3.distance_on_the_perimeter(4, 6) == 1
assert Day3.distance_on_the_perimeter(5, 6) == 2
assert Day3.distance_on_the_perimeter(6, 6) == 3
assert Day3.distance_on_the_perimeter(7, 6) == 2
assert Day3.distance_on_the_perimeter(8, 6) == 1
assert Day3.distance_on_the_perimeter(9, 6) == 0
assert Day3.distance_on_the_perimeter(10, 6) == 1
assert Day3.distance_on_the_perimeter(24, 6) == 3
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment