inlcude_aoc is now the only method for importing data

Dieser Commit ist enthalten in:
Sebastian Tobie 2024-12-19 17:12:39 +01:00
Ursprung 313c6f4e3b
Commit 90d400eb37
21 geänderte Dateien mit 83 neuen und 232 gelöschten Zeilen

Datei anzeigen

@ -1,9 +1,8 @@
use advent_of_code::include_aoc;
use advent_of_code::strings::{convert_to_array, get_numbers, get_string_numbers}; use advent_of_code::strings::{convert_to_array, get_numbers, get_string_numbers};
#[allow(unused_imports)]
use advent_of_code::{include_data, include_example};
include_data!(DATAa 2023 01a); include_aoc!(DATAa, 2023, 01a);
include_data!(DATAb 2023 01b); include_aoc!(DATAb, 2023, 01b);
fn main() { fn main() {
let mut sum: u32 = 0; let mut sum: u32 = 0;

Datei anzeigen

@ -1,8 +1,7 @@
use advent_of_code::include_aoc;
use advent_of_code::strings::parsenumber; use advent_of_code::strings::parsenumber;
#[allow(unused_imports)]
use advent_of_code::{include_data, include_example};
include_example!(DATA 2023 02); include_aoc!(2023, 02);
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
struct Take { struct Take {

Datei anzeigen

@ -1,8 +1,7 @@
use advent_of_code::include_aoc;
use advent_of_code::strings::{convert_to_array, parsenumber}; use advent_of_code::strings::{convert_to_array, parsenumber};
#[allow(unused_imports)]
use advent_of_code::{include_data, include_example};
include_data!(DATA 2024 01); include_aoc!(2024, 01);
pub fn splitspace(input: &str) -> (u32, u32) { pub fn splitspace(input: &str) -> (u32, u32) {
println!("{}", input); println!("{}", input);

Datei anzeigen

@ -1,11 +1,10 @@
#[allow(unused_imports)] use advent_of_code::include_aoc;
use advent_of_code::{include_data, include_example};
use advent_of_code::{ use advent_of_code::{
strings::{convert_to_array, parsenumber}, strings::{convert_to_array, parsenumber},
KD, KD,
}; };
include_data!(DATA 2024 02); include_aoc!(2024, 02);
fn get_numbers(input: &str) -> Vec<u32> { fn get_numbers(input: &str) -> Vec<u32> {
input.split(char::is_whitespace).map(parsenumber).collect() input.split(char::is_whitespace).map(parsenumber).collect()

Datei anzeigen

@ -1,9 +1,8 @@
use advent_of_code::include_aoc;
use advent_of_code::strings::parsenumber; use advent_of_code::strings::parsenumber;
#[allow(unused_imports)]
use advent_of_code::{include_data, include_example};
use regex::{Captures, Regex}; use regex::{Captures, Regex};
include_data!(DATA 2024 03); include_aoc!(2024, 03);
fn parse_part1(input: Vec<Captures<'_>>) -> u32 { fn parse_part1(input: Vec<Captures<'_>>) -> u32 {
let mut sum = 0; let mut sum = 0;

Datei anzeigen

@ -1,14 +1,10 @@
#![allow(unused_variables, unused_assignments)] use advent_of_code::include_aoc;
#![allow(unused_imports)]
use std::ops::Add;
use advent_of_code::{include_data, include_example};
use advent_of_code::{ use advent_of_code::{
strings::{convert_to_array, line_to_char}, strings::{convert_to_array, line_to_char},
Kartesian, KartesianDirection, MaximumFromMap, Table, Kartesian, KartesianDirection, MaximumFromMap, Table,
}; };
include_data!(DATA 2024 04); include_aoc!(2024, 04);
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)] #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
struct TextPos { struct TextPos {

Datei anzeigen

@ -1,6 +1,5 @@
#[allow(unused_imports)]
use advent_of_code::{ use advent_of_code::{
include_data, include_example, include_aoc,
strings::{convert_to_array, line_to_char}, strings::{convert_to_array, line_to_char},
KartesianDirection, KartesianDirection,
}; };
@ -8,7 +7,7 @@ use advent_of_code::{Kartesian, Table};
use log::debug; use log::debug;
use num::Integer; use num::Integer;
include_data!(DATA 2024 06); include_aoc!(2024, 06);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct DirectionalKartesian<T: Integer> { struct DirectionalKartesian<T: Integer> {
@ -139,7 +138,7 @@ fn main() {
mod test { mod test {
use super::*; use super::*;
include_example!(EXAMPLE 2024 06); include_aoc!(EXAMPLE, 2024, 06, true);
#[test] #[test]
fn test_solution_1() { fn test_solution_1() {

Datei anzeigen

@ -1,15 +1,13 @@
#![cfg_attr(debug_assertions, allow(unused_imports))] use std::ops::{Add, AddAssign, Mul};
use std::ops::{Add, AddAssign, BitXor, Mul};
use advent_of_code::{ use advent_of_code::{
numberlength, numberlength,
strings::{convert_to_array, parsenumber}, strings::{convert_to_array, parsenumber},
}; };
use advent_of_code_macros::{include_data, include_example}; use advent_of_code_macros::include_aoc;
use log::*;
use num::{pow::Pow, Integer}; use num::{pow::Pow, Integer};
include_data!(DATA 2024 07); include_aoc!(2024, 07);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum Operation { enum Operation {

Datei anzeigen

@ -4,11 +4,10 @@ use advent_of_code::{
strings::{convert_to_array, line_to_char}, strings::{convert_to_array, line_to_char},
Kartesian, Table, Kartesian, Table,
}; };
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
use log::*; use log::*;
include_data!(DATA 2024 08); include_aoc!(2024, 08);
const EMPTY: char = '.'; const EMPTY: char = '.';

Datei anzeigen

@ -1,8 +1,7 @@
use advent_of_code::strings::char_to_num; use advent_of_code::strings::char_to_num;
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
include_data!(DATA 2024 09); include_aoc!(2024, 09);
type Disk = Vec<Option<u64>>; type Disk = Vec<Option<u64>>;

Datei anzeigen

@ -2,10 +2,9 @@ use advent_of_code::{
strings::{char_to_num, convert_to_array}, strings::{char_to_num, convert_to_array},
Kartesian, KartesianDirection, MaximumFromMap, Kartesian, KartesianDirection, MaximumFromMap,
}; };
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
include_data!(DATA 2024 10); include_aoc!(2024, 10);
type Trail = Vec<Kartesian<u32>>; type Trail = Vec<Kartesian<u32>>;
type Map = Vec<Vec<u32>>; type Map = Vec<Vec<u32>>;
@ -96,7 +95,7 @@ fn main() {
mod test { mod test {
use super::*; use super::*;
include_example!(MAP 2024 10); include_aoc!(MAP, 2024, 10, true);
const SCORE: u32 = 36; const SCORE: u32 = 36;
#[test] #[test]

Datei anzeigen

@ -1,4 +1,3 @@
#![allow(unused)]
use std::collections::HashMap; use std::collections::HashMap;
use advent_of_code::{ use advent_of_code::{
@ -6,11 +5,10 @@ use advent_of_code::{
strings::{convert_to_array, parsenumber}, strings::{convert_to_array, parsenumber},
ExtendedOption, ExtendedOption,
}; };
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
use num::Integer; use num::Integer;
include_data!(DATA 2024 11); include_aoc!(2024, 11);
const BILLIONS: u64 = 1000_000_000; const BILLIONS: u64 = 1000_000_000;

Datei anzeigen

@ -1,13 +1,11 @@
#![allow(unused)] use std::ops::Mul;
use std::ops::{Mul, Not};
use advent_of_code::{strings::convert_to_array, ExtendedOption, Kartesian, KartesianDirection, KartesianIterator, MaximumFromMap, Table, KD}; use advent_of_code::{strings::convert_to_array, Kartesian, MaximumFromMap, Table, KD};
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
use log::*; use log::*;
use num::{iter, Integer}; use num::Integer;
include_data!(DATA 2024 12); include_aoc!(2024, 12);
type Minimap = Vec<Vec<bool>>; type Minimap = Vec<Vec<bool>>;
@ -269,11 +267,11 @@ fn main() {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
include_example!(MAP_A 2024 12a); include_aoc!(MAP_A, 2024, 12a, true);
include_example!(MAP_B 2024 12b); include_aoc!(MAP_B, 2024, 12b, true);
include_example!(MAP_C 2024 12c); include_aoc!(MAP_C, 2024, 12c, true);
include_example!(MAP_D 2024 12d); include_aoc!(MAP_D, 2024, 12d, true);
include_example!(MAP_E 2024 12f); include_aoc!(MAP_E, 2024, 12f, true);
#[test] #[test]
fn test_fence_a_perimeter() { fn test_fence_a_perimeter() {

Datei anzeigen

@ -2,10 +2,9 @@ use advent_of_code::{
strings::{convert_to_array, parsenumber}, strings::{convert_to_array, parsenumber},
Kartesian, Velocity, KD, Kartesian, Velocity, KD,
}; };
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
include_data!(DATA 2024 14); include_aoc!(2024, 14);
fn parse_robot(line: &str) -> (Kartesian<u32>, Velocity<u32>) { fn parse_robot(line: &str) -> (Kartesian<u32>, Velocity<u32>) {
let mut dir = KD::None; let mut dir = KD::None;

Datei anzeigen

@ -3,11 +3,10 @@ use advent_of_code::{
strings::{convert_to_array, line_to_char}, strings::{convert_to_array, line_to_char},
Kartesian, KartesianDirection, Map, Kartesian, KartesianDirection, Map,
}; };
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
use log::debug; use log::debug;
include_data!(DATA 2024 15); include_aoc!(DATA 2024 15);
const WALL: char = '#'; const WALL: char = '#';
const ROBOT: char = '@'; const ROBOT: char = '@';

Datei anzeigen

@ -5,10 +5,9 @@ use advent_of_code::{
strings::{convert_to_array, line_to_char}, strings::{convert_to_array, line_to_char},
Kartesian, KartesianDirection, Map, KD, Kartesian, KartesianDirection, Map, KD,
}; };
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
include_data!(DATA 2024 16); include_aoc!(DATA 2024 16);
const START: Option<char> = Some('S'); const START: Option<char> = Some('S');
const WALL: Option<char> = Some('#'); const WALL: Option<char> = Some('#');

Datei anzeigen

@ -1,10 +1,9 @@
use advent_of_code::strings::{convert_to_array, parsenumber}; use advent_of_code::strings::{convert_to_array, parsenumber};
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
use log::*; use log::*;
use thousands::Separable; use thousands::Separable;
include_data!(DATA 2024 17); include_aoc!(DATA 2024 17);
const ADV: u64 = 0; const ADV: u64 = 0;
const BXL: u64 = 1; const BXL: u64 = 1;

Datei anzeigen

@ -4,11 +4,10 @@ use advent_of_code::{
strings::{convert_to_array, parsenumber}, strings::{convert_to_array, parsenumber},
Kartesian, Map, ToCoords, KD, Kartesian, Map, ToCoords, KD,
}; };
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
use log::*; use log::*;
include_data!(DATA 2024 18); include_aoc!(DATA 2024 18);
const HEIGHT: usize = 71; const HEIGHT: usize = 71;
const WIDTH: usize = HEIGHT; const WIDTH: usize = HEIGHT;

Datei anzeigen

@ -1,11 +1,9 @@
use advent_of_code::strings::convert_to_array; use advent_of_code::strings::convert_to_array;
#[allow(unused_imports)] use advent_of_code_macros::include_aoc;
use advent_of_code_macros::{include_data, include_example};
include_data!(DATA 2024 19); include_aoc!(2024, 19);
fn test_pattern(pattern: String, parts: Vec<String>) -> bool { fn test_pattern(pattern: String, parts: Vec<String>) -> bool {
false false
} }
@ -17,14 +15,14 @@ fn main() {
let mut possible = 0; let mut possible = 0;
for design in designs { for design in designs {
let mut candidates = vec![design]; let mut candidates = vec![design];
'designloop :loop { 'designloop: loop {
let mut new = Vec::with_capacity(candidates.len()); let mut new = Vec::with_capacity(candidates.len());
for possibility in candidates { for possibility in candidates {
for part in patterns.clone() { for part in patterns.clone() {
if possibility.starts_with(part.as_str()) { if possibility.starts_with(part.as_str()) {
if possibility.len() == part.len() { if possibility.len() == part.len() {
println!("Found design"); println!("Found design");
possible+=1; possible += 1;
break 'designloop; break 'designloop;
} }
new.push(possibility[part.len()..].to_owned()); new.push(possibility[part.len()..].to_owned());

Datei anzeigen

@ -2,7 +2,7 @@ use std::fs::{self, read_to_string};
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::{parse, LitBool, Result}; use syn::{parse, token::Comma, LitBool, Result};
use syn::{ use syn::{
parse::{Parse, ParseStream}, parse::{Parse, ParseStream},
spanned::Spanned, spanned::Spanned,
@ -13,23 +13,6 @@ const DATA_DIR: &str = "data";
const EXAMPLE_DIR: &str = "examples"; const EXAMPLE_DIR: &str = "examples";
const VAR_NAME: &str = "DATA"; const VAR_NAME: &str = "DATA";
#[derive(Debug, Clone)]
struct IncludeData {
var: String,
year: Option<String>,
day: Option<String>,
}
impl Default for IncludeData {
fn default() -> Self {
IncludeData {
var: VAR_NAME.into(),
year: None,
day: None,
}
}
}
fn get_text<T: Spanned>(item: T) -> Result<String> { fn get_text<T: Spanned>(item: T) -> Result<String> {
let span = item.span(); let span = item.span();
match span.source_text() { match span.source_text() {
@ -42,119 +25,8 @@ fn get_text<T: Spanned>(item: T) -> Result<String> {
} }
} }
impl Parse for IncludeData {
fn parse(input: ParseStream) -> Result<Self> {
let mut data = IncludeData::default();
if input.peek(Ident) && !input.peek(LitInt) {
data.var = get_text(input.parse::<Ident>().unwrap())?;
}
data.year = Some(get_text(input.parse::<LitInt>()?)?);
data.day = Some(get_text(input.parse::<Lit>()?)?);
Ok(data)
}
}
fn canonicalize(dir: &str, input: IncludeData) -> Option<String> {
let pathname = format!("{}/{}/{}.txt", dir, input.year.unwrap(), input.day.unwrap());
match fs::canonicalize(pathname) {
Ok(canon) => {
if canon.is_file() {
match canon.to_str() {
Some(c) => Some(c.to_string()),
None => None,
}
} else {
None
}
},
Err(_) => None,
}
}
/// includes Data from Advent of code
/// ```ignore (cannot-doctest-external-file-dependency)
/// include_data!(DATA 2015 01)
/// // or
/// include_data!(2015 01)
///
/// fn main() {
/// print!("{DATA}");
/// }
/// ```
/// The Equivalent is
/// ```ignore (cannot-doctest-external-file-dependency)
/// static DATA: &str = include_str!("../../../data/2015/01.txt");
/// ```
#[proc_macro]
pub fn include_data(data: TokenStream) -> TokenStream {
let input = match parse::<IncludeData>(data) {
Ok(include) => include,
Err(error) => return error.into_compile_error().into(),
};
let ident = format_ident!("{}", input.var);
let mut comment: String;
if input.day.is_some() && input.year.is_some() {
comment = "Data from the data dir".into();
let mut path = canonicalize(DATA_DIR, input.clone());
if path.is_none() {
comment = "Data from the examples".into();
path = canonicalize(EXAMPLE_DIR, input)
}
match path {
Some(p) => {
return quote! {
#[doc = #comment]
const #ident: &str = include_str!(#p).trim_ascii();
}
.into();
},
None => comment = "failed to get data from the paths".into(),
}
} else {
comment = format!("Failed to get the year({:?}) or day({:?}) falling back to default", input.year, input.day);
}
quote! {
#[doc = #comment]
const #ident: &str = "";
}
.into()
}
/// Same as include_data!, but it only gets data from the example directory.
/// This is useful for testing the examples, even when Data from the AOC is available
#[proc_macro]
pub fn include_example(data: TokenStream) -> TokenStream {
let input = match parse::<IncludeData>(data) {
Ok(include) => include,
Err(error) => return error.into_compile_error().into(),
};
let ident = format_ident!("{}", input.var);
let mut comment: String;
if input.day.is_some() && input.year.is_some() {
comment = "Data from the Example dir".into();
match canonicalize(EXAMPLE_DIR, input.clone()) {
Some(p) => {
return quote! {
#[doc = #comment]
const #ident: &str = include_str!(#p).trim_ascii();
}
.into();
},
None => comment = "failed to get data from the path".into(),
}
} else {
comment = format!("Failed to get the year({:?}) or day({:?}) falling back to default", input.year, input.day);
}
quote! {
#[doc = #comment]
const #ident: &str = "";
}
.into()
}
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
struct NewIncludeData { struct IncludeData {
var: String, var: String,
year: String, year: String,
day: String, day: String,
@ -162,20 +34,25 @@ struct NewIncludeData {
parts: usize, parts: usize,
} }
impl Parse for NewIncludeData { impl Parse for IncludeData {
fn parse(input: ParseStream) -> Result<Self> { fn parse(input: ParseStream) -> Result<Self> {
let mut v = Self::default(); let mut v = Self::default();
v.var = if input.peek(Ident) && !input.peek(LitInt) { v.var = if input.peek(Ident) && !input.peek(LitInt) {
get_text(input.parse::<Ident>().unwrap())? let t = get_text(input.parse::<Ident>().unwrap())?;
input.parse::<Comma>()?;
t
} else { } else {
VAR_NAME.to_string() VAR_NAME.to_string()
}; };
v.year = get_text(input.parse::<LitInt>()?)?; v.year = get_text(input.parse::<LitInt>()?)?;
input.parse::<Comma>()?;
v.day = get_text(input.parse::<Lit>()?)?; v.day = get_text(input.parse::<Lit>()?)?;
if input.peek(LitBool) { if input.peek2(LitBool) {
input.parse::<Comma>()?;
v.example = input.parse::<LitBool>()?.value; v.example = input.parse::<LitBool>()?.value;
} }
if input.peek(LitInt) { if input.peek2(LitInt) {
input.parse::<Comma>()?;
v.parts = input.parse::<LitInt>()?.base10_parse()?; v.parts = input.parse::<LitInt>()?.base10_parse()?;
} }
if v.parts == 0 { if v.parts == 0 {
@ -185,12 +62,12 @@ impl Parse for NewIncludeData {
} }
} }
fn fallback(input: NewIncludeData, message: String) -> TokenStream { fn fallback(input: IncludeData, message: String) -> TokenStream {
if input.parts != 1 { if input.parts != 1 {
let postfixes = (1..=input.parts).map(|i| format_ident!("{}_{}", input.var, i)); let postfixes = (1..=input.parts).map(|i| format_ident!("{}_{}", input.var, i));
quote! { quote! {
#[doc = #message]
#( #(
///
const #postfixes: &str = ""; const #postfixes: &str = "";
)* )*
} }
@ -198,7 +75,7 @@ fn fallback(input: NewIncludeData, message: String) -> TokenStream {
} else { } else {
let name = format_ident!("{}", input.var); let name = format_ident!("{}", input.var);
quote! { quote! {
/// #name #[doc = #message]
const #name: &str = ""; const #name: &str = "";
} }
.into() .into()
@ -213,7 +90,7 @@ fn fallback(input: NewIncludeData, message: String) -> TokenStream {
/// and the last is the amount of parts in the file, if it is greater than 1 the first argument is treated as an Prefix. /// and the last is the amount of parts in the file, if it is greater than 1 the first argument is treated as an Prefix.
#[proc_macro] #[proc_macro]
pub fn include_aoc(data: TokenStream) -> TokenStream { pub fn include_aoc(data: TokenStream) -> TokenStream {
let input = match parse::<NewIncludeData>(data) { let input = match parse::<IncludeData>(data) {
Ok(data) => data, Ok(data) => data,
Err(error) => return error.into_compile_error().into(), Err(error) => return error.into_compile_error().into(),
}; };