Advent of Code 2022 Day 1 - Calorie Counting
Natcha Luangaroonchai
โดยปกติแล้วกวางเรนเดียร์ของซานต้าจะกินอาหารกวางเรนเดียร์เป็นประจำ แต่พวกมันต้องการพลังเวทย์มนต์จำนวนมากในการส่งของขวัญวันคริสต์มาส เพื่อการนั้นแล้ว ของว่างสุดโปรดของพวกมันคือผลดวงดาวชนิดพิเศษที่เติบโตในป่าลึกเท่านั้น เหล่าเอลฟ์ได้พาคุณเดินทางประจำปีไปยังป่าที่ผลไม้ชนิดนี้ขึ้นอยู่
สารบัญ
TL;DR
การจะจัดหาพลังงานเวทย์มนตร์ให้เพียงพอนั้น คณะสำรวจจำเป็นต้องได้รับดวงดาวอย่างน้อย 50 ดวงภายในวันที่ 25 ธันวาคม แม้พวกเอลฟ์จะยืนยันว่าในป่ามีผลไม้มากมาย แต่คุณก็เก็บผลไม้ที่เจอระหว่างทางเผื่อไว้ด้วย
ป่าที่คุณมาสำรวจนั้นรกชัฏยากต่อการใช้ยานพาหนะหรือแม้แต่ทางอากาศ การเดินทางของพวกเอลฟ์จึงมักจะเป็นการเดินทางด้วยเท้า เมื่อเรือของคุณเข้าใกล้ฝั่ง เหล่าเอลฟ์จะเริ่มนับสต๊อกเสบียงของพวกเขา สิ่งสำคัญอย่างแรกคือเสบียงอาหารที่เอลฟ์แต่ละคนพกติดตัวมา
เหล่าเอลฟ์จะผลัดกันเขียนจำนวนแคลอรีที่มีอยู่ในอาหาร ของว่าง อาหารปันส่วน ฯลฯ ที่พวกเขานำมาด้วย บรรทัดละหนึ่งรายการ เอลฟ์แต่ละคนจะแยกเสบียงของตนเองออกจากสินค้าคงคลังของเอลฟ์ก่อนหน้า ด้วยบรรทัดว่าง
ตัวอย่างเช่น
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
ตัวเลขที่เห็นคือรายการพลังงานของอาหารที่เอลฟ์แต่ละคนมี จากรายการข้างต้นแปลว่ามีเอลฟ์ห้าคนในลิสต์
เอลฟ์คนแรกพกอาหารที่ให้พลังงาน 1000, 2000 และ 3000 แคลอรี่ ซึ่งผลรวมทั้งหมดจะได้ 6000 แคลอรี่
เอลฟ์คนที่สองพกอาหารที่ให้พลังงาน 4000 แคลอรี่
เอลฟ์คนที่สามพกอาหารที่ให้พลังงาน 5000 และ 6000 แคลอรี่ ซึ่งผลรวมทั้งหมดจะได้ 11000 แคลอรี่
เอลฟ์คนที่สี่พกอาหารที่ให้พลังงาน 7000, 8000 และ 9000 แคลอรี่ ซึ่งผลรวมทั้งหมดจะได้ 24000 แคลอรี่
เอลฟ์คนที่ห้าพกอาหารที่ให้พลังงาน 10000 แคลอรี่
ในกรณีที่เอลฟ์ต้องการอาหารเพิ่มเติม พวกเขาอยากรู้ว่าเอลฟ์ที่พกอาหารมามากที่สุดนั้นมีกี่แคลอรี่ ในตัวอย่างด้านบนคือเอลฟ์คนที่สี่ซึ่งพกอาหารมาทั้งหมด 24,000 แคลอรี่
โจทย์ต้องการให้หาว่าผลรวมของพลังงานอาหารที่มากที่สุดของเอลฟ์เท่ากับเท่าไร
เริ่มต้นเหมือนกับทุกครั้งด้วยการดาวน์โหลดอินพุตไฟล์เข้ามาในโปรแกรมและทำการแปลงตัวเลขในแต่ละบรรทัดให้เป็น u32
ในภาษา Rust การแปลงสตริงให้เป็น u32
สามารถทำได้ด้วยการเรียกใช้ฟังก์ชัน parse
โดยมีเงื่อนไขว่าถ้าเจอบรรทัดที่เป็นค่าว่าง is_empty
ให้ทำเอาผลรวมแคลอรี่เพิ่มเข้าไปที่ elves
ที่เป็นประเภท Vec<u32>
และทำการรีเซ็ต carrying_calories
ให้เป็น 0
เพื่อใช้สำหรับคำนวณพลังงานรวมของเอลฟ์คนถัดไป
use std::{env, fs, io, io::BufRead, path};
fn main() {
let args: Vec<String> = env::args().collect();
let input = &args[1];
let mut elves: Vec<u32> = vec![];
if let Ok(lines) = read_lines(input) {
let mut carrying_calories = 0u32;
for line in lines {
if let Ok(line) = line {
if line.is_empty() {
elves.push(carrying_calories);
carrying_calories = 0;
continue;
}
carrying_calories += line.parse::<u32>().expect("invalid number");
}
}
}
// descending order
elves.sort_by(|a, b| b.cmp(a));
println!("first part answer is: {}", elves[0]);
}
fn read_lines<P: AsRef<path::Path>>(path: P) -> io::Result<io::Lines<io::BufReader<fs::File>>> {
let file = fs::File::open(path)?;
Ok(io::BufReader::new(file).lines())
}
เมื่อได้ Vec<u32>
ที่มีผลรวมของพลังงานทั้งหมดแล้วให้ทำการเรียงลำดับจากมากไปน้อยด้วยฟังก์ชัน sort_by
ตามโค้ดด้านบน เท่านี้ elves[0]
ก็คือเอลฟ์คนที่พกอาหารที่มีผลรวมพลังงานมากที่สุดซึ่งเป็นคำตอบของพาร์ทแรกแล้ว
เมื่อได้คำตอบแล้วว่าใครพกอาหารที่ให้พลังงานมามากที่สุดเหล่าเอลฟ์ก็กังวลว่าอาหารอาจจะไม่พอ เพื่อป้องกันปัญหานี้เหล่าเอลฟ์อยากรู้ว่าใครที่พกอาหารที่ให้พลังงานมากที่สุดสามคนแรก เพื่อที่ว่าถ้าเอลฟ์คนใดคนนึงกินอาหารหมดก่อน พวกเขาก็ยังมีอีกสองคนสำรองอยู่ว
ตัวอย่างข้างต้นเอลฟ์สามอันดับแรกคือเอลฟ์ที่สี่ (มีพลังงาน 24,000 แคลอรี) ตามด้วยเอลฟ์ที่สาม (มีพลังงาน 11,000 แคลอรี) ตามด้วยเอลฟ์ที่ห้า (มีพลังงาน 10,000 แคลอรี) ผลรวมของแคลอรีที่เอลฟ์ทั้งสามนี้มีคือ 45,000
ค้นหาเอลฟ์สามอันดับแรกที่มีพลังงานมากที่สุดและหาว่ามีพลังงานทั้งหมดกี่แคลอรี?
ในพาร์ทที่สองโจทย์ต้องการให้ผลรวมของพลังงานที่มากที่สุดของเอลฟ์สามคนแรกซึ่งตรงนี้สามารถหาคำตอบได้ด้วยการเอา elves[0] + elves[1] + elves[2]
แบบนี้ได้เลย
fn main() {
...
// descending order
elves.sort_by(|a, b| b.cmp(a));
println!("first part answer is: {}", elves[0]);
println!("second part answer: {}", elves[0] + elves[1] + elves[2]);
}