Skip to content

Commit

Permalink
Merge pull request #14 from ephemient/ephemient-patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient authored Dec 2, 2024
2 parents 84a58e2 + fea200d commit 29bc862
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 45 deletions.
16 changes: 9 additions & 7 deletions hs/src/Day2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@
module Day2 (part1, part2) where

import Common (readEntire)
import Data.Ix (inRange)
import Control.Monad (ap, foldM_, guard)
import Data.Functor (($>))
import Data.List (inits, tails)
import Data.Maybe (isJust)
import Data.Text (Text)
import Data.Text qualified as T (lines, words)
import Data.Text.Read qualified as T (decimal)

parse :: Text -> Either String [[Int]]
parse = mapM (mapM (readEntire T.decimal) . T.words) . T.lines

isSafe, isSafe' :: [Int] -> Bool
isSafe report = all (inRange (-3, -1)) delta || all (inRange (1, 3)) delta
isSafe1, isSafe2 :: [Int] -> Bool
isSafe1 = isJust . foldM_ go EQ . (zipWith (-) `ap` drop 1)
where
delta = zipWith (-) report $ drop 1 report
isSafe' report = any isSafe [a ++ b | (a, _ : b) <- zip (inits report) (tails report)]
go k x = guard (x /= 0 && abs x <= 3 && k /= compare 0 x) $> compare x 0
isSafe2 report = any isSafe1 [a ++ b | (a, _ : b) <- zip (inits report) (tails report)]

part1 :: Text -> Either String Int
part1 input = length . filter isSafe <$> parse input
part1 input = length . filter isSafe1 <$> parse input

part2 :: Text -> Either String Int
part2 input = length . filter isSafe' <$> parse input
part2 input = length . filter isSafe2 <$> parse input
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,22 @@ class Day2(input: String) {
private fun isSafe1(report: IntArray): Boolean {
var decreasing = false
var increasing = false
for (i in 0..report.size - 2) {
when (report[i + 1] - report[i]) {
in -3..-1 -> decreasing = true
in 1..3 -> increasing = true
else -> return false
return (0..report.size - 2).all {
when (report[it + 1] - report[it]) {
in -3..-1 -> !increasing.also { decreasing = true }
in 1..3 -> !decreasing.also { increasing = true }
else -> false
}
}
return !(decreasing && increasing)
}

private fun isSafe2(report: IntArray): Boolean {
if (report.isEmpty()) return true
val report2 = report.copyOf(report.size - 1)
for (i in report2.lastIndex downTo 0) {
if (isSafe1(report2)) return true
report2[i] = report[i + 1]
val report2 = report.copyOfRange(1, report.size)
return isSafe1(report2) || report2.indices.any {
report2[it] = report[it]
isSafe1(report2)
}
return isSafe1(report2)
}
}
}
43 changes: 16 additions & 27 deletions rs/src/day2.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
fn parse(data: &str) -> Vec<Vec<i32>> {
data.lines()
.flat_map(|line| {
line.split_ascii_whitespace()
.map(|level| level.parse::<i32>().ok())
.collect::<Option<Vec<_>>>()
})
.collect::<Vec<_>>()
use std::cmp::Ordering;

fn parse(data: &str) -> impl Iterator<Item = Vec<i32>> + use<'_> {
data.lines().flat_map(|line| {
line.split_ascii_whitespace()
.map(|level| level.parse::<i32>().ok())
.collect::<Option<Vec<_>>>()
})
}

fn is_safe_1(report: &[i32]) -> bool {
let mut decreasing = false;
let mut increasing = false;
report
.iter()
.zip(report.iter().skip(1))
.all(|(x, y)| match x - y {
-3..=-1 => {
decreasing = true;
!increasing
}
1..=3 => {
increasing = true;
!decreasing
.try_fold(Ordering::Equal, |cmp, (x, y)| {
if x != y && (x - y).abs() <= 3 {
Some(x.cmp(y)).filter(|cmp2| cmp != cmp2.reverse())
} else {
None
}
_ => false,
})
.is_some()
}

fn is_safe_2(report: &[i32]) -> bool {
Expand All @@ -41,17 +36,11 @@ fn is_safe_2(report: &[i32]) -> bool {
}

pub fn part1(data: &str) -> usize {
parse(data)
.into_iter()
.filter(|report| is_safe_1(report))
.count()
parse(data).filter(|report| is_safe_1(report)).count()
}

pub fn part2(data: &str) -> usize {
parse(data)
.into_iter()
.filter(|report| is_safe_2(report))
.count()
parse(data).filter(|report| is_safe_2(report)).count()
}

#[cfg(test)]
Expand Down

0 comments on commit 29bc862

Please sign in to comment.