diff --git a/2021/day13/day13_rs/Cargo.toml b/2021/day13/day13_rs/Cargo.toml
new file mode 100644
index 0000000..79b502f
--- /dev/null
+++ b/2021/day13/day13_rs/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "day13_rs"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+nom = "7.1.0"
diff --git a/2021/day13/day13_rs/src/main.rs b/2021/day13/day13_rs/src/main.rs
new file mode 100644
index 0000000..cc9e4e8
--- /dev/null
+++ b/2021/day13/day13_rs/src/main.rs
@@ -0,0 +1,83 @@
+#![warn(clippy::pedantic)]
+use std::collections::HashSet;
+use std::io::{stdin, Read};
+
+use nom::bytes::complete::tag;
+use nom::character::complete::{anychar, newline, u32};
+use nom::combinator::{map, map_opt};
+use nom::multi::many1;
+use nom::sequence::{preceded, separated_pair, terminated};
+
+type Input<'a> = &'a str;
+type IResult<'a, T> = nom::IResult, T>;
+
+type Point = (usize, usize);
+
+fn point(i: Input) -> IResult {
+ separated_pair(map(u32, |i| i as usize), tag(","), map(u32, |i| i as usize))(i)
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+enum Fold {
+ X(usize),
+ Y(usize),
+}
+
+fn fold(i: Input) -> IResult {
+ map_opt(
+ preceded(
+ tag("fold along "),
+ separated_pair(anychar, tag("="), map(u32, |i| i as usize)),
+ ),
+ |(dimension, position)| match dimension {
+ 'x' => Some(Fold::X(position)),
+ 'y' => Some(Fold::Y(position)),
+ _ => None,
+ },
+ )(i)
+}
+
+fn input(i: Input) -> IResult<(Vec, Vec)> {
+ separated_pair(
+ many1(terminated(point, newline)),
+ newline,
+ many1(terminated(fold, newline)),
+ )(i)
+}
+
+fn do_fold(points: impl Iterator- , fold: Fold) -> HashSet {
+ let transform = |x, n| if x < n { x } else { n - (x - n) };
+ points
+ .map(|(x, y)| match fold {
+ Fold::X(n) => (transform(x, n), y),
+ Fold::Y(n) => (x, transform(y, n)),
+ })
+ .collect()
+}
+
+fn main() {
+ let mut data = String::new();
+ stdin().lock().read_to_string(&mut data).unwrap();
+ let (points, folds) = input(&data).unwrap().1;
+
+ let mut points: HashSet<_> = points.into_iter().collect();
+ let mut folds = folds.into_iter();
+
+ points = do_fold(points.into_iter(), folds.next().unwrap());
+ println!("{}", points.len());
+
+ for fold in folds {
+ points = do_fold(points.into_iter(), fold);
+ }
+
+ for row in 0..=points.iter().map(|&(_, y)| y).max().unwrap() {
+ for col in 0..=points.iter().map(|&(x, _)| x).max().unwrap() {
+ if points.contains(&(col, row)) {
+ print!("#");
+ } else {
+ print!(".");
+ }
+ }
+ println!();
+ }
+}