i got this to work. i do not know how.

This commit is contained in:
Shoofle 2023-12-22 22:23:39 -05:00
parent 08cffbf2d2
commit 9a217a0202
155 changed files with 95 additions and 129 deletions

View File

@ -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.

Some files were not shown because too many files have changed in this diff Show More