Day 2, 3, and 4.

This commit is contained in:
2017-12-04 10:46:19 +01:00
parent f8873234a0
commit d1d29bcd64
12 changed files with 892 additions and 0 deletions

154
2017/03/src/main.rs Normal file
View File

@@ -0,0 +1,154 @@
use std::io::{self, Read};
use std::iter::Iterator;
use std::collections::HashMap;
struct Spiral {
x: i32,
y: i32,
n: usize,
d_x: i32,
d_y: i32,
}
impl Spiral {
fn new() -> Self {
Spiral {
x: 0,
y: 0,
n: 0,
d_x: 0,
d_y: -1,
}
}
}
impl Iterator for Spiral {
type Item = (usize, (i32, i32));
fn next(&mut self) -> Option<Self::Item> {
self.n += 1;
if self.x.abs() == self.y.abs() && !(self.d_x == 1 && self.d_y == 0)
|| self.x > 0 && self.y == 1 - self.x
{
let t = self.d_x;
self.d_x = -self.d_y;
self.d_y = t;
}
let position = Some((self.n, (self.x, self.y)));
self.x += self.d_x;
self.y += self.d_y;
position
}
}
fn position(n: i32) -> (i32, i32) {
let mut spiral = Spiral::new();
let (_, pos) = spiral.nth((n - 1) as usize).unwrap();
pos
}
fn distance(from: (i32, i32), to: (i32, i32)) -> usize {
((to.0 - from.0) + (to.1 - from.1)).abs() as usize
}
fn allocate(input: usize) -> usize {
let mut grid: HashMap<(i32, i32), usize> = HashMap::new();
grid.insert((0, 0), 1);
let spiral = Spiral::new();
let mut value = 0;
for (_, (x, y)) in spiral.skip(1) {
value = 0;
if let Some(v) = grid.get(&(x + 1, y)) {
value += v;
}
if let Some(v) = grid.get(&(x + 1, y + 1)) {
value += v;
}
if let Some(v) = grid.get(&(x, y + 1)) {
value += v;
}
if let Some(v) = grid.get(&(x - 1, y + 1)) {
value += v;
}
if let Some(v) = grid.get(&(x - 1, y)) {
value += v;
}
if let Some(v) = grid.get(&(x - 1, y - 1)) {
value += v;
}
if let Some(v) = grid.get(&(x, y - 1)) {
value += v;
}
if let Some(v) = grid.get(&(x + 1, y - 1)) {
value += v;
}
if value > input {
break;
}
grid.insert((x, y), value);
}
value
}
fn main() {
let mut input = String::new();
io::stdin()
.read_to_string(&mut input)
.expect("failed to parse input");
for line in input
.lines()
.map(|line| line.trim())
.filter(|line| !line.is_empty())
{
let value = line.parse::<usize>()
.expect("failed to parse value as integer");
println!("distance={:?}", distance(position(value as i32), (0, 0)));
println!("allocate={:?}", allocate(value));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_position() {
assert_eq!(position(1), (0, 0));
assert_eq!(position(12), (2, 1));
assert_eq!(position(23), (0, -2));
}
#[test]
fn test_distance() {
assert_eq!(distance((0, 0), (0, 0)), 0);
assert_eq!(distance((2, 1), (0, 0)), 3);
assert_eq!(distance((0, -2), (0, 0)), 2);
}
#[test]
fn test_allocate() {
assert_eq!(allocate(4), 5);
assert_eq!(allocate(72), 122);
assert_eq!(allocate(500), 747);
}
}