Skip to content

Commit c4c0748

Browse files
committed
day 1
1 parent 648b909 commit c4c0748

File tree

12 files changed

+1446
-0
lines changed

12 files changed

+1446
-0
lines changed

.envrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use flake

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ Cargo.lock
1212

1313
# MSVC Windows builds of rustc generate these, which store debugging information
1414
*.pdb
15+
16+
# Nix
17+
/target
18+
result*
19+
.direnv/

Cargo.lock

+39
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "aoc2023"
3+
version = "0.1.0"
4+
edition = "2021"
5+
license = "MIT"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
eyre = "0.6.9"
11+
12+
[dev-dependencies]
13+
indoc = "2.0.4"

deny.toml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[licenses]
2+
allow = [
3+
"MIT"
4+
]

flake.lock

+121
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
{
2+
description = "Build a cargo project";
3+
4+
inputs = {
5+
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
6+
7+
crane = {
8+
url = "github:ipetkov/crane";
9+
inputs.nixpkgs.follows = "nixpkgs";
10+
};
11+
12+
fenix = {
13+
url = "github:nix-community/fenix";
14+
inputs.nixpkgs.follows = "nixpkgs";
15+
inputs.rust-analyzer-src.follows = "";
16+
};
17+
18+
flake-utils.url = "github:numtide/flake-utils";
19+
20+
advisory-db = {
21+
url = "github:rustsec/advisory-db";
22+
flake = false;
23+
};
24+
};
25+
26+
outputs = { self, nixpkgs, crane, fenix, flake-utils, advisory-db, ... }:
27+
flake-utils.lib.eachDefaultSystem (system:
28+
let
29+
pkgs = nixpkgs.legacyPackages.${system};
30+
31+
inherit (pkgs) lib;
32+
33+
craneLib = crane.lib.${system};
34+
src = craneLib.cleanCargoSource (craneLib.path ./.);
35+
36+
# Common arguments can be set here to avoid repeating them later
37+
commonArgs = {
38+
inherit src;
39+
strictDeps = true;
40+
41+
buildInputs = [
42+
# Add additional build inputs here
43+
] ++ lib.optionals pkgs.stdenv.isDarwin [
44+
# Additional darwin specific inputs can be set here
45+
pkgs.libiconv
46+
];
47+
48+
# Additional environment variables can be set directly
49+
# MY_CUSTOM_VAR = "some value";
50+
};
51+
52+
craneLibLLvmTools = craneLib.overrideToolchain
53+
(fenix.packages.${system}.complete.withComponents [
54+
"cargo"
55+
"llvm-tools"
56+
"rustc"
57+
]);
58+
59+
# Build *just* the cargo dependencies, so we can reuse
60+
# all of that work (e.g. via cachix) when running in CI
61+
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
62+
63+
# Build the actual crate itself, reusing the dependency
64+
# artifacts from above.
65+
my-crate = craneLib.buildPackage (commonArgs // {
66+
inherit cargoArtifacts;
67+
});
68+
in
69+
{
70+
checks = {
71+
# Build the crate as part of `nix flake check` for convenience
72+
inherit my-crate;
73+
74+
# Run clippy (and deny all warnings) on the crate source,
75+
# again, resuing the dependency artifacts from above.
76+
#
77+
# Note that this is done as a separate derivation so that
78+
# we can block the CI if there are issues here, but not
79+
# prevent downstream consumers from building our crate by itself.
80+
my-crate-clippy = craneLib.cargoClippy (commonArgs // {
81+
inherit cargoArtifacts;
82+
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
83+
});
84+
85+
my-crate-doc = craneLib.cargoDoc (commonArgs // {
86+
inherit cargoArtifacts;
87+
});
88+
89+
# Check formatting
90+
my-crate-fmt = craneLib.cargoFmt {
91+
inherit src;
92+
};
93+
94+
# Audit dependencies
95+
my-crate-audit = craneLib.cargoAudit {
96+
inherit src advisory-db;
97+
};
98+
99+
# Audit licenses
100+
my-crate-deny = craneLib.cargoDeny {
101+
inherit src;
102+
};
103+
104+
# Run tests with cargo-nextest
105+
# Consider setting `doCheck = false` on `my-crate` if you do not want
106+
# the tests to run twice
107+
my-crate-nextest = craneLib.cargoNextest (commonArgs // {
108+
inherit cargoArtifacts;
109+
partitions = 1;
110+
partitionType = "count";
111+
});
112+
};
113+
114+
packages = {
115+
default = my-crate;
116+
my-crate-llvm-coverage = craneLibLLvmTools.cargoLlvmCov (commonArgs // {
117+
inherit cargoArtifacts;
118+
});
119+
};
120+
121+
apps.default = flake-utils.lib.mkApp {
122+
drv = my-crate;
123+
};
124+
125+
devShells.default = craneLib.devShell {
126+
# Inherit inputs from checks.
127+
checks = self.checks.${system};
128+
129+
# Additional dev-shell environment variables can be set directly
130+
# MY_CUSTOM_DEVELOPMENT_VAR = "something else";
131+
132+
# Extra inputs can be added here; cargo and rustc are provided by default.
133+
packages = with pkgs; [
134+
# pkgs.ripgrep
135+
rust-analyzer
136+
];
137+
};
138+
});
139+
}

src/day1.rs

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use std::io::{BufRead, BufReader, Read};
2+
3+
use eyre::{eyre, Context};
4+
5+
pub fn part1(input: impl Read) -> eyre::Result<u64> {
6+
let reader = BufReader::new(input);
7+
let mut sum = 0;
8+
for (num, line) in reader.lines().enumerate() {
9+
let line = line.wrap_err_with(|| format!("failed to read line {num}"))?;
10+
if line.is_empty() {
11+
continue;
12+
}
13+
let (mut first, mut last) = (None, None);
14+
for ch in line.chars() {
15+
if let Some(digit) = ch.to_digit(10) {
16+
first.get_or_insert(digit);
17+
last = digit.into();
18+
}
19+
}
20+
let first = first.ok_or_else(|| eyre!("no valid digits in line {num}"))?;
21+
let last = last.expect("if first is set, last should be too");
22+
sum += 10 * first as u64 + last as u64;
23+
}
24+
Ok(sum)
25+
}
26+
27+
// this is dumb, but it's probably the only algorithm that works as intended
28+
fn replace_in_order(s: &str) -> String {
29+
s.replace("one", "one1one")
30+
.replace("two", "two2two")
31+
.replace("three", "three3three")
32+
.replace("four", "four4four")
33+
.replace("five", "five5five")
34+
.replace("six", "six6six")
35+
.replace("seven", "seven7seven")
36+
.replace("eight", "eight8eight")
37+
.replace("nine", "nine9nine")
38+
}
39+
40+
pub fn part2(input: impl Read) -> eyre::Result<u64> {
41+
let reader = BufReader::new(input);
42+
let mut sum = 0;
43+
for (num, line) in reader.lines().enumerate() {
44+
let line = line.wrap_err_with(|| format!("failed to read line {num}"))?;
45+
if line.is_empty() {
46+
continue;
47+
}
48+
let replaced = replace_in_order(&line);
49+
let (mut first, mut last) = (None, None);
50+
for ch in replaced.chars() {
51+
if let Some(digit) = ch.to_digit(10) {
52+
first.get_or_insert(digit);
53+
last = digit.into();
54+
}
55+
}
56+
let first = first.ok_or_else(|| eyre!("no valid digits in line {num}"))?;
57+
let last = last.expect("if first is set, last should be too");
58+
sum += 10 * first as u64 + last as u64;
59+
}
60+
Ok(sum)
61+
}

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod day1;

0 commit comments

Comments
 (0)