day7: optimized

This commit is contained in:
Ishan Jain 2023-12-07 15:06:13 +05:30
parent 73f0b5dc61
commit 37818823a8
Signed by: ishan
GPG Key ID: 0506DB2A1CC75C27
2 changed files with 48 additions and 160 deletions

View File

@ -11,8 +11,8 @@ const INPUTS: [&[u8]; 2] = [
]; ];
#[derive(Debug)] #[derive(Debug)]
struct Card<'a> { struct Card {
val: &'a [u8], val: usize,
set_type: SetType, set_type: SetType,
} }
@ -29,7 +29,7 @@ enum SetType {
const ARRAY_SIZE: usize = 15; const ARRAY_SIZE: usize = 15;
fn process(data: &[u8]) -> u64 { fn process(data: &[u8]) -> usize {
let mut answer = 0; let mut answer = 0;
let mut cards = vec![]; let mut cards = vec![];
@ -37,14 +37,14 @@ fn process(data: &[u8]) -> u64 {
if data.is_empty() { if data.is_empty() {
continue; continue;
} }
let (card, value) = data.split_at(6); let (card, value) = data.split_at(5);
let card = card.trim_ascii(); let value = &value[1..];
let mut arr = [0; ARRAY_SIZE]; let mut arr = [0; ARRAY_SIZE];
for &c in card { for &c in card {
let c = card_weight(c); let c = card_weight(c);
arr[c as usize] += 1; arr[c] += 1;
} }
let transposed = transpose(&arr); let transposed = transpose(&arr);
@ -70,10 +70,16 @@ fn process(data: &[u8]) -> u64 {
let mut pow = 1; let mut pow = 1;
for &val in value.iter().rev() { for &val in value.iter().rev() {
num += (val - b'0') as u64 * pow; num += (val - b'0') as usize * pow;
pow *= 10; pow *= 10;
} }
let card = (card_weight(card[0]) << 32)
+ (card_weight(card[1]) << 24)
+ (card_weight(card[2]) << 16)
+ (card_weight(card[3]) << 8)
+ card_weight(card[4]);
cards.push(( cards.push((
Card { Card {
val: card, val: card,
@ -83,85 +89,27 @@ fn process(data: &[u8]) -> u64 {
)); ));
} }
cards.sort_unstable_by(|(a, _), (b, _)| match (a.set_type, b.set_type) { cards.sort_unstable_by(|(a, _), (b, _)| -> Ordering {
(x, y) if x == y => { match (a.set_type, b.set_type) {
for (a, b) in a.val.iter().zip(b.val.iter()) { (x, y) if x == y => a.val.cmp(&b.val),
let ordering = cmp(*a, *b); (x, y) => {
let x = x as u8;
let y = y as u8;
if ordering != Ordering::Equal { x.cmp(&y)
return ordering;
}
} }
Ordering::Equal
}
(x, y) => {
let x = x as u8;
let y = y as u8;
x.cmp(&y)
} }
}); });
for (i, (_, v)) in cards.into_iter().enumerate() { for (i, (_, v)) in cards.into_iter().enumerate() {
let i = i + 1; let i = i + 1;
answer += v * i as u64; answer += v * i;
} }
answer answer
} }
#[inline]
const fn cmp(a: u8, b: u8) -> Ordering {
if a == b {
return Ordering::Equal;
}
match (a, b) {
(b'A', _) => Ordering::Greater,
(_, b'A') => Ordering::Less,
(b'K', _) => Ordering::Greater,
(_, b'K') => Ordering::Less,
(b'Q', _) => Ordering::Greater,
(_, b'Q') => Ordering::Less,
(b'J', _) => Ordering::Greater,
(_, b'J') => Ordering::Less,
(b'T', _) => Ordering::Greater,
(_, b'T') => Ordering::Less,
(b'9', _) => Ordering::Greater,
(_, b'9') => Ordering::Less,
(b'8', _) => Ordering::Greater,
(_, b'8') => Ordering::Less,
(b'7', _) => Ordering::Greater,
(_, b'7') => Ordering::Less,
(b'6', _) => Ordering::Greater,
(_, b'6') => Ordering::Less,
(b'5', _) => Ordering::Greater,
(_, b'5') => Ordering::Less,
(b'4', _) => Ordering::Greater,
(_, b'4') => Ordering::Less,
(b'3', _) => Ordering::Greater,
(_, b'3') => Ordering::Less,
(b'2', _) => Ordering::Greater,
(_, b'2') => Ordering::Less,
(_, _) => unreachable!(),
}
}
#[inline] #[inline]
fn transpose(ip: &[u8; ARRAY_SIZE]) -> [u8; 6] { fn transpose(ip: &[u8; ARRAY_SIZE]) -> [u8; 6] {
let mut out = [0; 6]; let mut out = [0; 6];
@ -174,12 +122,12 @@ fn transpose(ip: &[u8; ARRAY_SIZE]) -> [u8; 6] {
} }
#[inline] #[inline]
const fn card_weight(a: u8) -> u8 { const fn card_weight(a: u8) -> usize {
match a { match a {
b'2'..=b'9' => a - b'0', b'2'..=b'9' => (a - b'0') as usize,
b'J' => 10, b'T' => 10,
b'T' => 11, b'J' => 11,
b'Q' => 12, b'Q' => 12,
b'K' => 13, b'K' => 13,
b'A' => 14, b'A' => 14,

View File

@ -1,8 +1,6 @@
#![feature(byte_slice_trim_ascii)] #![feature(byte_slice_trim_ascii)]
#![feature(test)] #![feature(test)]
use std::cmp::Ordering;
extern crate test; extern crate test;
const INPUTS: [&[u8]; 2] = [ const INPUTS: [&[u8]; 2] = [
@ -11,8 +9,8 @@ const INPUTS: [&[u8]; 2] = [
]; ];
#[derive(Debug)] #[derive(Debug)]
struct Card<'a> { struct Card {
val: &'a [u8], val: usize,
ctype: SetType, ctype: SetType,
} }
@ -29,7 +27,7 @@ enum SetType {
const ARRAY_SIZE: usize = 14; const ARRAY_SIZE: usize = 14;
fn process(data: &[u8]) -> u64 { fn process(data: &[u8]) -> usize {
let mut answer = 0; let mut answer = 0;
let mut cards = vec![]; let mut cards = vec![];
@ -38,71 +36,63 @@ fn process(data: &[u8]) -> u64 {
if data.is_empty() { if data.is_empty() {
continue; continue;
} }
let (card, value) = data.split_at(6); let (card, value) = data.split_at(5);
let card = card.trim_ascii(); let value = &value[1..];
let mut arr = [0; ARRAY_SIZE]; let mut arr = [0; ARRAY_SIZE];
for &c in card.iter() { for &c in card.iter() {
let c = card_weight(c); let c = card_weight(c);
arr[c as usize] += 1; arr[c] += 1;
} }
let count = arr[card_weight(b'J') as usize]; let count = arr[card_weight(b'J')];
let transposed = transpose(&arr); let transposed = transpose(&arr);
let ctype = match (count, transposed) { let ctype = match (count, transposed) {
(_, [_, _, _, _, _, 1]) => SetType::Five, (_, [_, _, _, _, _, 1]) => SetType::Five,
(4, [_, 1, _, _, 1, _]) => SetType::Five, (4 | 1, [_, 1, _, _, 1, _]) => SetType::Five,
(1, [_, 1, _, _, 1, _]) => SetType::Five,
(_, [_, 1, _, _, 1, _]) => SetType::Four, (_, [_, 1, _, _, 1, _]) => SetType::Four,
(3, [_, _, 1, 1, _, _]) => SetType::Five, (3 | 2, [_, _, 1, 1, _, _]) => SetType::Five,
(2, [_, _, 1, 1, _, _]) => SetType::Five,
(_, [_, _, 1, 1, _, _]) => SetType::FullHouse, (_, [_, _, 1, 1, _, _]) => SetType::FullHouse,
(3, [_, 2, _, 1, _, _]) => SetType::Four, (3 | 1, [_, 2, _, 1, _, _]) => SetType::Four,
(1, [_, 2, _, 1, _, _]) => SetType::Four,
(_, [_, 2, _, 1, _, _]) => SetType::Three, (_, [_, 2, _, 1, _, _]) => SetType::Three,
(2, [_, 1, 2, _, _, _]) => SetType::Four, (2, [_, 1, 2, _, _, _]) => SetType::Four,
(1, [_, 1, 2, _, _, _]) => SetType::FullHouse, (1, [_, 1, 2, _, _, _]) => SetType::FullHouse,
(_, [_, 1, 2, _, _, _]) => SetType::Two, (_, [_, 1, 2, _, _, _]) => SetType::Two,
(2, [_, 3, 1, _, _, _]) => SetType::Three, (2 | 1, [_, 3, 1, _, _, _]) => SetType::Three,
(1, [_, 3, 1, _, _, _]) => SetType::Three,
(_, [_, 3, 1, _, _, _]) => SetType::One, (_, [_, 3, 1, _, _, _]) => SetType::One,
(1, [_, 5, _, _, _, _]) => SetType::One, (1, [_, 5, _, _, _, _]) => SetType::One,
(_, [_, 5, _, _, _, _]) => SetType::High, (_, [_, 5, _, _, _, _]) => SetType::High,
(_, _) => unreachable!(), // Never
(_, _) => SetType::High,
}; };
let mut num = 0; let mut num = 0;
let mut pow = 1; let mut pow = 1;
for &val in value.iter().rev() { for &val in value.iter().rev() {
num += (val - b'0') as u64 * pow; num += (val - b'0') as usize * pow;
pow *= 10; pow *= 10;
} }
let card = (card_weight(card[0]) << 32)
+ (card_weight(card[1]) << 24)
+ (card_weight(card[2]) << 16)
+ (card_weight(card[3]) << 8)
+ card_weight(card[4]);
cards.push((Card { val: card, ctype }, num)); cards.push((Card { val: card, ctype }, num));
} }
cards.sort_unstable_by(|(a, _), (b, _)| match (a.ctype, b.ctype) { cards.sort_unstable_by(|(a, _), (b, _)| match (a.ctype, b.ctype) {
(x, y) if x == y => { (x, y) if x == y => a.val.cmp(&b.val),
for (a, b) in a.val.iter().zip(b.val.iter()) {
let ordering = cmp(*a, *b);
if ordering != Ordering::Equal {
return ordering;
}
}
Ordering::Equal
}
(x, y) => { (x, y) => {
let x = x as u8; let x = x as u8;
let y = y as u8; let y = y as u8;
@ -114,7 +104,7 @@ fn process(data: &[u8]) -> u64 {
for (i, (_, v)) in cards.into_iter().enumerate() { for (i, (_, v)) in cards.into_iter().enumerate() {
let i = i + 1; let i = i + 1;
answer += v * i as u64; answer += v * i;
} }
answer answer
@ -132,11 +122,11 @@ fn transpose(ip: &[u8; ARRAY_SIZE]) -> [u8; 6] {
} }
#[inline] #[inline]
const fn card_weight(a: u8) -> u8 { const fn card_weight(a: u8) -> usize {
match a { match a {
b'J' => 1, b'J' => 1,
b'2'..=b'9' => a - b'0', b'2'..=b'9' => (a - b'0') as usize,
b'T' => 10, b'T' => 10,
b'Q' => 11, b'Q' => 11,
@ -147,56 +137,6 @@ const fn card_weight(a: u8) -> u8 {
} }
} }
#[inline]
const fn cmp(a: u8, b: u8) -> Ordering {
if a == b {
return Ordering::Equal;
}
match (a, b) {
(b'A', _) => Ordering::Greater,
(_, b'A') => Ordering::Less,
(b'K', _) => Ordering::Greater,
(_, b'K') => Ordering::Less,
(b'Q', _) => Ordering::Greater,
(_, b'Q') => Ordering::Less,
(b'T', _) => Ordering::Greater,
(_, b'T') => Ordering::Less,
(b'9', _) => Ordering::Greater,
(_, b'9') => Ordering::Less,
(b'8', _) => Ordering::Greater,
(_, b'8') => Ordering::Less,
(b'7', _) => Ordering::Greater,
(_, b'7') => Ordering::Less,
(b'6', _) => Ordering::Greater,
(_, b'6') => Ordering::Less,
(b'5', _) => Ordering::Greater,
(_, b'5') => Ordering::Less,
(b'4', _) => Ordering::Greater,
(_, b'4') => Ordering::Less,
(b'3', _) => Ordering::Greater,
(_, b'3') => Ordering::Less,
(b'2', _) => Ordering::Greater,
(_, b'2') => Ordering::Less,
(b'J', _) => Ordering::Greater,
(_, b'J') => Ordering::Less,
(_, _) => unreachable!(),
}
}
fn main() { fn main() {
for input in INPUTS.iter() { for input in INPUTS.iter() {
println!("total = {}", process(input)); println!("total = {}", process(input));