在上述第二步中,一开始筛选条件为“若本位数字下标大于最后一位下标,则更新”(即 number_last_match > last_index),然而当有且仅有第一位为数字时,不会更新。改为大于等于即可。这样例确实有股 OI 味儿,得学会自己出~
rustpub fn part_one(input: &str) -> Option<u32> {
// separate input into lines
let lines = input.lines();
let mut sum = 0;
let numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
for line in lines {
let mut first_number = 0;
let mut first_index: usize = line.len() + 1;
let mut last_number = 0;
let mut last_index: usize = 0;
for i in 0..10 {
if let Some(number_first_match) = line.find(numbers[i]) {
if number_first_match < first_index {
first_number = i;
first_index = number_first_match;
}
}
if let Some(number_last_match) = line.rfind(numbers[i]) {
if number_last_match >= last_index { // If the only number is at [0], use this to record it
last_number = i;
last_index = number_last_match;
}
}
}
sum += first_number * 10 + last_number;
}
Some(sum as u32)
}
pubfnpart_one(input: &str)-> Option<u32>{// separate input into lines
letlines=input.lines();letmutsum=0;letnumbers=["0","1","2","3","4","5","6","7","8","9"];forlineinlines{letmutfirst_number=0;letmutfirst_index: usize=line.len()+1;letmutlast_number=0;letmutlast_index: usize=0;foriin0..10{ifletSome(number_first_match)=line.find(numbers[i]){ifnumber_first_match<first_index{first_number=i;first_index=number_first_match;}}ifletSome(number_last_match)=line.rfind(numbers[i]){ifnumber_last_match>=last_index{// If the only number is at [0], use this to record it
last_number=i;last_index=number_last_match;}}}sum+=first_number*10+last_number;}Some(sumasu32)}
pubfnpart_two(input: &str)-> Option<u32>{// separate input into lines
letlines=input.lines();letmutsum=0;letnumbers=["0","1","2","3","4","5","6","7","8","9"];letword_numbers=["zero","one","two","three","four","five","six","seven","eight","nine",];forlineinlines{letmutfirst_number=0;letmutfirst_index: usize=line.len()+1;letmutlast_number=0;letmutlast_index: usize=0;foriin0..10{ifletSome(word_first_match)=line.find(word_numbers[i]){ifword_first_match<first_index{first_number=i;first_index=word_first_match;}}ifletSome(word_last_match)=line.rfind(word_numbers[i]){ifword_last_match>=last_index{last_number=i;last_index=word_last_match;}}ifletSome(number_first_match)=line.find(numbers[i]){ifnumber_first_match<first_index{first_number=i;first_index=number_first_match;}}ifletSome(number_last_match)=line.rfind(numbers[i]){ifnumber_last_match>=last_index{last_number=i;last_index=number_last_match;}}}sum+=first_number*10+last_number;}Some(sumasu32)}
Day 2
Part 1
每行代表一次 game,每次 game 进行多次随机抽取,共有 12 个红色、13 个绿色、14 个蓝色,问有哪几次 game 中,所有抽取都符合实际情况,也就是每次抽取的每种颜色都不超过实际数量。
plaintextGame 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
1
2
3
4
5
Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green
rustpub fn part_one(input: &str) -> Option<u32> {
let mut id_sum: u32 = 0;
'game: for (index, game) in input.lines().enumerate() {
// split "Game X: yyyyyyyyy"
let content = game.split(": ").collect::<Vec<&str>>()[1];
// split "X blue, Y red; XX green, YY yellow"
let gotchas = content.split("; ").collect::<Vec<&str>>();
let (mut red, mut green, mut blue) = (0, 0, 0);
// Per gotcha: maximum 12 red, 13 green, 14 blue
for gotcha in gotchas {
let colors = gotcha.split(", ").collect::<Vec<&str>>();
for color in colors {
// color: "X blue/green/red"
let color = color.split(" ").collect::<Vec<&str>>();
let count = color[0].parse::<u32>().unwrap();
match color[1] {
"blue" => blue = count,
"green" => green = count,
"red" => red = count,
_ => panic!("Unknown color: {}", color[1]),
}
}
if red > 12 || green > 13 || blue > 14 {
// this game is invalid, skip to next game
continue 'game;
}
}
id_sum += (index + 1) as u32;
}
Some(id_sum)
}
pubfnpart_one(input: &str)-> Option<u32>{letmutid_sum: u32=0;'game: for(index,game)ininput.lines().enumerate(){// split "Game X: yyyyyyyyy"
letcontent=game.split(": ").collect::<Vec<&str>>()[1];// split "X blue, Y red; XX green, YY yellow"
letgotchas=content.split("; ").collect::<Vec<&str>>();let(mutred,mutgreen,mutblue)=(0,0,0);// Per gotcha: maximum 12 red, 13 green, 14 blue
forgotchaingotchas{letcolors=gotcha.split(", ").collect::<Vec<&str>>();forcolorincolors{// color: "X blue/green/red"
letcolor=color.split(" ").collect::<Vec<&str>>();letcount=color[0].parse::<u32>().unwrap();matchcolor[1]{"blue"=>blue=count,"green"=>green=count,"red"=>red=count,_=>panic!("Unknown color: {}",color[1]),}}ifred>12||green>13||blue>14{// this game is invalid, skip to next game
continue'game;}}id_sum+=(index+1)asu32;}Some(id_sum)}
Part 2
Part 2 求出对每次 game,在能满足抽出数量的情况下,三种颜色各自的数量最小值。将这三个值相乘,再将每次 game 的乘积相加得到结果。
其实也一样,初始化一个最小值,然后对每一抽更新一下最小值。
rustpub fn part_two(input: &str) -> Option<u32> {
let mut id_sum: u32 = 0;
for game in input.lines() {
// split "Game X: yyyyyyyyy"
let content = game.split(": ").collect::<Vec<&str>>()[1];
// split "X blue, Y red; XX green, YY yellow"
let gotchas = content.split("; ").collect::<Vec<&str>>();
let (mut red, mut green, mut blue) = (0, 0, 0);
// Get the maximum of each color
for gotcha in gotchas {
let colors = gotcha.split(", ").collect::<Vec<&str>>();
for color in colors {
// color: "X blue/green/red"
let color = color.split(" ").collect::<Vec<&str>>();
let count = color[0].parse::<u32>().unwrap();
match color[1] {
"blue" => blue = cmp::max(blue, count),
"green" => green = cmp::max(green, count),
"red" => red = cmp::max(red, count),
_ => panic!("Unknown color: {}", color[1]),
}
}
}
let color_pow = red * green * blue;
id_sum += color_pow;
}
Some(id_sum)
}
pubfnpart_two(input: &str)-> Option<u32>{letmutid_sum: u32=0;forgameininput.lines(){// split "Game X: yyyyyyyyy"
letcontent=game.split(": ").collect::<Vec<&str>>()[1];// split "X blue, Y red; XX green, YY yellow"
letgotchas=content.split("; ").collect::<Vec<&str>>();let(mutred,mutgreen,mutblue)=(0,0,0);// Get the maximum of each color
forgotchaingotchas{letcolors=gotcha.split(", ").collect::<Vec<&str>>();forcolorincolors{// color: "X blue/green/red"
letcolor=color.split(" ").collect::<Vec<&str>>();letcount=color[0].parse::<u32>().unwrap();matchcolor[1]{"blue"=>blue=cmp::max(blue,count),"green"=>green=cmp::max(green,count),"red"=>red=cmp::max(red,count),_=>panic!("Unknown color: {}",color[1]),}}}letcolor_pow=red*green*blue;id_sum+=color_pow;}Some(id_sum)}
rustpub fn part_one(input: &str) -> Option<u32> {
// convert lines into a char matrix
let lines = input.lines();
let mut sum = 0;
let mut matrix: Vec<Vec<char>> = Vec::new();
for line in lines {
matrix.push(line.chars().collect());
}
let mut curr = 0; // current number
let mut is_part_number = false; // current number adjacent to a symbol
// iterate through the matrix
for (x, line) in matrix.iter().enumerate() {
for (y, ch) in line.iter().enumerate() {
if *ch >= '0' && *ch <= '9' {
// ch is a number
curr = curr * 10 + (*ch as u32 - '0' as u32);
if !is_part_number {
// check char in 8 directions
if x > 0 && is_symbol(matrix[x - 1][y]) {
is_part_number = true;
} else if y > 0 && is_symbol(matrix[x][y - 1]) {
is_part_number = true;
} else if x < matrix.len() - 1 && is_symbol(matrix[x + 1][y]) {
is_part_number = true;
} else if y < matrix[x].len() - 1 && is_symbol(matrix[x][y + 1]) {
is_part_number = true;
} else if x > 0 && y > 0 && is_symbol(matrix[x - 1][y - 1]) {
is_part_number = true;
} else if x > 0 && y < matrix[x].len() - 1 && is_symbol(matrix[x - 1][y + 1]) {
is_part_number = true;
} else if x < matrix.len() - 1 && y > 0 && is_symbol(matrix[x + 1][y - 1]) {
is_part_number = true;
} else if x < matrix.len() - 1
&& y < matrix[x].len() - 1
&& is_symbol(matrix[x + 1][y + 1])
{
is_part_number = true;
}
}
} else {
// ch is a letter
if curr != 0 {
if is_part_number {
sum += curr;
println!("Add {}", curr)
}
curr = 0;
is_part_number = false;
}
}
}
// at the end of each line (including last), add the number
if curr != 0 {
if is_part_number {
sum += curr;
println!("Add {}", curr)
}
curr = 0;
is_part_number = false;
}
}
Some(sum)
}
fn is_symbol(char: char) -> bool {
(char < '0' || char > '9') && char != '.'
}
pubfnpart_one(input: &str)-> Option<u32>{// convert lines into a char matrix
letlines=input.lines();letmutsum=0;letmutmatrix: Vec<Vec<char>>=Vec::new();forlineinlines{matrix.push(line.chars().collect());}letmutcurr=0;// current number
letmutis_part_number=false;// current number adjacent to a symbol
// iterate through the matrix
for(x,line)inmatrix.iter().enumerate(){for(y,ch)inline.iter().enumerate(){if*ch>='0'&&*ch<='9'{// ch is a number
curr=curr*10+(*chasu32-'0'asu32);if!is_part_number{// check char in 8 directions
ifx>0&&is_symbol(matrix[x-1][y]){is_part_number=true;}elseify>0&&is_symbol(matrix[x][y-1]){is_part_number=true;}elseifx<matrix.len()-1&&is_symbol(matrix[x+1][y]){is_part_number=true;}elseify<matrix[x].len()-1&&is_symbol(matrix[x][y+1]){is_part_number=true;}elseifx>0&&y>0&&is_symbol(matrix[x-1][y-1]){is_part_number=true;}elseifx>0&&y<matrix[x].len()-1&&is_symbol(matrix[x-1][y+1]){is_part_number=true;}elseifx<matrix.len()-1&&y>0&&is_symbol(matrix[x+1][y-1]){is_part_number=true;}elseifx<matrix.len()-1&&y<matrix[x].len()-1&&is_symbol(matrix[x+1][y+1]){is_part_number=true;}}}else{// ch is a letter
ifcurr!=0{ifis_part_number{sum+=curr;println!("Add {}",curr)}curr=0;is_part_number=false;}}}// at the end of each line (including last), add the number
ifcurr!=0{ifis_part_number{sum+=curr;println!("Add {}",curr)}curr=0;is_part_number=false;}}Some(sum)}fnis_symbol(char: char)-> bool{(char<'0'||char>'9')&&char!='.'}
pubfnpart_two(input: &str)-> Option<u32>{// convert lines into a char matrix
letlines=input.lines();letmutsum=0;letmutmatrix: Vec<Vec<char>>=Vec::new();forlineinlines{matrix.push(line.chars().collect());}for(x,line)inmatrix.iter().enumerate(){for(y,ch)inline.iter().enumerate(){if*ch=='*'{// find numbers nearby
let(mutup_left,mutup,mutup_right,mutleft,mutright,mutdown_left,mutdown,mutdown_right,)=(false,false,false,false,false,false,false,false);letmutpow=1;ifx>0{ify>0{ifis_digit(matrix[x-1][y-1]){up_left=true;}}ifis_digit(matrix[x-1][y]){up=true;}ify<matrix[x].len()-1{ifis_digit(matrix[x-1][y+1]){up_right=true;}}}ify>0&&is_digit(matrix[x][y-1]){left=true;}ify<matrix[x].len()-1&&is_digit(matrix[x][y+1]){right=true;}ifx<matrix.len()-1{ify>0{ifis_digit(matrix[x+1][y-1]){down_left=true;}}ifis_digit(matrix[x+1][y]){down=true;}ify<matrix[x].len()-1{ifis_digit(matrix[x+1][y+1]){down_right=true;}}}// get number count
letmutcount=0;match(up_left,up,up_right){(false,false,true)|(true,false,false)|(false,true,false)=>{count+=1}(true,true,false)|(false,true,true)=>{count+=1;up=false;// to prevent calculating value twice
}(true,false,true)=>count+=2,(true,true,true)=>{count+=1;up_left=false;// as above
up_right=false;}(false,false,false)=>{}}ifleft{count+=1;}ifright{count+=1;}match(down_left,down,down_right){(false,false,true)|(true,false,false)|(false,true,false)=>{count+=1}(true,true,false)|(false,true,true)=>{count+=1;down=false;}(true,false,true)=>count+=2,(true,true,true)=>{count+=1;down_left=false;down_right=false;}(false,false,false)=>{}}println!("({}, {}) has {} numbers",x,y,count);ifcount!=2{// not a "gear"
continue;}ifup_left{pow*=get_value(&matrix[x-1],y-1);}ifup{pow*=get_value(&matrix[x-1],y);}ifup_right{pow*=get_value(&matrix[x-1],y+1);}ifleft{pow*=get_value(&matrix[x],y-1);}ifright{pow*=get_value(&matrix[x],y+1);}ifdown_left{pow*=get_value(&matrix[x+1],y-1);}ifdown{pow*=get_value(&matrix[x+1],y);}ifdown_right{pow*=get_value(&matrix[x+1],y+1);}sum+=pow;println!("Adding {} at ({}, {})",pow,x,y);}}}Some(sumasu32)}fnis_digit(char: char)-> bool{char>='0'&&char<='9'}// Since the value stays only on one line, we can just use one line.
fnget_value(matrix: &Vec<char>,y: usize)-> i32{letmutstart_y=y;letmutval=0;whilestart_y>0&&is_digit(matrix[start_y-1]){start_y-=1;}whilestart_y<matrix.len()&&is_digit(matrix[start_y]){val=val*10+(matrix[start_y]asi32-'0'asi32);start_y+=1;}val}
rustpub fn part_one(input: &str) -> Option<u32> {
let lines = input.lines();
let mut sum: u32 = 0;
for line in lines{
let mut win = 0;
// process strings
let content = line.split(": ").collect_vec()[1]; // cut "Card X: "
let result = content.split(" | ").collect_vec();
let winning_numbers = result[0];
let own_numbers = result[1];
let winning_set: HashSet<u32> = winning_numbers
.split_whitespace()
.map(|x| x.parse::<u32>().unwrap())
.collect();
let own_numbers: Vec<u32> = own_numbers
.split_whitespace()
.map(|x| x.parse::<u32>().unwrap())
.collect();
for number in own_numbers.iter() {
if winning_set.contains(number) {
win += 1;
}
}
if win > 0 {
sum += 2_u32.pow(win - 1);
}
}
Some(sum)
}
rustpub fn part_two(input: &str) -> Option<u32> {
let lines = input.lines().collect_vec();
let mut sum = 0; // cards scratched in total
let mut cards_count = vec![1; lines.len()]; // every card has 1 copy
let contents: Vec<&str> = lines
.iter()
.map(|x| x.split(": ").collect_vec()[1])
.collect_vec();
let results = contents
.iter()
.map(|x| x.split(" | ").collect_vec())
.collect_vec();
let winning_sets: Vec<HashSet<u32>> = results
.iter()
.map(|x| x[0])
.map(|x| {
x.split_whitespace()
.map(|y| y.parse::<u32>().unwrap()) // Numbers that gets point for each card
.collect()
})
.collect_vec();
let own_numbers: Vec<Vec<u32>> = results
.iter()
.map(|x| x[1])
.map(|x| {
x.split_whitespace()
.map(|y| y.parse::<u32>().unwrap()) // Numbers that gets point for each card
.collect()
})
.collect_vec();
for index in 0..cards_count.len() {
println!("Has {} of card {}", cards_count[index], index);
if cards_count[index] == 0 {
break;
}
sum += cards_count[index];
let winning_set = &winning_sets[index];
let own_numbers = &own_numbers[index];
let mut win = 0;
print!("Intersect numbers: ");
for number in own_numbers.iter() {
if winning_set.contains(number) {
win += 1;
print!("{} ", number);
}
}
println!("Win {} cards", win,);
for i in 0..win {
cards_count[index + 1 + i] += cards_count[index];
println!(
"Add {} copies of card {}",
cards_count[index],
index + 2 + i
)
}
}
Some(sum)
}
pubfnpart_two(input: &str)-> Option<u32>{letlines=input.lines().collect_vec();letmutsum=0;// cards scratched in total
letmutcards_count=vec![1;lines.len()];// every card has 1 copy
letcontents: Vec<&str>=lines.iter().map(|x|x.split(": ").collect_vec()[1]).collect_vec();letresults=contents.iter().map(|x|x.split(" | ").collect_vec()).collect_vec();letwinning_sets: Vec<HashSet<u32>>=results.iter().map(|x|x[0]).map(|x|{x.split_whitespace().map(|y|y.parse::<u32>().unwrap())// Numbers that gets point for each card
.collect()}).collect_vec();letown_numbers: Vec<Vec<u32>>=results.iter().map(|x|x[1]).map(|x|{x.split_whitespace().map(|y|y.parse::<u32>().unwrap())// Numbers that gets point for each card
.collect()}).collect_vec();forindexin0..cards_count.len(){println!("Has {} of card {}",cards_count[index],index);ifcards_count[index]==0{break;}sum+=cards_count[index];letwinning_set=&winning_sets[index];letown_numbers=&own_numbers[index];letmutwin=0;print!("Intersect numbers: ");fornumberinown_numbers.iter(){ifwinning_set.contains(number){win+=1;print!("{} ",number);}}println!("Win {} cards",win,);foriin0..win{cards_count[index+1+i]+=cards_count[index];println!("Add {} copies of card {}",cards_count[index],index+2+i)}}Some(sum)}
rust// old
if soil >= mapping.src_start
&& soil < mapping.src_start + mapping.length
// new
if soil >= mapping.src_start
&& soil
< mapping
.src_start
.checked_add(mapping.length)
.unwrap_or(u32::MAX)
1
2
3
4
5
6
7
8
9
10
// old
ifsoil>=mapping.src_start&&soil<mapping.src_start+mapping.length// new
ifsoil>=mapping.src_start&&soil<mapping.src_start.checked_add(mapping.length).unwrap_or(u32::MAX)
rustpub fn part_two(input: &str) -> Option<u32> {
let items = input.split("\n\n").collect::<Vec<_>>();
let seeds = items[0]
.strip_prefix("seeds: ")
.unwrap()
.split_whitespace()
.map(|s| s.parse::<u32>().unwrap())
.collect::<Vec<_>>()
.chunks(2)
.map(|x| (x[0], x[0] + x[1]))
.collect::<Vec<_>>();
let process_mapping = |x: &str| -> Vec<Mapping> {
let mut result = x
.lines()
.skip(1)
.map(|line| {
let mut parts = line.split_whitespace();
let dst_start = parts.next().unwrap().parse::<u32>().unwrap();
let src_start = parts.next().unwrap().parse::<u32>().unwrap();
let length = parts.next().unwrap().parse::<u32>().unwrap();
Mapping {
dst_start,
src_start,
length,
}
})
.collect::<Vec<_>>();
result.sort_by(|a, b| a.src_start.cmp(&b.src_start));
result
};
let seed_to_soil = process_mapping(items[1]);
let soil_to_fertilizer = process_mapping(items[2]);
let fertilizer_to_water = process_mapping(items[3]);
let water_to_light = process_mapping(items[4]);
let light_to_temperature = process_mapping(items[5]);
let temperature_to_humidity = process_mapping(items[6]);
let humidity_to_location = process_mapping(items[7]);
let mut min_position = u32::MAX;
let transform_ranges =
|original_ranges: Vec<(u32, u32)>, mappings: &Vec<Mapping>| -> Vec<(u32, u32)> {
let mut result = vec![];
'range: for range in original_ranges.iter() {
let mut range_start = range.0; // "cut" the range from start
let range_end = range.1; // include start, exclude end
for mapping in mappings.iter() {
let mapping_start = mapping.src_start;
let mapping_end = mapping
.src_start
.checked_add(mapping.length)
.unwrap_or(u32::MAX);
if range_start < mapping_start {
// remove the part before the mapping, use original range start
if range_end < mapping_start {
// current range has ended
result.push((range_start, range_end));
break;
} else {
// current range has some overlap with current mapping
result.push((range_start, mapping_start));
range_start = mapping_start;
}
}
if range_start >= mapping_end {
continue;
}
// now it at least has some overlap
let new_start = cmp::max(range_start, mapping_start)
.wrapping_sub(mapping.src_start)
.wrapping_add(mapping.dst_start);
let new_end = cmp::min(range_end, mapping_end)
.wrapping_sub(mapping.src_start)
.wrapping_add(mapping.dst_start);
result.push((new_start, new_end));
if range_end <= mapping_end {
// current range has ended
continue 'range;
} else {
// current range has some left
range_start = mapping_end;
}
}
// if still has some left, add it
if range_start < range_end {
result.push((range_start, range_end));
}
}
result
};
for seed in seeds.iter() {
let seed_ranges = vec![(seed.0, seed.1)];
let soil_ranges = transform_ranges(seed_ranges, &seed_to_soil);
let fertilizer_ranges = transform_ranges(soil_ranges, &soil_to_fertilizer);
let water_ranges = transform_ranges(fertilizer_ranges, &fertilizer_to_water);
let light_ranges = transform_ranges(water_ranges, &water_to_light);
let temperature_ranges = transform_ranges(light_ranges, &light_to_temperature);
let humidity_ranges = transform_ranges(temperature_ranges, &temperature_to_humidity);
let location_ranges = transform_ranges(humidity_ranges, &humidity_to_location);
for location_range in location_ranges.iter() {
if location_range.0 < min_position {
min_position = location_range.0;
}
}
}
Some(min_position)
}
pubfnpart_two(input: &str)-> Option<u32>{letitems=input.split("\n\n").collect::<Vec<_>>();letseeds=items[0].strip_prefix("seeds: ").unwrap().split_whitespace().map(|s|s.parse::<u32>().unwrap()).collect::<Vec<_>>().chunks(2).map(|x|(x[0],x[0]+x[1])).collect::<Vec<_>>();letprocess_mapping=|x: &str|-> Vec<Mapping>{letmutresult=x.lines().skip(1).map(|line|{letmutparts=line.split_whitespace();letdst_start=parts.next().unwrap().parse::<u32>().unwrap();letsrc_start=parts.next().unwrap().parse::<u32>().unwrap();letlength=parts.next().unwrap().parse::<u32>().unwrap();Mapping{dst_start,src_start,length,}}).collect::<Vec<_>>();result.sort_by(|a,b|a.src_start.cmp(&b.src_start));result};letseed_to_soil=process_mapping(items[1]);letsoil_to_fertilizer=process_mapping(items[2]);letfertilizer_to_water=process_mapping(items[3]);letwater_to_light=process_mapping(items[4]);letlight_to_temperature=process_mapping(items[5]);lettemperature_to_humidity=process_mapping(items[6]);lethumidity_to_location=process_mapping(items[7]);letmutmin_position=u32::MAX;lettransform_ranges=|original_ranges: Vec<(u32,u32)>,mappings: &Vec<Mapping>|-> Vec<(u32,u32)>{letmutresult=vec![];'range: forrangeinoriginal_ranges.iter(){letmutrange_start=range.0;// "cut" the range from start
letrange_end=range.1;// include start, exclude end
formappinginmappings.iter(){letmapping_start=mapping.src_start;letmapping_end=mapping.src_start.checked_add(mapping.length).unwrap_or(u32::MAX);ifrange_start<mapping_start{// remove the part before the mapping, use original range start
ifrange_end<mapping_start{// current range has ended
result.push((range_start,range_end));break;}else{// current range has some overlap with current mapping
result.push((range_start,mapping_start));range_start=mapping_start;}}ifrange_start>=mapping_end{continue;}// now it at least has some overlap
letnew_start=cmp::max(range_start,mapping_start).wrapping_sub(mapping.src_start).wrapping_add(mapping.dst_start);letnew_end=cmp::min(range_end,mapping_end).wrapping_sub(mapping.src_start).wrapping_add(mapping.dst_start);result.push((new_start,new_end));ifrange_end<=mapping_end{// current range has ended
continue'range;}else{// current range has some left
range_start=mapping_end;}}// if still has some left, add it
ifrange_start<range_end{result.push((range_start,range_end));}}result};forseedinseeds.iter(){letseed_ranges=vec![(seed.0,seed.1)];letsoil_ranges=transform_ranges(seed_ranges,&seed_to_soil);letfertilizer_ranges=transform_ranges(soil_ranges,&soil_to_fertilizer);letwater_ranges=transform_ranges(fertilizer_ranges,&fertilizer_to_water);letlight_ranges=transform_ranges(water_ranges,&water_to_light);lettemperature_ranges=transform_ranges(light_ranges,&light_to_temperature);lethumidity_ranges=transform_ranges(temperature_ranges,&temperature_to_humidity);letlocation_ranges=transform_ranges(humidity_ranges,&humidity_to_location);forlocation_rangeinlocation_ranges.iter(){iflocation_range.0<min_position{min_position=location_range.0;}}}Some(min_position)}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]enumCard2{A=14,K=13,Q=12,J=1,T=10,Nine=9,Eight=8,Seven=7,Six=6,Five=5,Four=4,Three=3,Two=2,}#[derive(Debug)]structHand2{hand: Vec<Card2>,bid: u32,}implPartialOrdforHand2{fnpartial_cmp(&self,other: &Self)-> Option<Ordering>{Some(self.cmp(other))}}implPartialEqforHand2{fneq(&self,other: &Self)-> bool{self.bid==other.bid}}implEqforHand2{}fnmerge_j(dict: &mutHashMap<&Card2,i32>){// get the number of j and card with largest count
letmutj_count=0;letmutmax_count=0;letmutmax_card=None;letdict_clone=dict.clone();for(card,count)indict_clone.iter(){ifcard==&&Card2::J{j_count=*count;}elseif*count>max_count{max_count=*count;max_card=Some(card);}}dict.remove(&Card2::J);ifletSome(max_card)=max_card{*dict.entry(max_card).or_insert(0)+=j_count;}else{dict.insert(&Card2::J,j_count);}}implOrdforHand2{fncmp(&self,other: &Self)-> Ordering{letmutself_dict=self.hand.iter().fold(HashMap::new(),|mutacc,card|{*acc.entry(card).or_insert(0)+=1;acc});letmutother_dict=other.hand.iter().fold(HashMap::new(),|mutacc,card|{*acc.entry(card).or_insert(0)+=1;acc});merge_j(&mutself_dict);merge_j(&mutother_dict);letself_weight=self_dict.iter().map(|(_,count)|matchcount{5=>30,4=>20,3=>10,2=>5,1=>1,_=>panic!("Invalid card count"),}).sum::<u32>();letother_weight=other_dict.iter().map(|(_,count)|matchcount{5=>30,4=>20,3=>10,2=>5,1=>1,_=>panic!("Invalid card count"),}).sum::<u32>();ifself_weight>other_weight{returnOrdering::Greater;}elseifself_weight<other_weight{returnOrdering::Less;}else{// compare `Card`s in descending order
for(self_card,other_card)inself.hand.iter().zip(other.hand.iter()){ifself_card>other_card{returnOrdering::Greater;}elseifself_card<other_card{returnOrdering::Less;}}}Ordering::Equal}}pubfnpart_two(input: &str)-> Option<u32>{letmuthands: Vec<Hand2>=input.lines().map(|line|{letmutparts=line.split_whitespace();lethand=parts.next().unwrap().chars().map(|c|matchc{'A'=>Card2::A,'K'=>Card2::K,'Q'=>Card2::Q,'J'=>Card2::J,'T'=>Card2::T,'9'=>Card2::Nine,'8'=>Card2::Eight,'7'=>Card2::Seven,'6'=>Card2::Six,'5'=>Card2::Five,'4'=>Card2::Four,'3'=>Card2::Three,'2'=>Card2::Two,_=>panic!("Invalid card"),}).collect::<Vec<_>>();letbid=parts.next().unwrap().parse().unwrap();Hand2{hand,bid}}).collect();hands.sort();letmutwinnings: u32=0;foriin1..=hands.len(){winnings+=hands[i-1].bid*iasu32;println!("#{}: {:?}",i,hands[i-1]);}Some(winnings)}
rustpub fn part_one(input: &str) -> Option<u32> {
let mut steps: u32 = 0;
let mut curr_pos = "AAA";
let lines = input.lines().collect::<Vec<_>>();
let seq = lines[0];
let mut direction = HashMap::<&str, (&str, &str)>::new();
for line in lines[2..].iter() {
// AAA = (BBB,CCC)
let mut line = line.split(" = ");
let key = line.next().unwrap();
let mut line = line.next().unwrap().split(", ");
let left = line.next().unwrap();
let right = line.next().unwrap();
direction.insert(key, (&left[1..], &right[0..3]));
}
while curr_pos != "ZZZ" {
let index: usize = steps as usize % seq.len();
curr_pos = match seq.chars().nth(index).unwrap() {
'R' => direction.get(curr_pos).unwrap().1,
'L' => direction.get(curr_pos).unwrap().0,
_ => curr_pos,
};
steps += 1;
}
Some(steps)
}
rustfn diff(nums: &Vec<i32>) -> u32 {
let mut degree: u32 = 0;
if nums.iter().all(|&x| x == nums[0]) {
// special case
return 0;
}
let mut diff = nums.clone();
loop {
// 0 3 6 9 12 15
// -> 3 3 3 3 3
// -> 0 0 0 0
// then, times = 1; this is y=ax+b
diff = diff
.iter()
.tuple_windows()
.map(|(a, b)| b - a)
.collect_vec();
degree += 1;
// if all diff is same, return times
if diff.iter().all(|&x| x == diff[0]) {
return degree;
}
}
}
pub fn part_one(input: &str) -> Option<i64> {
let lines = input.lines().collect::<Vec<_>>();
let mut sum = 0;
for line in lines {
let nums = line
.split_whitespace()
.map(|n| n.parse::<i32>().unwrap())
.collect_vec();
let degree = diff(&nums);
let x_values = (0..nums.len()).map(|x| x as f64).collect_vec();
let y_values = nums.iter().map(|&x| x as f64).collect_vec();
let coefficients = polyfit_rs::polyfit(&x_values, &y_values, degree as usize).unwrap();
let mut next = 0.0;
// next = f(len(nums))
for i in 0..degree as usize + 1 {
next += coefficients[i] * (nums.len() as f64).powi(i as i32);
}
println!("{}", next.round() as i64);
sum += next.round() as i64;
}
Some(sum)
}
fndiff(nums: &Vec<i32>)-> u32{letmutdegree: u32=0;ifnums.iter().all(|&x|x==nums[0]){// special case
return0;}letmutdiff=nums.clone();loop{// 0 3 6 9 12 15
// -> 3 3 3 3 3
// -> 0 0 0 0
// then, times = 1; this is y=ax+b
diff=diff.iter().tuple_windows().map(|(a,b)|b-a).collect_vec();degree+=1;// if all diff is same, return times
ifdiff.iter().all(|&x|x==diff[0]){returndegree;}}}pubfnpart_one(input: &str)-> Option<i64>{letlines=input.lines().collect::<Vec<_>>();letmutsum=0;forlineinlines{letnums=line.split_whitespace().map(|n|n.parse::<i32>().unwrap()).collect_vec();letdegree=diff(&nums);letx_values=(0..nums.len()).map(|x|xasf64).collect_vec();lety_values=nums.iter().map(|&x|xasf64).collect_vec();letcoefficients=polyfit_rs::polyfit(&x_values,&y_values,degreeasusize).unwrap();letmutnext=0.0;// next = f(len(nums))
foriin0..degreeasusize+1{next+=coefficients[i]*(nums.len()asf64).powi(iasi32);}println!("{}",next.round()asi64);sum+=next.round()asi64;}Some(sum)}
Day 10
Part 1
给出的一张图描述了管道的连接情况,其中有个 S 点在管道的环路中,求出从某个点出发沿主(含 S 的)环路最远的距离。基本就是相当于要我们把环路找出来。