From 7e407c3dd7d76869cca56c095caad7d8207feb40 Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Mon, 1 Dec 2025 23:19:14 +0200 Subject: [PATCH] feat: init with day1 part one --- .cargo/config.toml | 3 + .envrc | 1 + .gitignore | 4 + Cargo.lock | 23 ++++++ Cargo.toml | 3 + crates/common/Cargo.toml | 7 ++ crates/common/src/lib.rs | 68 ++++++++++++++++ crates/day1/Cargo.toml | 7 ++ crates/day1/src/main.rs | 69 ++++++++++++++++ flake.lock | 170 +++++++++++++++++++++++++++++++++++++++ flake.nix | 72 +++++++++++++++++ justfile | 8 ++ rust-toolchain.toml | 2 + 13 files changed, 437 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 crates/common/Cargo.toml create mode 100644 crates/common/src/lib.rs create mode 100644 crates/day1/Cargo.toml create mode 100644 crates/day1/src/main.rs create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 justfile create mode 100644 rust-toolchain.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..d29d6c3 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[target.x86_64-unknown-linux-gnu] +linker = "clang" +rustflags = ["-C", "link-arg=-fuse-ld=mold"] diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..c4b17d7 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use_flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7fd16a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.direnv/ +/input/ +/target/ +/.pre-commit-config.yaml diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..31151e3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,23 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "common" +version = "0.1.0" +dependencies = [ + "sc", +] + +[[package]] +name = "day1" +version = "0.1.0" +dependencies = [ + "common", +] + +[[package]] +name = "sc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "010e18bd3bfd1d45a7e666b236c78720df0d9a7698ebaa9c1c559961eb60a38b" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..86c4459 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,3 @@ +[workspace] +resolver = "3" +members = ["crates/common", "crates/day1"] diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml new file mode 100644 index 0000000..83facb6 --- /dev/null +++ b/crates/common/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "common" +version = "0.1.0" +edition = "2024" + +[dependencies] +sc = "0.2" diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs new file mode 100644 index 0000000..46e1f20 --- /dev/null +++ b/crates/common/src/lib.rs @@ -0,0 +1,68 @@ +use core::fmt::{self, Write}; + +use sc::syscall; + +const STDIN: i32 = 0; +const STDOUT: i32 = 1; + +pub fn write(msg: &str) { + unsafe { + syscall!(WRITE, STDOUT, msg.as_ptr(), msg.len()); + } +} + +pub fn read(buf_ptr: *const u8, buf_len: usize) { + unsafe { + syscall!(READ, STDIN, buf_ptr, buf_len); + } +} + +pub struct Format<'a> { + buf: &'a mut [u8], + len: usize, +} + +impl<'a> Format<'a> { + pub fn new(buf: &'a mut [u8]) -> Self { + Self { buf, len: 0 } + } +} + +impl<'a> fmt::Write for Format<'a> { + fn write_str(&mut self, s: &str) -> fmt::Result { + if self.len > self.buf.len() { + write("1"); + return Err(fmt::Error); + } + let remaining_buf = &mut self.buf[self.len..]; + let bytes = s.as_bytes(); + let write_num = core::cmp::min(bytes.len(), remaining_buf.len()); + remaining_buf[..write_num].copy_from_slice(&bytes[..write_num]); + self.len += bytes.len(); + if write_num < bytes.len() { + write("2"); + return Err(fmt::Error); + } + + Ok(()) + } +} + +pub fn format(buf: &mut [u8], args: fmt::Arguments<'_>) { + let mut f = Format::new(buf); + f.write_fmt(args).unwrap(); +} + +pub fn format_str<'a>(buf: &'a mut [u8], args: fmt::Arguments<'_>) -> &'a str { + let mut f = Format::new(buf); + f.write_fmt(args).unwrap(); + str::from_utf8(buf).unwrap() +} + +#[macro_export] +macro_rules! print { + ($len:expr, $($args:tt)*) => { + let mut buf = [0u8; $len]; + common::write(common::format_str(&mut buf, core::format_args!($($args)*))); + }; +} diff --git a/crates/day1/Cargo.toml b/crates/day1/Cargo.toml new file mode 100644 index 0000000..386e48b --- /dev/null +++ b/crates/day1/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day1" +version = "0.1.0" +edition = "2024" + +[dependencies] +common = { path = "../common" } diff --git a/crates/day1/src/main.rs b/crates/day1/src/main.rs new file mode 100644 index 0000000..947f601 --- /dev/null +++ b/crates/day1/src/main.rs @@ -0,0 +1,69 @@ +#![no_std] + +use common::{print, read}; + +fn main() { + let buf = [0u8; 65000]; + read(buf.as_ptr(), buf.len()); + let input = str::from_utf8(&buf).unwrap(); + let result_one = one(input); + let result_two = two(input); + print!(32, "one: {}\ntwo: {}\n", result_one, result_two); +} + +fn one(input: &str) -> u16 { + let mut zeros: u16 = 0; + let mut pos: i16 = 50; + for ins in input.split("\n") { + // Last entry is all unused bytes. + if ins.len() > 10 { + continue; + } + + let (direction, amount_s) = ins.split_at(1); + let amount = amount_s.parse::().unwrap(); + + match direction { + "R" => { + pos += amount; + while pos > 99 { + pos -= 100; + } + } + "L" => { + pos -= amount; + while pos < 0 { + pos += 100; + } + } + _ => unreachable!(), + } + + if pos == 0 { + zeros += 1; + } + } + + zeros +} + +#[cfg(test)] +mod test { + use super::*; + + const EXAMPLE_INPUT: &str = r#"L68 +L30 +R48 +L5 +R60 +L55 +L1 +L99 +R14 +L82"#; + + #[test] + fn example() { + assert_eq!(one(EXAMPLE_INPUT), 3); + } +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..9bc7aab --- /dev/null +++ b/flake.lock @@ -0,0 +1,170 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1761588595, + "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1763759067, + "narHash": "sha256-LlLt2Jo/gMNYAwOgdRQBrsRoOz7BPRkzvNaI/fzXi2Q=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "2cccadc7357c0ba201788ae99c4dfa90728ef5e0", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1764557259, + "narHash": "sha256-fhD/QUtJ0HKs3oLvfnD+/SrBV5Y7YEkCYnDjOVUjLys=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "0d70460758949966e91d9ecb823b821f963cefbb", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1761765539, + "narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "719359f4562934ae99f5443f20aa06c2ffff91fc", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1759417375, + "narHash": "sha256-O7eHcgkQXJNygY6AypkF9tFhsoDQjpNEojw3eFs73Ow=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "dc704e6102e76aad573f63b74c742cd96f8f1e6c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1763988335, + "narHash": "sha256-QlcnByMc8KBjpU37rbq5iP7Cp97HvjRP0ucfdh+M4Qc=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "50b9238891e388c9fdc6a5c49e49c42533a1b5ce", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1764557621, + "narHash": "sha256-kX5PoY8hQZ80+amMQgOO9t8Tc1JZ70gYRnzaVD4AA+o=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "93316876c2229460a5d6f5f052766cc4cef538ce", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..b5ef53e --- /dev/null +++ b/flake.nix @@ -0,0 +1,72 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-parts.url = "github:hercules-ci/flake-parts"; + pre-commit-hooks.url = "github:cachix/git-hooks.nix"; + rust-overlay.url = "github:oxalica/rust-overlay"; + }; + + outputs = inputs @ {self, ...}: + inputs.flake-parts.lib.mkFlake {inherit inputs;} { + systems = ["x86_64-linux"]; + perSystem = { + pkgs, + system, + ... + }: let + toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + in { + _module.args.pkgs = import inputs.nixpkgs { + inherit system; + overlays = [inputs.rust-overlay.overlays.default]; + }; + + checks.pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run { + src = ./.; + hooks = { + # Nix formatting + alejandra.enable = true; + + # Toml formatting + taplo.enable = true; + + # Rust formatting and linting + rustfmt = { + enable = true; + packageOverrides = { + cargo = toolchain; + rustfmt = toolchain; + }; + }; + clippy = { + enable = true; + packageOverrides = { + cargo = toolchain; + clippy = toolchain; + }; + settings = { + denyWarnings = true; + }; + }; + }; + }; + + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; + [ + clang + mold + + just + ] + ++ [ + toolchain + self.checks.${system}.pre-commit-check.enabledPackages + ]; + shellHook = '' + ${self.checks.${system}.pre-commit-check.shellHook} + ''; + }; + }; + }; +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..855f828 --- /dev/null +++ b/justfile @@ -0,0 +1,8 @@ +_default: + just --list + +init day: + cargo init crates/day{{day}} + +solve day: + cat input/day{{day}}.txt | cargo run day{{day}} -- diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..1a35d66 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.91" -- 2.44.1