Day 1 done!
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "advent2020"
|
||||
version = "0.1.0"
|
||||
authors = ["Adam Wick <awick@uhsure.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
200
inputs/day1.txt
Normal file
200
inputs/day1.txt
Normal file
@@ -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
|
||||
6
inputs/day1_test.txt
Normal file
6
inputs/day1_test.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
1721
|
||||
979
|
||||
366
|
||||
299
|
||||
675
|
||||
1456
|
||||
127
src/bin/accounting.rs
Normal file
127
src/bin/accounting.rs
Normal file
@@ -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<u64> {
|
||||
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<usize> {
|
||||
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(_) => {}
|
||||
}
|
||||
}
|
||||
32
src/errors.rs
Normal file
32
src/errors.rs
Normal file
@@ -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);
|
||||
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod errors;
|
||||
Reference in New Issue
Block a user