|
|
|
|
@ -14,6 +14,7 @@ enum TokenType
|
|
|
|
|
struct Token
|
|
|
|
|
{
|
|
|
|
|
ttype: TokenType,
|
|
|
|
|
length: u32,
|
|
|
|
|
value: i32,
|
|
|
|
|
symbol: u8
|
|
|
|
|
}
|
|
|
|
|
@ -21,7 +22,7 @@ struct Token
|
|
|
|
|
|
|
|
|
|
fn main()
|
|
|
|
|
{
|
|
|
|
|
let data = load_data("data/test_input");
|
|
|
|
|
let data = load_data("data/input");
|
|
|
|
|
let schematic = parse_schematic(&data);
|
|
|
|
|
|
|
|
|
|
let mut sum = 0;
|
|
|
|
|
@ -52,68 +53,53 @@ fn has_symbol_neighbor(row: usize, col: usize, schematic: &Vec<Vec<Token>>) -> b
|
|
|
|
|
// TOP ROW
|
|
|
|
|
if row as isize - 1 >= 0
|
|
|
|
|
{
|
|
|
|
|
// TOP LEFT
|
|
|
|
|
if col as isize - 1 >= 0
|
|
|
|
|
{
|
|
|
|
|
if schematic[row - 1][col - 1].ttype == TokenType::Symbol
|
|
|
|
|
if check_row(row - 1, col, schematic, schematic[row][col].length as i32)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TOP CENTER
|
|
|
|
|
if schematic[row - 1][col].ttype == TokenType::Symbol
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TOP RIGHT
|
|
|
|
|
if col + 1 < schematic[row - 1].len()
|
|
|
|
|
{
|
|
|
|
|
if schematic[row - 1][col + 1].ttype == TokenType::Symbol
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// BOTTOM ROW
|
|
|
|
|
if row + 1 < schematic.len()
|
|
|
|
|
{
|
|
|
|
|
// BOTTOM LEFT
|
|
|
|
|
if col as isize - 1 >= 0
|
|
|
|
|
{
|
|
|
|
|
if schematic[row + 1][col - 1].ttype == TokenType::Symbol
|
|
|
|
|
if check_row(row + 1, col, schematic, schematic[row][col].length as i32)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BOTTOM CENTER
|
|
|
|
|
if schematic[row + 1][col].ttype == TokenType::Symbol
|
|
|
|
|
// CENTER ROW
|
|
|
|
|
if check_row(row, col, schematic, schematic[row][col].length as i32)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BOTTOM RIGHT
|
|
|
|
|
if col + 1 < schematic[row + 1].len()
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn check_row(row: usize, col: usize, schematic: &Vec<Vec<Token>>, len: i32) -> bool
|
|
|
|
|
{
|
|
|
|
|
if schematic[row + 1][col + 1].ttype == TokenType::Symbol
|
|
|
|
|
let mut offset: i32 = 0;
|
|
|
|
|
if col > 0
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
offset = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// LEFT
|
|
|
|
|
if col as isize - 1 > 0 && schematic[row][col - 1].ttype == TokenType::Symbol
|
|
|
|
|
while offset <= len as i32
|
|
|
|
|
{
|
|
|
|
|
return true
|
|
|
|
|
let col_off = (col as i32 + offset) as usize;
|
|
|
|
|
let l = schematic[row].len();
|
|
|
|
|
if col_off >= l
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RIGHT
|
|
|
|
|
if col + 1 < schematic[row].len() && schematic[row][col + 1].ttype == TokenType::Symbol
|
|
|
|
|
if schematic[row][col_off].ttype == TokenType::Symbol
|
|
|
|
|
{
|
|
|
|
|
return true
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
offset += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
@ -131,6 +117,7 @@ fn parse_schematic(input: &str) -> Vec<Vec<Token>>
|
|
|
|
|
match bytes[idx]
|
|
|
|
|
{
|
|
|
|
|
// NEW LINE
|
|
|
|
|
b'\r' => (),
|
|
|
|
|
b'\n' =>
|
|
|
|
|
{
|
|
|
|
|
parsed.push(Vec::new());
|
|
|
|
|
@ -138,14 +125,17 @@ fn parse_schematic(input: &str) -> Vec<Vec<Token>>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// EMPTY
|
|
|
|
|
b'.' => parsed[row].push(Token { ttype: TokenType::Empty, value: 0, symbol: b'.' }),
|
|
|
|
|
b'.' => parsed[row].push(Token { ttype: TokenType::Empty, length: 1, value: 0, symbol: b'.' }),
|
|
|
|
|
|
|
|
|
|
// NUMBER
|
|
|
|
|
b'0'..=b'9' =>
|
|
|
|
|
{
|
|
|
|
|
let mut num: String = String::new();
|
|
|
|
|
let mut len = 0;
|
|
|
|
|
while bytes[idx] >= b'0' && bytes[idx] <= b'9'
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
len += 1;
|
|
|
|
|
num.push(bytes[idx] as char);
|
|
|
|
|
idx += 1;
|
|
|
|
|
}
|
|
|
|
|
@ -155,11 +145,19 @@ fn parse_schematic(input: &str) -> Vec<Vec<Token>>
|
|
|
|
|
idx -= 1;
|
|
|
|
|
|
|
|
|
|
let num = num.parse::<i32>().expect(&format!("Failed to parse number: {} on line: {}", num, row));
|
|
|
|
|
parsed[row].push(Token { ttype: TokenType::Number, value: num, symbol: bytes[idx] });
|
|
|
|
|
parsed[row].push(Token { ttype: TokenType::Number, length: len, value: num, symbol: bytes[idx] });
|
|
|
|
|
|
|
|
|
|
// Pad out the grid with extra empties to account for the digits being
|
|
|
|
|
// squished into 1 grid space
|
|
|
|
|
for i in 1..len
|
|
|
|
|
{
|
|
|
|
|
parsed[row].push(Token { ttype: TokenType::Empty, length: 1, value: 0, symbol: b'.'});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SYMBOL
|
|
|
|
|
_ => parsed[row].push(Token { ttype: TokenType::Symbol, value: 0, symbol: bytes[idx] }),
|
|
|
|
|
_ => parsed[row].push(Token { ttype: TokenType::Symbol, length: 1, value: 0, symbol: bytes[idx] }),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
idx += 1;
|
|
|
|
|
|