Advent of Code 2020 day23
33117 단어 Rustadventofcodetech
part1
389125467
과 같은 입력을 제공합니다.1
부터 9
까지의 컵은 이 순서대로 시계 바늘에 따라 배열하고 아래의 규칙에 따라 이동한다.current cup 시계 방향으로 3개 꺼내기
current cup의 수치에서
1
를 뺀 수치cup는destination cup로1
뺀 수치가 꺼낸 3개에 포함되면 다시 뺀다1
계속
1
최저치에 도달하면 다음 최대치current cup부터 시계 방향으로 옆에 있는current cup를 다음current cup
이것
100
을 반복할 때1
의 찻잔을 시계 방향으로 보면 어떤 순서로 찻잔을 배열합니까?이런 문제.상술한 예의 경우
67384529
.9
개 컵을 100
회 움직일 정도라면 넣고Vec
순서대로 반복remove
하고insert
해도 문제없는simulate.struct Solution {
cups: Vec<u8>,
}
impl Solution {
fn new(input: String) -> Self {
Self {
cups: input.as_bytes().iter().map(|&b| b - b'0').collect(),
}
}
fn solve_1(&self) -> String {
let mut cups = self.cups.clone();
for _ in 0..100 {
let current = cups.remove(0);
let pickup: Vec<u8> = (0..3).map(|_| cups.remove(0)).collect();
let mut destination = if current == 1 { 9 } else { current - 1 };
while pickup.contains(&destination) {
destination = if destination == 1 { 9 } else { destination - 1 };
}
if let Some(p) = cups.iter().position(|&x| x == destination) {
cups.splice(p + 1..p + 1, pickup);
}
cups.push(current);
}
while cups[0] != 1 {
let first = cups.remove(0);
cups.push(first);
}
cups.iter().skip(1).map(|&u| (u + b'0') as char).collect()
}
}
part2
뜻밖에도 찻잔이 9개가 아니라 100만개라니...!처음 몇 개(입력한 9개)를 순서대로 배열한 다음 순서대로 배열한다.그리고 이동 횟수도 100번이 아니라 1000만 번!
역시 이것은
Vec
의remove
와insert
에서 완전히 계산되지 않았다.LinkedList를 다시 연결하는 것이 올바른 방법입니다.
그렇긴 한데, Rust 같은 조작은 비교적 번거롭다...
실제 조작을 꼼꼼히 고려하면
current cup -> [picked up 3 cups] -> next1 -> ... -> destination cup -> next2 ->
순차적current cup -> next1 -> ... -> destination cup -> [picked up 3 cups] -> next2 ->
다시 연결하면 됩니다.이 조작을 할 때는'어떤 컵의 시계 방향 옆에 있는 컵의 번호'만 알면 된다.
current cup에서 뽑은 3개는 current cup을 시작으로 3개씩 차례로 가면 됩니다.
그리고 다음cup은 다시 연결한 후에currentcup 옆(다음)에 올 것입니다.
destination cup의 다음 cup은 다시 연결된 세 개의 옆(아래)에서 가져올 물건입니다.
따라서
HashMap
등에서 지정된 번호의cup에서 다음 줄의cup번호를 빼면 고쳐쓰기만 하면 된다.실제로 1000만 번
HashMap
을 조작하면 계산이 무겁기 때문에 Vec
에 깊이 들어가면 빠르다.code
impl Solution {
fn new(input: String) -> Self {
Self {
cups: input
.as_bytes()
.iter()
.map(|&b| (b - b'0') as u32)
.collect(),
}
}
fn solve_1(&self) -> String {
let cups = self.game(9, 100);
let mut ret = Vec::new();
let mut cup = 1;
for _ in 0..8 {
ret.push(cups[cup].to_string());
cup = cups[cup] as usize;
}
ret.concat()
}
fn solve_2(&self) -> u64 {
let cups = self.game(1_000_000, 10_000_000);
let mut ret = 1;
let mut cup = 1;
for _ in 0..2 {
ret *= cups[cup] as u64;
cup = cups[cup] as usize;
}
ret
}
fn game(&self, cups: usize, moves: usize) -> Vec<u32> {
let mut map = vec![0; cups + 1];
let mut last = None;
for (i, &cup) in self.cups.iter().enumerate() {
if i > 0 {
map[self.cups[i - 1] as usize] = cup;
}
last = Some(cup);
}
for i in self.cups.len()..cups {
if let Some(l) = last {
map[l as usize] = i as u32 + 1;
}
last = Some(i as u32 + 1)
}
if let Some(l) = last {
map[l as usize] = self.cups[0];
}
let highest = cups as usize;
let mut current = self.cups[0] as usize;
let mut pickups = [0; 3];
for _ in 0..moves {
let mut p = current;
for pickup in pickups.iter_mut() {
p = map[p] as usize;
*pickup = p;
}
let mut destination = if current > 1 { current - 1 } else { highest };
while pickups.iter().any(|&x| x == destination) {
destination = if destination > 1 {
destination - 1
} else {
highest
};
}
let tmp = map[current];
map[current] = map[p];
map[p] = map[destination];
map[destination] = tmp;
current = map[current] as usize;
}
map
}
}
fn main() {
let solution = Solution::new(
BufReader::new(std::io::stdin().lock())
.lines()
.filter_map(|line| line.ok())
.next()
.unwrap(),
);
println!("{}", solution.solve_1());
println!("{}", solution.solve_2());
}
Reference
이 문제에 관하여(Advent of Code 2020 day23), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/sugyan/articles/402c9bcd3f8336텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)