<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

#[derive(Debug)]
enum Direction {
  Left(u32),
  Right(u32),
  Up(u32),
  Down(u32)
}

type Wire = Vec<Direction>;
type Grid = HashMap<(i32, i32), HashMap<usize, usize>>;

fn get_input() -> std::io::Result<String> {
  let mut file = File::open("03.txt")?;
  let mut contents = String::new();
  file.read_to_string(&mut contents)?;

  Ok(contents)
}

fn norm((x, y): (i32, i32)) -> i32 {
  x.abs() + y.abs()
}

fn parse_wires(input: &str) -> Vec<Wire> {
  input.lines()
  .map(|line| {
    line.split(',')
    .filter_map(|token| {
      let direction = token.chars().nth(0);
      let steps = &token[1..];

      steps.parse::<u32>().ok()
      .and_then(|steps| match direction {
        Some('L') => Some(Direction::Left(steps)),
        Some('R') => Some(Direction::Right(steps)),
        Some('U') => Some(Direction::Up(steps)),
        Some('D') => Some(Direction::Down(steps)),
        _ => None
      })
    })
    .collect::<Vec<_>>()
  })
  .collect::<Vec<_>>()
}

fn trace_wire(grid: &mut Grid, id: usize, wire: &Wire) {
  let mut position = (0, 0);
  let mut timestamp = 0;

  for direction in wire.iter() {
    let (move_vector, steps) = match direction {
      &Direction::Left(x) => ((-1, 0), x),
      &Direction::Right(x) => ((1, 0), x),
      &Direction::Up(x) => ((0, 1), x),
      &Direction::Down(x) => ((0, -1), x)
    };

    for _ in 0..steps {
      position = (position.0 + move_vector.0, position.1 + move_vector.1);
      timestamp += 1;

      if !grid.contains_key(&position) {
        grid.insert(position, HashMap::new());
      }

      let ids = grid.get_mut(&position).unwrap();

      if !ids.contains_key(&id) {
        ids.insert(id, timestamp);
      }
    }
  }
}

fn iter_collisions<'a>(grid: &'a Grid) -> impl Iterator<Item = (i32, i32)> + 'a {
  grid.iter()
  .filter(|(_, ids)| ids.len() > 1)
  .map(|(&pos, _)| pos)
}

fn iter_collision_times<'a>(grid: &'a Grid) -> impl Iterator<Item = usize> + 'a {
  iter_collisions(grid)
  .map(move |pos| {
    grid.get(&pos)
    .unwrap()
    .iter()
    .map(|(_, timestamp)| timestamp)
    .sum::<usize>()
  })
}
<commit_msg>Make code simpler<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

#[derive(Debug, Clone, Copy)]
enum Direction {
  Left,
  Right,
  Up,
  Down
}

type Wire = Vec<(Direction, usize)>;
type Grid = HashMap<(i32, i32), HashMap<usize, usize>>;

fn get_input() -> std::io::Result<String> {
  let mut file = File::open("03.txt")?;
  let mut contents = String::new();
  file.read_to_string(&mut contents)?;

  Ok(contents)
}

fn norm((x, y): (i32, i32)) -> i32 {
  x.abs() + y.abs()
}

fn parse_wires(input: &str) -> Vec<Wire> {
  input.lines()
  .map(|line| {
    line.split(',')
    .filter_map(|token| {
      let direction = token.chars().nth(0);
      let steps = &token[1..];

      steps.parse::<usize>().ok()
      .and_then(|steps| {
        match direction {
          Some('L') => Some(Direction::Left),
          Some('R') => Some(Direction::Right),
          Some('U') => Some(Direction::Up),
          Some('D') => Some(Direction::Down),
          _ => None
        }
        .map(|direction| (direction, steps))
      })
    })
    .collect::<Vec<_>>()
  })
  .collect::<Vec<_>>()
}

fn trace_wire(grid: &mut Grid, id: usize, wire: &Wire) {
  let mut position = (0, 0);
  let mut timestamp = 0;

  for &(direction, steps) in wire.iter() {
    let move_vector = match direction {
      Direction::Left => (-1, 0),
      Direction::Right => (1, 0),
      Direction::Up => (0, 1),
      Direction::Down => (0, -1)
    };

    for _ in 0..steps {
      position = (position.0 + move_vector.0, position.1 + move_vector.1);
      timestamp += 1;

      if !grid.contains_key(&position) {
        grid.insert(position, HashMap::new());
      }

      let ids = grid.get_mut(&position).unwrap();

      if !ids.contains_key(&id) {
        ids.insert(id, timestamp);
      }
    }
  }
}

fn iter_collisions<'a>(grid: &'a Grid) -> impl Iterator<Item = (i32, i32)> + 'a {
  grid.iter()
  .filter(|(_, ids)| ids.len() > 1)
  .map(|(&pos, _)| pos)
}

fn iter_collision_times<'a>(grid: &'a Grid) -> impl Iterator<Item = usize> + 'a {
  iter_collisions(grid)
  .map(move |pos| {
    grid.get(&pos)
    .unwrap()
    .values()
    .sum()
  })
}

{'fraction_non_alphanumeric': 0.21288259479214253, 'fraction_numerical': 0.018730013704888075, 'mean_word_length': 2.8547535211267605, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1582970', 'n_tokens_mistral': 1669, 'n_tokens_neox': 1637, 'n_words': 341}