Advent of Code
毎日2題出題されます。競技プログラミングチックに楽しめます。
この問題概要と実装解答を以下にご紹介します。
問題概要は生成AIに書いてもらったものを貼り付けています。
実装は人間が行なっています。
Day 1: Secret Entrance
part1 問題概要
安全金庫のダイヤル(0〜99 の円形の数字盤)があります。
初期位置は 50。
入力(パズル入力)は 1行ごとの回転指示:
- Lx = 左(数字が小さくなる方向)に x回回す
- Rx = 右(数字が大きくなる方向)に x回回す
ダイヤルは円形で、0 の左は 99、99 の右は 0
すべきこと:
- 入力指示通りにダイヤルを回す
- 各回転の後にダイヤルが 0 を指した回数を数える
- その回数がパスワード(答え)になる
解答
単なるシミュレーションです。O(N)です。
fn main() {
let n = 4136;
let mods = 100;
let mut now = 50isize;
input! {
s: [String; n]
}
let reg = Regex::new("^([LR])(\\d{1,})$").unwrap();
let s = s.iter().map(|e| {
let cap = reg.captures(e).unwrap();
let c = cap[1].chars().next().unwrap();
let num = cap[2].parse::<isize>().unwrap();
(c, num)
}).collect_vec();
let mut ans = 0;
for &(c, num) in s.iter() {
match c {
'L' => now = (now - num).rem_euclid(mods),
'R' => now = (now + num).rem_euclid(mods),
_ => unreachable!("")
}
if now == 0 {
ans += 1usize;
}
}
println!("{}", ans);
}
part2 問題概要
Part 1 では「回転が終わった時に 0 を指している回数」を数えた。
Part 2(method 0x434C49434B)では新ルールに変更
- 回転の途中でも 0 を通過したら全部カウントする
つまり:
- 回している途中で 0 を通る
- 回し終わりの位置が 0 である
どちらもカウント対象になる。
「通過しただけでも全部カウントする」ルールに変更。
解答
modで何回周回するか、残りは何回かを数値計算しておくことでこちらもO(N)で計算可能。
fn main() {
let n = 4136;
let mods = 100;
let mut now = 50isize;
input! {
s: [String; n]
}
let reg = Regex::new("^([LR])(\\d{1,})$").unwrap();
let s = s.iter().map(|e| {
let cap = reg.captures(e).unwrap();
let c = cap[1].chars().next().unwrap();
let num = cap[2].parse::<isize>().unwrap();
(c, num)
}).collect_vec();
let mut ans = 0;
for &(c, num) in s.iter() {
let shu = num / mods;
ans += shu;
let rest = num % mods;
match c {
'L' => {
if now != 0 && rest >= now {
ans += 1;
}
now = (now - rest).rem_euclid(mods);
},
'R' => {
if now != 0 && now + rest >= mods {
ans += 1;
}
now = (now + rest).rem_euclid(mods);
},
_ => unreachable!("")
}
}
println!("{}", ans);
}
終わりに
Day2も頑張ります!