i got this to work. i do not know how.
This commit is contained in:
parent
08cffbf2d2
commit
9a217a0202
@ -1,9 +1,8 @@
|
|||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
use std::cmp::{max, min, Ordering};
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
struct Brick {
|
struct Brick {
|
||||||
start: (i32, i32, i32),
|
start: (i32, i32, i32),
|
||||||
end: (i32, i32, i32),
|
end: (i32, i32, i32),
|
||||||
@ -31,24 +30,8 @@ impl Brick {
|
|||||||
.collect();
|
.collect();
|
||||||
if xes.len() != 1 { return xes; }
|
if xes.len() != 1 { return xes; }
|
||||||
if yes.len() != 1 { return yes; }
|
if yes.len() != 1 { return yes; }
|
||||||
if zes.len() != 1 { return zes; }
|
return zes;
|
||||||
return Vec::new();
|
|
||||||
}
|
}
|
||||||
fn shadow(&self) -> Vec<(i32, i32)> {
|
|
||||||
let mut squares = self.squares();
|
|
||||||
squares.dedup_by(|a, b| a.2 == b.2);
|
|
||||||
return squares.iter().map(|(x,y,_z)| (*x,*y)).collect();
|
|
||||||
}
|
|
||||||
fn top (&self) -> i32 {
|
|
||||||
return max(self.start.2, self.end.2);
|
|
||||||
}
|
|
||||||
fn bottom (&self) -> i32 {
|
|
||||||
return min(self.start.2, self.end.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compare_z(a: &Brick, b: &Brick) -> Ordering {
|
|
||||||
return a.start.2.cmp(&b.start.2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -63,138 +46,121 @@ fn main() {
|
|||||||
let file_path = &args[1];
|
let file_path = &args[1];
|
||||||
let contents = fs::read_to_string(file_path).expect("Should have been able to read the file");
|
let contents = fs::read_to_string(file_path).expect("Should have been able to read the file");
|
||||||
|
|
||||||
println!("soorting the bricks by z for some reason");
|
|
||||||
let mut bricks: Vec<Brick> = contents.lines().map(|x| x.parse().unwrap()).collect();
|
let mut bricks: Vec<Brick> = contents.lines().map(|x| x.parse().unwrap()).collect();
|
||||||
let mut bbs = bricks_by_shadow(&bricks);
|
let mut grid: HashMap<(i32, i32, i32), Brick> = HashMap::new();
|
||||||
bricks.sort_unstable_by(compare_z);
|
|
||||||
println!("{:?}", bricks);
|
|
||||||
|
|
||||||
println!("dropping bricks now");
|
|
||||||
let mut made_changes = true;
|
|
||||||
while made_changes {
|
|
||||||
let mut new_bricks: Vec<Brick> = Vec::new();
|
|
||||||
made_changes = false;
|
|
||||||
for brick in &bricks {
|
for brick in &bricks {
|
||||||
if made_changes {
|
for coordinate in brick.squares() {
|
||||||
new_bricks.push(brick.clone());
|
grid.insert(coordinate, brick.clone());
|
||||||
} else {
|
|
||||||
let tops = under(&brick, &bbs);
|
|
||||||
if let Some(highest) = tops.iter().max_by_key(|a| a.top()) {
|
|
||||||
let new_brick = lower(brick,highest);
|
|
||||||
if new_brick != brick.clone() {
|
|
||||||
new_bricks.push(new_brick);
|
|
||||||
made_changes = true;
|
|
||||||
} else {
|
|
||||||
new_bricks.push(brick.clone());
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
new_bricks.push(brick.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bricks = new_bricks;
|
|
||||||
bbs = bricks_by_shadow(&new_bricks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("bricks have been dropped: {bricks:?}");
|
//println!("Bricks: {bricks:?}");
|
||||||
|
|
||||||
println!("calculating brick shadows");
|
let mut changed_things = true;
|
||||||
let brick_shadows = bricks_by_shadow(&bricks);
|
while changed_things {
|
||||||
println!("there are {} brick shadows", brick_shadows.len());
|
changed_things = false;
|
||||||
|
for brick in &mut bricks {
|
||||||
|
let mut able_to_drop_1 = true;
|
||||||
|
for (x, y, z) in brick.squares() {
|
||||||
|
if z <= 0 { able_to_drop_1 = false; }
|
||||||
|
let runs_into_something =
|
||||||
|
grid.contains_key(&(x,y,z-1)) && !brick.squares().contains(&(x,y,z-1));
|
||||||
|
able_to_drop_1 = able_to_drop_1 && !runs_into_something;
|
||||||
|
}
|
||||||
|
|
||||||
|
if able_to_drop_1 {
|
||||||
|
for (x, y, z) in brick.squares() {
|
||||||
|
grid.remove(&(x,y,z));
|
||||||
|
}
|
||||||
|
brick.start.2 -= 1;
|
||||||
|
brick.end.2 -= 1;
|
||||||
|
|
||||||
|
for (x, y, z) in brick.squares() {
|
||||||
|
grid.insert((x, y, z), brick.clone());
|
||||||
|
}
|
||||||
|
//println!("dropping brick {brick:?}");
|
||||||
|
changed_things = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("bricks have been dropped:");// {bricks:?}");
|
||||||
|
|
||||||
|
let mut grid: HashMap<(i32, i32, i32), Brick> = HashMap::new();
|
||||||
|
for brick in &bricks {
|
||||||
|
for coordinate in brick.squares() {
|
||||||
|
grid.insert(coordinate, brick.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
println!("looking for disintegratbale bricks");
|
println!("looking for disintegratbale bricks");
|
||||||
|
|
||||||
let mut disintegratable_bricks: HashSet<Brick> = HashSet::new();
|
let mut disintegratable_bricks: HashSet<Brick> = HashSet::new();
|
||||||
for brick in &bricks {
|
for brick in &bricks {
|
||||||
let mut removable = true;
|
if dependent_bricks(&HashSet::from([*brick]), &grid).len() == 0 {
|
||||||
for other_brick in supported_by(brick, &brick_shadows) {
|
|
||||||
if supporting(other_brick, &brick_shadows).len() == 1 {
|
|
||||||
removable = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if removable {
|
|
||||||
disintegratable_bricks.insert(brick.clone());
|
disintegratable_bricks.insert(brick.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("The total number of disintegratable bricks is {}", disintegratable_bricks.len());
|
println!("The total number of disintegratable bricks is {}", disintegratable_bricks.len());
|
||||||
|
|
||||||
|
println!("now we're looking for chain reactions.");
|
||||||
|
let mut sum = 0;
|
||||||
|
for brick in &bricks {
|
||||||
|
let mut start = HashSet::from([*brick]);
|
||||||
|
let mut keep_going = true;
|
||||||
|
while keep_going {
|
||||||
|
keep_going = false;
|
||||||
|
let chain = dependent_bricks(&start, &grid);
|
||||||
|
if chain.len() != 0 { keep_going = true;}
|
||||||
|
start.extend(chain.iter());
|
||||||
|
}
|
||||||
|
start.remove(&brick);
|
||||||
|
//println!("found a brick we could remove to immediately chain {} bricks", start.len());
|
||||||
|
sum += start.len();
|
||||||
|
}
|
||||||
|
println!("sum is {sum}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bricks_by_shadow(bricks: &Vec<Brick>) -> HashMap<(i32, i32), Vec<&Brick>> {
|
fn bricks_relying_on(brick: &Brick, grid: &HashMap<(i32, i32, i32), Brick>) -> HashSet<Brick> {
|
||||||
let mut bricks_by_shadow: HashMap<(i32, i32), Vec<&Brick>> = HashMap::new();
|
|
||||||
for brick in bricks {
|
|
||||||
for coordinate in brick.shadow() {
|
|
||||||
if let Some(vector) = bricks_by_shadow.get_mut(&coordinate) {
|
|
||||||
vector.push(&brick)
|
|
||||||
} else {
|
|
||||||
bricks_by_shadow.insert(coordinate, Vec::new());
|
|
||||||
bricks_by_shadow.get_mut(&coordinate).unwrap().push(brick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bricks_by_shadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns a set of bricks under the specified brick
|
|
||||||
fn under<'a>(brick: &Brick,
|
|
||||||
shadow_bricks: &'a HashMap<(i32, i32), Vec<&Brick>>) -> HashSet<&'a Brick>
|
|
||||||
{
|
|
||||||
let mut unders: HashSet<&Brick> = HashSet::new();
|
|
||||||
for c in brick.shadow() {
|
|
||||||
let mut top_brick: Option<&Brick> = None;
|
|
||||||
for other_brick in shadow_bricks.get(&c).unwrap() {
|
|
||||||
if other_brick.top() < brick.bottom() {
|
|
||||||
if top_brick.is_none() {
|
|
||||||
top_brick = Some(other_brick);
|
|
||||||
} else if other_brick.top() > top_brick.unwrap().top() {
|
|
||||||
top_brick = Some(other_brick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if top_brick.is_some() {
|
|
||||||
unders.insert(top_brick.unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return unders;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn supporting<'a>(brick: &Brick, shadow_bricks: &'a HashMap<(i32, i32), Vec<&Brick>>) -> HashSet<&'a Brick> {
|
|
||||||
let mut candidates: Vec<&Brick> = Vec::new();
|
|
||||||
for coordinate in brick.shadow() {
|
|
||||||
candidates.extend(shadow_bricks.get(&coordinate).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut output = HashSet::new();
|
let mut output = HashSet::new();
|
||||||
for other_brick in candidates {
|
|
||||||
if other_brick.top() == brick.bottom() - 1 {
|
for (x, y, z) in brick.squares() {
|
||||||
|
if let Some(other_brick) = grid.get(&(x,y,z+1)) {
|
||||||
|
if other_brick != brick {
|
||||||
|
output.insert(other_brick.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bricks_relied_on_by(brick: &Brick, grid: &HashMap<(i32, i32, i32), Brick>) -> HashSet<Brick> {
|
||||||
|
let mut output: HashSet<Brick> = HashSet::new();
|
||||||
|
|
||||||
|
for (x, y, z) in brick.squares() {
|
||||||
|
if let Some(other_brick) = grid.get(&(x,y,z-1)) {
|
||||||
|
if other_brick != brick {
|
||||||
|
output.insert(other_brick.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dependent_bricks(missing_bricks: &HashSet<Brick>, grid: &HashMap<(i32, i32, i32), Brick>) -> HashSet<Brick> {
|
||||||
|
let mut output = HashSet::new();
|
||||||
|
|
||||||
|
for brick in missing_bricks {
|
||||||
|
let above = bricks_relying_on(brick, grid);
|
||||||
|
for other_brick in above {
|
||||||
|
let below = bricks_relied_on_by(&other_brick, grid);
|
||||||
|
if below.is_subset(missing_bricks) && !missing_bricks.contains(&other_brick) {
|
||||||
output.insert(other_brick);
|
output.insert(other_brick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
fn supported_by<'a>(brick: &Brick, shadow_bricks: &'a HashMap<(i32, i32), Vec<&Brick>>) -> HashSet<&'a Brick> {
|
|
||||||
let mut candidates: Vec<&Brick> = Vec::new();
|
|
||||||
for coordinate in brick.shadow() {
|
|
||||||
candidates.extend(shadow_bricks.get(&coordinate).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut output = HashSet::new();
|
|
||||||
for other_brick in candidates {
|
|
||||||
if other_brick.bottom() == brick.top() + 1 {
|
|
||||||
output.insert(other_brick);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower(brick: &Brick, below: &Brick) -> Brick {
|
|
||||||
let mut output = brick.clone();
|
|
||||||
let distance = brick.bottom() - below.top() - 1;
|
|
||||||
if distance > 0 {
|
|
||||||
output = Brick{start: (brick.start.0, brick.start.1, brick.start.2 - distance),
|
|
||||||
end: (brick.end.0, brick.end.1, brick.end.2 - 1)};
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user