Skip to content

Commit c832ca6

Browse files
committed
CQ problem 14
1 parent 2476a98 commit c832ca6

File tree

3 files changed

+115
-16
lines changed

3 files changed

+115
-16
lines changed

codingquest_clp_solutions/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ use codingquest_clp::build_solvers;
66

77
pub mod helpers;
88
pub mod problem_13;
9+
pub mod problem_14;
910

1011
pub type Error = codingquest_clp::Error;
1112
pub type Result<T> = codingquest_clp::Result<T>;
1213

1314
build_solvers! {
14-
[13]
15+
[13, 14]
1516
}

codingquest_clp_solutions/src/problem_13.rs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::ops::Deref;
2+
13
use codingquest_clp::solvers_impl::input::get_input;
24
use itertools::Itertools;
35

@@ -6,22 +8,23 @@ use crate::helpers::get_problem_input_data;
68
pub fn solve() -> usize {
79
let (board, moves) = input();
810

11+
let move_player = |p: &mut i32, p_move: i32| {
12+
*p += p_move;
13+
while (*p as usize) < board.len() && board[*p as usize] != 0 {
14+
*p += board[*p as usize];
15+
}
16+
};
17+
918
let mut p1 = 0;
1019
let mut p2 = 0;
11-
for (count, &(p1_move, p2_move)) in moves.moves.iter().enumerate() {
12-
p1 += p1_move;
13-
while (p1 as usize) < board.tiles.len() && board.tiles[p1 as usize] != 0 {
14-
p1 += board.tiles[p1 as usize];
15-
}
16-
if (p1 as usize) >= board.tiles.len() {
20+
for (count, &(p1_move, p2_move)) in moves.iter().enumerate() {
21+
move_player(&mut p1, p1_move);
22+
if (p1 as usize) >= board.len() {
1723
return count + 1;
1824
}
1925

20-
p2 += p2_move;
21-
while (p2 as usize) < board.tiles.len() && board.tiles[p2 as usize] != 0 {
22-
p2 += board.tiles[p2 as usize];
23-
}
24-
if (p2 as usize) >= board.tiles.len() {
26+
move_player(&mut p2, p2_move);
27+
if (p2 as usize) >= board.len() {
2528
return 2 * (count + 1);
2629
}
2730
}
@@ -35,13 +38,13 @@ fn input() -> (Board, Moves) {
3538
}
3639

3740
struct Board {
38-
pub tiles: Vec<i32>,
41+
tiles: Vec<i32>,
3942
}
4043

4144
const BOARD_SIZE: usize = 20;
4245

4346
impl Board {
44-
fn from_input_data<I>(input_data: I) -> Self
47+
pub fn from_input_data<I>(input_data: I) -> Self
4548
where
4649
I: AsRef<str>,
4750
{
@@ -70,12 +73,20 @@ impl Board {
7073
}
7174
}
7275

76+
impl Deref for Board {
77+
type Target = [i32];
78+
79+
fn deref(&self) -> &Self::Target {
80+
&self.tiles
81+
}
82+
}
83+
7384
struct Moves {
74-
pub moves: Vec<(i32, i32)>,
85+
moves: Vec<(i32, i32)>,
7586
}
7687

7788
impl Moves {
78-
fn from_input_data<I>(input_data: I) -> Self
89+
pub fn from_input_data<I>(input_data: I) -> Self
7990
where
8091
I: AsRef<str>,
8192
{
@@ -93,3 +104,11 @@ impl Moves {
93104
}
94105
}
95106
}
107+
108+
impl Deref for Moves {
109+
type Target = [(i32, i32)];
110+
111+
fn deref(&self) -> &Self::Target {
112+
&self.moves
113+
}
114+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use std::collections::{HashMap, HashSet};
2+
3+
use codingquest_clp::solvers_impl::input::get_input;
4+
use itertools::Itertools;
5+
6+
use crate::helpers::get_problem_input_data;
7+
8+
pub fn solve() -> String {
9+
let word_list = word_list();
10+
let rules: Rules = GUESSES.into();
11+
12+
word_list
13+
.into_iter()
14+
.filter(|word| rules.matches(word))
15+
.exactly_one()
16+
.unwrap()
17+
.clone()
18+
}
19+
20+
fn word_list() -> Vec<String> {
21+
get_input(get_problem_input_data(14).unwrap())
22+
.unwrap()
23+
.safe_into_many()
24+
}
25+
26+
const GUESSES: &[(&str, &str)] =
27+
&[("keyless", "YYBBYYG"), ("society", "YGYYYBB"), ("phobias", "BBGBGBG")];
28+
29+
#[derive(Debug, Default)]
30+
struct Rules {
31+
green: HashMap<usize, char>,
32+
yellow: HashSet<char>,
33+
black: HashSet<char>,
34+
}
35+
36+
impl Rules {
37+
pub fn matches<S>(&self, word: S) -> bool
38+
where
39+
S: AsRef<str>,
40+
{
41+
let word = word.as_ref();
42+
43+
word.chars()
44+
.enumerate()
45+
.filter(|(i, c)| {
46+
if let Some(green) = self.green.get(i) {
47+
green == c
48+
} else {
49+
self.yellow.contains(c) && !self.black.contains(c)
50+
}
51+
})
52+
.count()
53+
== word.len()
54+
}
55+
}
56+
57+
impl From<&[(&str, &str)]> for Rules {
58+
fn from(value: &[(&str, &str)]) -> Self {
59+
let rules: HashMap<_, _> = value
60+
.iter()
61+
.flat_map(|&(guess, colored)| {
62+
guess
63+
.chars()
64+
.enumerate()
65+
.zip_eq(colored.chars())
66+
.map(|((i, g), color)| (color, (i, g)))
67+
})
68+
.into_group_map();
69+
70+
let color_rule = |color| rules.get(&color).unwrap().clone();
71+
let simple_color_rule = |color| color_rule(color).into_iter().map(|(_, g)| g).collect();
72+
let indexed_color_rule = |color| color_rule(color).into_iter().collect();
73+
74+
let green = indexed_color_rule('G');
75+
let yellow = simple_color_rule('Y');
76+
let black = simple_color_rule('B');
77+
Self { green, yellow, black }
78+
}
79+
}

0 commit comments

Comments
 (0)