commit 1cb05050b365047f65367bc6054f00502c323c62 Author: Adam Wick Date: Tue Dec 1 08:39:50 2020 -0800 Day 1 done! diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..869df07 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..5fb6ac0 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "advent2020" +version = "0.1.0" +authors = ["Adam Wick "] +edition = "2018" + +[dependencies] diff --git a/inputs/day1.txt b/inputs/day1.txt new file mode 100644 index 0000000..13585a4 --- /dev/null +++ b/inputs/day1.txt @@ -0,0 +1,200 @@ +1772 +1065 +1827 +1671 +1181 +1915 +1657 +1632 +1053 +1546 +1039 +1388 +1698 +1174 +1275 +1250 +1988 +1078 +1075 +1958 +1617 +1387 +1543 +1965 +1867 +1771 +1755 +1331 +1677 +1935 +1488 +911 +1001 +1516 +1949 +1626 +1083 +1402 +1223 +1179 +2001 +1790 +1551 +1117 +1990 +1968 +1532 +1999 +1175 +1126 +1869 +1666 +1753 +513 +1349 +1139 +1941 +1823 +1647 +1835 +1943 +1459 +1833 +1398 +1877 +1625 +1749 +1631 +1864 +1826 +1499 +1336 +1264 +1091 +1558 +1321 +1754 +1729 +1585 +1740 +1767 +1774 +1164 +1318 +1930 +1236 +1995 +1611 +1319 +1361 +1119 +1563 +1578 +1047 +1797 +1787 +1038 +1921 +1656 +1898 +1828 +1727 +1825 +2010 +536 +1395 +1865 +1882 +1638 +1954 +1565 +1296 +1723 +1187 +60 +1130 +1102 +1963 +1048 +1493 +1795 +472 +1496 +1278 +1444 +1889 +860 +1975 +1961 +1070 +1570 +1495 +1644 +1881 +1293 +1090 +1906 +1385 +1549 +1143 +1195 +2004 +1397 +1032 +1681 +2000 +1574 +1400 +1911 +1868 +1917 +1872 +1696 +1086 +1291 +1761 +1703 +1202 +1486 +1705 +1924 +1186 +1676 +1615 +1951 +1556 +1604 +1534 +2002 +1334 +1109 +1108 +1713 +1422 +1909 +1418 +1592 +1887 +1037 +1568 +1914 +1780 +1929 +1973 +1684 +1581 +1148 +1931 +1619 +1082 +1166 +1913 +1312 +1330 +1540 +1841 +1977 +1769 +1691 +1821 diff --git a/inputs/day1_test.txt b/inputs/day1_test.txt new file mode 100644 index 0000000..0bb977d --- /dev/null +++ b/inputs/day1_test.txt @@ -0,0 +1,6 @@ +1721 +979 +366 +299 +675 +1456 \ No newline at end of file diff --git a/src/bin/accounting.rs b/src/bin/accounting.rs new file mode 100644 index 0000000..706ea6e --- /dev/null +++ b/src/bin/accounting.rs @@ -0,0 +1,127 @@ +use advent2020::errors::TopLevelError; +use std::cmp::Ordering; +use std::env; +use std::fs; +use std::str::FromStr; + +fn real_main() -> Result<(), TopLevelError> { + let mut numbers = Vec::new(); + + for argument in env::args().skip(2) { + let contents = fs::read_to_string(argument)?; + for line in contents.lines() { + match u64::from_str(line) { + Err(e) => eprintln!("Skipping line with '{}': {}", line, e), + Ok(v) => numbers.push(v), + } + } + } + + // sort the arguments for faster searching + numbers.sort_unstable(); + + let mut found_right = false; + let mut found_middle_right = false; + + 'top: for i in 0..numbers.len() { + let left = numbers[i]; + + if !found_right { + if let Some(right) = find_right(&numbers, left, &[i]) { + println!( + "Found {} + {} = 2020, so {} * {} = {}", + left, + right, + left, + right, + left * right + ); + found_right = true; + } + } + + if !found_middle_right { + for j in 0..numbers.len() { + if i != j { + let middle = numbers[j]; + + if left + middle > 2020 { + continue; + } + + if let Some(right) = find_right(&numbers, left + middle, &[i, j]) { + println!( + "Found {} + {} + {} = 2020, so {} * {} * {} = {}", + left, + middle, + right, + left, + middle, + right, + left * middle * right + ); + found_middle_right = true; + continue 'top; + } + } + } + } + } + + if found_right && found_middle_right { + Ok(()) + } else { + Err(TopLevelError::NoSolutionFound) + } +} + +fn find_right(items: &[u64], left: u64, avoid: &[usize]) -> Option { + let mut low_tide = 0; + let mut high_tide = items.len() - 1; + + loop { + let target = next_target(low_tide, high_tide, avoid)?; + let sum = left + items[target]; + + match sum.cmp(&2020) { + Ordering::Less => low_tide = target + 1, + Ordering::Greater if target == 0 => return None, + Ordering::Greater => high_tide = target - 1, + Ordering::Equal => return Some(items[target]), + } + } +} + +fn next_target(low_index: usize, high_index: usize, avoid: &[usize]) -> Option { + if low_index > high_index { + return None; + } + + let midpoint = (low_index + high_index) / 2; + let mut worker = midpoint; + + while worker >= low_index { + if avoid.contains(&worker) { + worker -= 1; + } else { + return Some(worker); + } + } + + while worker <= high_index { + if avoid.contains(&worker) { + worker += 1; + } else { + return Some(worker); + } + } + + None +} + +fn main() { + match real_main() { + Err(e) => eprintln!("ERROR: {}", e), + Ok(_) => {} + } +} diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..4592d8b --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,32 @@ +use std::fmt; +use std::io; + +pub enum TopLevelError { + IOError(io::Error), + NoSolutionFound, + UnknownError, +} + +impl fmt::Display for TopLevelError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + TopLevelError::IOError(e) => write!(f, "IO error: {}", e), + TopLevelError::NoSolutionFound => write!(f, "No solution found."), + TopLevelError::UnknownError => { + write!(f, "Unknown error occurred; this shouldn't be possible.") + } + } + } +} + +macro_rules! convert_error { + ($type: ty, $pattern: ident) => { + impl From<$type> for TopLevelError { + fn from(x: $type) -> TopLevelError { + TopLevelError::$pattern(x) + } + } + }; +} + +convert_error!(io::Error, IOError); diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..629e98f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod errors;