day7: optimized
This commit is contained in:
parent
fc31940164
commit
73f0b5dc61
169
src/day7/1.rs
169
src/day7/1.rs
|
@ -1,15 +1,19 @@
|
||||||
|
#![feature(byte_slice_trim_ascii)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")];
|
const INPUTS: [&[u8]; 2] = [
|
||||||
|
include_bytes!("./sample.txt"),
|
||||||
|
include_bytes!("./input.txt"),
|
||||||
|
];
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Card {
|
struct Card<'a> {
|
||||||
val: String,
|
val: &'a [u8],
|
||||||
ttype: SetType,
|
set_type: SetType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
|
@ -23,59 +27,66 @@ enum SetType {
|
||||||
High = 1,
|
High = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process(data: &str) -> u64 {
|
const ARRAY_SIZE: usize = 15;
|
||||||
let mut answer = 0;
|
|
||||||
|
|
||||||
|
fn process(data: &[u8]) -> u64 {
|
||||||
|
let mut answer = 0;
|
||||||
let mut cards = vec![];
|
let mut cards = vec![];
|
||||||
|
|
||||||
for data in data.lines() {
|
for data in data.split(|&x| x == b'\n') {
|
||||||
if data.is_empty() {
|
if data.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let (card, value) = data.split_at(6);
|
let (card, value) = data.split_at(6);
|
||||||
let card = card.trim();
|
let card = card.trim_ascii();
|
||||||
|
|
||||||
let mut arr = [0; 255];
|
let mut arr = [0; ARRAY_SIZE];
|
||||||
|
|
||||||
for c in card.bytes() {
|
for &c in card {
|
||||||
|
let c = card_weight(c);
|
||||||
arr[c as usize] += 1;
|
arr[c as usize] += 1;
|
||||||
}
|
}
|
||||||
|
let transposed = transpose(&arr);
|
||||||
|
|
||||||
let ttype = if arr.iter().any(|&x| x == 5) {
|
let set_type = match transposed {
|
||||||
SetType::Five
|
[_, _, _, _, _, 1] => SetType::Five,
|
||||||
} else if arr.iter().any(|&x| x == 4) && arr.iter().any(|&x| x == 1) {
|
|
||||||
SetType::Four
|
[_, 1, _, _, 1, _] => SetType::Four,
|
||||||
} else if arr.iter().any(|&x| x == 3) && arr.iter().any(|&x| x == 2) {
|
|
||||||
SetType::FullHouse
|
[_, _, 1, 1, _, _] => SetType::FullHouse,
|
||||||
} else if arr.iter().any(|&x| x == 3) && arr.iter().filter(|&&x| x == 1).count() == 2 {
|
|
||||||
SetType::Three
|
[_, 2, _, 1, _, _] => SetType::Three,
|
||||||
} else if arr.iter().filter(|&&x| x == 2).count() == 2
|
|
||||||
&& arr.iter().filter(|&&x| x == 1).count() == 1
|
[_, 1, 2, _, _, _] => SetType::Two,
|
||||||
{
|
|
||||||
SetType::Two
|
[_, 3, 1, _, _, _] => SetType::One,
|
||||||
} else if arr.iter().filter(|&&x| x == 2).count() == 1
|
|
||||||
&& arr.iter().filter(|&&x| x == 1).count() == 3
|
[_, 5, _, _, _, _] => SetType::High,
|
||||||
{
|
|
||||||
SetType::One
|
_ => unreachable!(),
|
||||||
} else if arr.iter().all(|&x| x == 0 || x == 1) {
|
|
||||||
SetType::High
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut num = 0;
|
||||||
|
let mut pow = 1;
|
||||||
|
|
||||||
|
for &val in value.iter().rev() {
|
||||||
|
num += (val - b'0') as u64 * pow;
|
||||||
|
pow *= 10;
|
||||||
|
}
|
||||||
|
|
||||||
cards.push((
|
cards.push((
|
||||||
Card {
|
Card {
|
||||||
val: card.to_string(),
|
val: card,
|
||||||
ttype,
|
set_type,
|
||||||
},
|
},
|
||||||
value,
|
num,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
cards.sort_unstable_by(|(a, _), (b, _)| match (a.ttype, b.ttype) {
|
cards.sort_unstable_by(|(a, _), (b, _)| match (a.set_type, b.set_type) {
|
||||||
(x, y) if x == y => {
|
(x, y) if x == y => {
|
||||||
for (a, b) in a.val.chars().zip(b.val.chars()) {
|
for (a, b) in a.val.iter().zip(b.val.iter()) {
|
||||||
let ordering = cmp(a, b);
|
let ordering = cmp(*a, *b);
|
||||||
|
|
||||||
if ordering != Ordering::Equal {
|
if ordering != Ordering::Equal {
|
||||||
return ordering;
|
return ordering;
|
||||||
|
@ -93,7 +104,6 @@ fn process(data: &str) -> u64 {
|
||||||
});
|
});
|
||||||
|
|
||||||
for (i, (_, v)) in cards.into_iter().enumerate() {
|
for (i, (_, v)) in cards.into_iter().enumerate() {
|
||||||
let v = v.parse::<u64>().unwrap();
|
|
||||||
let i = i + 1;
|
let i = i + 1;
|
||||||
|
|
||||||
answer += v * i as u64;
|
answer += v * i as u64;
|
||||||
|
@ -102,55 +112,82 @@ fn process(data: &str) -> u64 {
|
||||||
answer
|
answer
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmp(a: char, b: char) -> Ordering {
|
#[inline]
|
||||||
if let Ordering::Equal = a.cmp(&b) {
|
const fn cmp(a: u8, b: u8) -> Ordering {
|
||||||
|
if a == b {
|
||||||
return Ordering::Equal;
|
return Ordering::Equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
match (a, b) {
|
match (a, b) {
|
||||||
('A', _) => Ordering::Greater,
|
(b'A', _) => Ordering::Greater,
|
||||||
(_, 'A') => Ordering::Less,
|
(_, b'A') => Ordering::Less,
|
||||||
|
|
||||||
('K', _) => Ordering::Greater,
|
(b'K', _) => Ordering::Greater,
|
||||||
(_, 'K') => Ordering::Less,
|
(_, b'K') => Ordering::Less,
|
||||||
|
|
||||||
('Q', _) => Ordering::Greater,
|
(b'Q', _) => Ordering::Greater,
|
||||||
(_, 'Q') => Ordering::Less,
|
(_, b'Q') => Ordering::Less,
|
||||||
|
|
||||||
('J', _) => Ordering::Greater,
|
(b'J', _) => Ordering::Greater,
|
||||||
(_, 'J') => Ordering::Less,
|
(_, b'J') => Ordering::Less,
|
||||||
|
|
||||||
('T', _) => Ordering::Greater,
|
(b'T', _) => Ordering::Greater,
|
||||||
(_, 'T') => Ordering::Less,
|
(_, b'T') => Ordering::Less,
|
||||||
|
|
||||||
('9', _) => Ordering::Greater,
|
(b'9', _) => Ordering::Greater,
|
||||||
(_, '9') => Ordering::Less,
|
(_, b'9') => Ordering::Less,
|
||||||
|
|
||||||
('8', _) => Ordering::Greater,
|
(b'8', _) => Ordering::Greater,
|
||||||
(_, '8') => Ordering::Less,
|
(_, b'8') => Ordering::Less,
|
||||||
|
|
||||||
('7', _) => Ordering::Greater,
|
(b'7', _) => Ordering::Greater,
|
||||||
(_, '7') => Ordering::Less,
|
(_, b'7') => Ordering::Less,
|
||||||
|
|
||||||
('6', _) => Ordering::Greater,
|
(b'6', _) => Ordering::Greater,
|
||||||
(_, '6') => Ordering::Less,
|
(_, b'6') => Ordering::Less,
|
||||||
|
|
||||||
('5', _) => Ordering::Greater,
|
(b'5', _) => Ordering::Greater,
|
||||||
(_, '5') => Ordering::Less,
|
(_, b'5') => Ordering::Less,
|
||||||
|
|
||||||
('4', _) => Ordering::Greater,
|
(b'4', _) => Ordering::Greater,
|
||||||
(_, '4') => Ordering::Less,
|
(_, b'4') => Ordering::Less,
|
||||||
|
|
||||||
('3', _) => Ordering::Greater,
|
(b'3', _) => Ordering::Greater,
|
||||||
(_, '3') => Ordering::Less,
|
(_, b'3') => Ordering::Less,
|
||||||
|
|
||||||
('2', _) => Ordering::Greater,
|
(b'2', _) => Ordering::Greater,
|
||||||
(_, '2') => Ordering::Less,
|
(_, b'2') => Ordering::Less,
|
||||||
|
|
||||||
(_, _) => unreachable!(),
|
(_, _) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transpose(ip: &[u8; ARRAY_SIZE]) -> [u8; 6] {
|
||||||
|
let mut out = [0; 6];
|
||||||
|
|
||||||
|
for &v in ip {
|
||||||
|
out[v as usize] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
const fn card_weight(a: u8) -> u8 {
|
||||||
|
match a {
|
||||||
|
b'2'..=b'9' => a - b'0',
|
||||||
|
|
||||||
|
b'J' => 10,
|
||||||
|
b'T' => 11,
|
||||||
|
b'Q' => 12,
|
||||||
|
b'K' => 13,
|
||||||
|
b'A' => 14,
|
||||||
|
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
for input in INPUTS.iter() {
|
for input in INPUTS.iter() {
|
||||||
println!("total = {}", process(input));
|
println!("total = {}", process(input));
|
||||||
|
@ -158,7 +195,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn part2(b: &mut test::Bencher) {
|
fn part1(b: &mut test::Bencher) {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let v = process(INPUTS[1]);
|
let v = process(INPUTS[1]);
|
||||||
test::black_box(v);
|
test::black_box(v);
|
||||||
|
|
209
src/day7/2.rs
209
src/day7/2.rs
|
@ -1,15 +1,19 @@
|
||||||
|
#![feature(byte_slice_trim_ascii)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")];
|
const INPUTS: [&[u8]; 2] = [
|
||||||
|
include_bytes!("./sample.txt"),
|
||||||
|
include_bytes!("./input.txt"),
|
||||||
|
];
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Card {
|
struct Card<'a> {
|
||||||
val: String,
|
val: &'a [u8],
|
||||||
ttype: SetType,
|
ctype: SetType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
|
@ -23,85 +27,74 @@ enum SetType {
|
||||||
High = 1,
|
High = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process(data: &str) -> u64 {
|
const ARRAY_SIZE: usize = 14;
|
||||||
|
|
||||||
|
fn process(data: &[u8]) -> u64 {
|
||||||
let mut answer = 0;
|
let mut answer = 0;
|
||||||
|
|
||||||
let mut cards = vec![];
|
let mut cards = vec![];
|
||||||
|
|
||||||
for data in data.lines() {
|
for data in data.split(|&x| x == b'\n') {
|
||||||
if data.is_empty() {
|
if data.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let (card, value) = data.split_at(6);
|
let (card, value) = data.split_at(6);
|
||||||
let card = card.trim();
|
let card = card.trim_ascii();
|
||||||
|
|
||||||
let mut arr = [0; 255];
|
let mut arr = [0; ARRAY_SIZE];
|
||||||
|
|
||||||
for c in card.bytes() {
|
for &c in card.iter() {
|
||||||
|
let c = card_weight(c);
|
||||||
arr[c as usize] += 1;
|
arr[c as usize] += 1;
|
||||||
}
|
}
|
||||||
let count = arr['J' as u8 as usize];
|
|
||||||
|
|
||||||
let ttype = if arr.iter().any(|&x| x == 5) {
|
let count = arr[card_weight(b'J') as usize];
|
||||||
SetType::Five
|
let transposed = transpose(&arr);
|
||||||
} else if arr.iter().any(|&x| x == 4) && arr.iter().any(|&x| x == 1) {
|
|
||||||
if count == 4 || count == 1 {
|
let ctype = match (count, transposed) {
|
||||||
SetType::Five
|
(_, [_, _, _, _, _, 1]) => SetType::Five,
|
||||||
} else {
|
|
||||||
SetType::Four
|
(4, [_, 1, _, _, 1, _]) => SetType::Five,
|
||||||
}
|
(1, [_, 1, _, _, 1, _]) => SetType::Five,
|
||||||
} else if arr.iter().any(|&x| x == 3) && arr.iter().any(|&x| x == 2) {
|
(_, [_, 1, _, _, 1, _]) => SetType::Four,
|
||||||
if count == 3 || count == 2 {
|
|
||||||
SetType::Five
|
(3, [_, _, 1, 1, _, _]) => SetType::Five,
|
||||||
} else {
|
(2, [_, _, 1, 1, _, _]) => SetType::Five,
|
||||||
SetType::FullHouse
|
(_, [_, _, 1, 1, _, _]) => SetType::FullHouse,
|
||||||
}
|
|
||||||
} else if arr.iter().any(|&x| x == 3) && arr.iter().filter(|&&x| x == 1).count() == 2 {
|
(3, [_, 2, _, 1, _, _]) => SetType::Four,
|
||||||
if count == 3 || count == 1 {
|
(1, [_, 2, _, 1, _, _]) => SetType::Four,
|
||||||
SetType::Four
|
(_, [_, 2, _, 1, _, _]) => SetType::Three,
|
||||||
} else {
|
|
||||||
SetType::Three
|
(2, [_, 1, 2, _, _, _]) => SetType::Four,
|
||||||
}
|
(1, [_, 1, 2, _, _, _]) => SetType::FullHouse,
|
||||||
} else if arr.iter().filter(|&&x| x == 2).count() == 2
|
(_, [_, 1, 2, _, _, _]) => SetType::Two,
|
||||||
&& arr.iter().filter(|&&x| x == 1).count() == 1
|
|
||||||
{
|
(2, [_, 3, 1, _, _, _]) => SetType::Three,
|
||||||
if count == 2 {
|
(1, [_, 3, 1, _, _, _]) => SetType::Three,
|
||||||
SetType::Four
|
(_, [_, 3, 1, _, _, _]) => SetType::One,
|
||||||
} else if count == 1 {
|
|
||||||
SetType::FullHouse
|
(1, [_, 5, _, _, _, _]) => SetType::One,
|
||||||
} else {
|
(_, [_, 5, _, _, _, _]) => SetType::High,
|
||||||
SetType::Two
|
|
||||||
}
|
(_, _) => unreachable!(),
|
||||||
} else if arr.iter().filter(|&&x| x == 2).count() == 1
|
|
||||||
&& arr.iter().filter(|&&x| x == 1).count() == 3
|
|
||||||
{
|
|
||||||
if count == 2 || count == 1 {
|
|
||||||
SetType::Three
|
|
||||||
} else {
|
|
||||||
SetType::One
|
|
||||||
}
|
|
||||||
} else if arr.iter().all(|&x| x == 0 || x == 1) {
|
|
||||||
if count == 1 {
|
|
||||||
SetType::One
|
|
||||||
} else {
|
|
||||||
SetType::High
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
cards.push((
|
let mut num = 0;
|
||||||
Card {
|
let mut pow = 1;
|
||||||
val: card.to_string(),
|
|
||||||
ttype,
|
for &val in value.iter().rev() {
|
||||||
},
|
num += (val - b'0') as u64 * pow;
|
||||||
value.parse::<u64>().unwrap(),
|
pow *= 10;
|
||||||
));
|
|
||||||
}
|
}
|
||||||
cards.sort_unstable_by(|(a, _), (b, _)| match (a.ttype, b.ttype) {
|
|
||||||
|
cards.push((Card { val: card, ctype }, num));
|
||||||
|
}
|
||||||
|
|
||||||
|
cards.sort_unstable_by(|(a, _), (b, _)| match (a.ctype, b.ctype) {
|
||||||
(x, y) if x == y => {
|
(x, y) if x == y => {
|
||||||
for (a, b) in a.val.chars().zip(b.val.chars()) {
|
for (a, b) in a.val.iter().zip(b.val.iter()) {
|
||||||
let ordering = cmp(a, b);
|
let ordering = cmp(*a, *b);
|
||||||
|
|
||||||
if ordering != Ordering::Equal {
|
if ordering != Ordering::Equal {
|
||||||
return ordering;
|
return ordering;
|
||||||
|
@ -127,50 +120,78 @@ fn process(data: &str) -> u64 {
|
||||||
answer
|
answer
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmp(a: char, b: char) -> Ordering {
|
#[inline]
|
||||||
if let Ordering::Equal = a.cmp(&b) {
|
fn transpose(ip: &[u8; ARRAY_SIZE]) -> [u8; 6] {
|
||||||
|
let mut out = [0; 6];
|
||||||
|
|
||||||
|
for &v in ip {
|
||||||
|
out[v as usize] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
const fn card_weight(a: u8) -> u8 {
|
||||||
|
match a {
|
||||||
|
b'J' => 1,
|
||||||
|
|
||||||
|
b'2'..=b'9' => a - b'0',
|
||||||
|
|
||||||
|
b'T' => 10,
|
||||||
|
b'Q' => 11,
|
||||||
|
b'K' => 12,
|
||||||
|
b'A' => 13,
|
||||||
|
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
const fn cmp(a: u8, b: u8) -> Ordering {
|
||||||
|
if a == b {
|
||||||
return Ordering::Equal;
|
return Ordering::Equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
match (a, b) {
|
match (a, b) {
|
||||||
('A', _) => Ordering::Greater,
|
(b'A', _) => Ordering::Greater,
|
||||||
(_, 'A') => Ordering::Less,
|
(_, b'A') => Ordering::Less,
|
||||||
|
|
||||||
('K', _) => Ordering::Greater,
|
(b'K', _) => Ordering::Greater,
|
||||||
(_, 'K') => Ordering::Less,
|
(_, b'K') => Ordering::Less,
|
||||||
|
|
||||||
('Q', _) => Ordering::Greater,
|
(b'Q', _) => Ordering::Greater,
|
||||||
(_, 'Q') => Ordering::Less,
|
(_, b'Q') => Ordering::Less,
|
||||||
|
|
||||||
('T', _) => Ordering::Greater,
|
(b'T', _) => Ordering::Greater,
|
||||||
(_, 'T') => Ordering::Less,
|
(_, b'T') => Ordering::Less,
|
||||||
|
|
||||||
('9', _) => Ordering::Greater,
|
(b'9', _) => Ordering::Greater,
|
||||||
(_, '9') => Ordering::Less,
|
(_, b'9') => Ordering::Less,
|
||||||
|
|
||||||
('8', _) => Ordering::Greater,
|
(b'8', _) => Ordering::Greater,
|
||||||
(_, '8') => Ordering::Less,
|
(_, b'8') => Ordering::Less,
|
||||||
|
|
||||||
('7', _) => Ordering::Greater,
|
(b'7', _) => Ordering::Greater,
|
||||||
(_, '7') => Ordering::Less,
|
(_, b'7') => Ordering::Less,
|
||||||
|
|
||||||
('6', _) => Ordering::Greater,
|
(b'6', _) => Ordering::Greater,
|
||||||
(_, '6') => Ordering::Less,
|
(_, b'6') => Ordering::Less,
|
||||||
|
|
||||||
('5', _) => Ordering::Greater,
|
(b'5', _) => Ordering::Greater,
|
||||||
(_, '5') => Ordering::Less,
|
(_, b'5') => Ordering::Less,
|
||||||
|
|
||||||
('4', _) => Ordering::Greater,
|
(b'4', _) => Ordering::Greater,
|
||||||
(_, '4') => Ordering::Less,
|
(_, b'4') => Ordering::Less,
|
||||||
|
|
||||||
('3', _) => Ordering::Greater,
|
(b'3', _) => Ordering::Greater,
|
||||||
(_, '3') => Ordering::Less,
|
(_, b'3') => Ordering::Less,
|
||||||
|
|
||||||
('2', _) => Ordering::Greater,
|
(b'2', _) => Ordering::Greater,
|
||||||
(_, '2') => Ordering::Less,
|
(_, b'2') => Ordering::Less,
|
||||||
|
|
||||||
('J', _) => Ordering::Greater,
|
(b'J', _) => Ordering::Greater,
|
||||||
(_, 'J') => Ordering::Less,
|
(_, b'J') => Ordering::Less,
|
||||||
|
|
||||||
(_, _) => unreachable!(),
|
(_, _) => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user