Skip to content

Instantly share code, notes, and snippets.

@lilactown
Created December 4, 2017 09:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lilactown/00ad8dfb539a6fe0ffbba22d05e4075c to your computer and use it in GitHub Desktop.
Save lilactown/00ad8dfb539a6fe0ffbba22d05e4075c to your computer and use it in GitHub Desktop.
Advent of Code, 2017: Day 3
let abs = Js.Math.abs_int;
/*
Desired output:
1 => (0, 0)
2 => (1, 0)
3 => (1, 1)
4 => (0, 1)
5 => (-1, 1)
6 => (-1, 0)
7 => (-1, -1)
8 => (0, -1)
9 => (1, -1)
*/
let spiral = (n) => {
let rec next = (x, y, count) => {
/* based off https://stackoverflow.com/a/31864777/4379329
the direction is wrong but the distance should stay the same */
let finished = count == n;
let pivot = abs(x) <= abs(y) && (x != y || x >= 0);
switch (finished, pivot) {
| (true, _) => (x, y)
| (_, true) =>
let x' = x + (y >= 0 ? 1 : (-1));
next(x', y, count + 1)
| (_, false) =>
let y' = y + (x >= 0 ? (-1) : 1);
next(x, y', count + 1)
}
};
next(0, 0, 1)
};
let distance = ((x, y)) => abs(x) + abs(y);
let part1 = (n) => distance(spiral(n));
/**
* For part two, I created an actual grid. I allow
* coordinates to be placed inside of it for ease of
* printing.
*/
type element =
| Coordinates(int, int)
| Number(int);
type grid = array(array(element));
let makeGrid: int => grid =
(n) => {
let d = n / 2;
Array.init(n, (y) => Array.init(n, (x) => Coordinates(x - d, - y + d)))
};
let get = (grid: grid, d, x, y) =>
switch grid[- (y - d)][x + d] {
| Coordinates(_, _) => 0
| exception (Invalid_argument(_)) => 0
| Number(el) => el
};
let set = (grid: grid, d, x, y, el) => grid[- (y - d)][x + d] = el;
let part2 = (n, magicNumber) => {
let grid = makeGrid(n);
let get = get(grid, n / 2);
let set = set(grid, n / 2);
set(0, 0, Number(1));
let rec next = (x, y) => {
/* based off https://stackoverflow.com/a/31864777/4379329
the direction is wrong but the distance should stay the same */
let pivot = abs(x) <= abs(y) && (x != y || x >= 0);
/* get all neighbors */
let n1 = get(x + 1, y + 0);
let n2 = get(x + 1, y + 1);
let n3 = get(x + 0, y + 1);
let n4 = get(x - 1, y + 1);
let n5 = get(x - 1, y + 0);
let n6 = get(x - 1, y - 1);
let n7 = get(x + 0, y - 1);
let n8 = get(x + 1, y - 1);
let sum = n1 + n2 + n3 + n4 + n5 + n6 + n7 + n8;
let finished = sum > magicNumber || x == n / 2 && y == n / 2;
set(x, y, Number(sum));
switch (finished, pivot) {
| (true, _) => sum
| (_, true) =>
let x' = x + (y >= 0 ? 1 : (-1));
next(x', y)
| (_, false) =>
let y' = y + (x >= 0 ? (-1) : 1);
next(x, y')
}
};
next(1, 0)
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment