This commit is contained in:
ctsk
2023-09-07 08:20:07 +02:00
parent 4ea7c5329c
commit 89c9c622d1
8 changed files with 442 additions and 3 deletions

View File

@@ -3,6 +3,7 @@
module Common where
import Data.ByteString.Char8 (ByteString)
import Data.Text qualified as T
data Answer where
@@ -25,4 +26,5 @@ type DayResult = Either String (Result, Result)
data Day
= TextDay (T.Text -> DayResult)
| StringDay (String -> DayResult)
| ByteStringDay (ByteString -> DayResult)
| ParsecDay (FilePath -> T.Text -> DayResult)

195
src/Days/D08.c Normal file
View File

@@ -0,0 +1,195 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
struct result_cell
{
int32_t fst;
int32_t snd;
};
struct stack_cell
{
char c;
int32_t p;
};
struct stack
{
struct stack_cell stk[10];
int32_t height;
};
struct stack init_stack()
{
struct stack result;
result.height = 0;
return result;
}
void stack_push(struct stack* stk, struct stack_cell v)
{
stk->stk[stk->height] = v;
stk->height++;
}
void stack_pop(struct stack *stk)
{
stk->height--;
}
struct stack_cell stack_top(struct stack *stk)
{
return stk->stk[stk->height - 1];
}
bool stack_empty(struct stack *stk)
{
return stk->height == 0;
}
void analyze_row(
char grid[],
bool result_visible[],
int32_t result_fwd[],
int32_t result_bwd[],
int32_t row,
int32_t w,
int32_t xs,
int32_t ys)
{
struct stack stk = init_stack();
struct stack_cell top;
int32_t j = 0;
char cur;
size_t pos;
stack_push(&stk, (struct stack_cell) { '9' + 1, 0}); //sentinel
for (; j < w; j++) {
pos = row*xs+j*ys;
cur = grid[pos];
while (stk.height > 0
&& (top = stack_top(&stk)).c < cur) {
result_fwd[row*xs+(top.p)*ys] = j - top.p;
stack_pop(&stk);
}
if (stk.height == 1) {
result_visible[row*xs+j*ys] = true;
}
result_bwd[pos] = j - top.p;
if (top.c == cur) {
result_fwd[row*xs+(top.p)*ys] = j - top.p;
stack_pop(&stk);
}
stack_push(&stk, (struct stack_cell) { cur, j});
}
while (stk.height > 1) {
top = stack_top(&stk);
result_fwd[row*xs+(top.p)*ys] = w - top.p - 1;
result_visible[row*xs+(top.p)*ys] = true;
stack_pop(&stk);
}
}
void analyze(
char grid[],
bool result_visible[],
int32_t result_fwd[],
int32_t result_bwd[],
int32_t h,
int32_t w,
int32_t xs,
int32_t ys)
{
for (int32_t i = 0; i < h; i++) {
analyze_row(grid, result_visible, result_fwd, result_bwd, i, w, xs, ys);
}
}
// void analyze_horizontal(char grid[], int32_t result_fwd[], int32_t result_bwd[], int32_t height, int32_t width)
// {
// analyze(grid, result_fwd, result_bwd, height, width, width, 1);
// }
// void analyze_vertical(char grid[], int32_t result_fwd[], int32_t result_bwd[], int32_t height, int32_t width)
// {
// analyze(grid, result_fwd, result_bwd, height, width, 1, height);
// }
// void print_grid(char grid[], int h, int w) {
// for (int i = 0; i < h; i++) {
// for (int j = 0; j < w; j++) {
// putchar(grid[i*w + j]);
// putchar(' ');
// }
// putchar('\n');
// }
// }
// void print_result(int grid[], int h, int w) {
// for (int i = 0; i < h; i++) {
// for (int j = 0; j < w; j++) {
// printf("%d ", grid[i*w+j]);
// }
// putchar('\n');
// }
// }
// int main()
// {
// FILE *fp = fopen("./data/08.in", "r");
// // Determine file size
// fseek(fp, 0L, SEEK_END);
// int fpsize = ftell(fp);
// fseek(fp, 0L, SEEK_SET);
// rewind(fp);
// char *buf = malloc(fpsize);
// char *grid = malloc(fpsize);
// fread(buf, 1, fpsize, fp);
// char *grid_ptr = grid;
// for (int i = 0; i < fpsize; i++) {
// *grid_ptr = buf[i];
// if (buf[i] != '\n') {
// grid_ptr++;
// }
// }
// int H = 5;
// int W = 5;
// print_grid(grid, H, W);
// int* result_fwd = malloc(fpsize * sizeof(int));
// int* result_bwd = malloc(fpsize * sizeof(int));
// analyze_vertical(grid, result_fwd, result_bwd, H, W);
// printf("\n D \n");
// print_result(result_fwd, H, W);
// printf("\n U \n");
// print_result(result_bwd, H, W);
// analyze_horizontal(grid, result_fwd, result_bwd, H, W);
// printf("\n R \n");
// print_result(result_fwd, H, W);
// printf("\n L \n");
// print_result(result_bwd, H, W);
// }

132
src/Days/D08.hs Normal file
View File

@@ -0,0 +1,132 @@
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE NamedFieldPuns #-}
module Days.D08 where
import Common
import Data.ByteString.Char8 qualified as BS
import Data.ByteString.Unsafe qualified as BS
import Data.Int
import Data.Maybe (fromMaybe)
import Data.Vector.Storable qualified as VS
import Data.Vector.Storable.Mutable qualified as VSM
import Foreign qualified as F
import Foreign.C qualified as FT
import GHC.IO (unsafePerformIO)
foreign import ccall unsafe "analyze"
cAnalyze ::
-- | grid
FT.CString ->
-- | result_visible
F.Ptr FT.CBool ->
-- | result_fwd
F.Ptr Int32 ->
-- | result_bwd
F.Ptr Int32 ->
-- | h
Int32 ->
-- | w
Int32 ->
-- | x_stride
Int32 ->
-- | y_stride
Int32 ->
IO ()
analyzeHorizontal :: FT.CString -> F.Ptr FT.CBool -> F.Ptr Int32 -> F.Ptr Int32 -> Int32 -> Int32 -> IO ()
analyzeHorizontal grid vis fwd bwd h w = cAnalyze grid vis fwd bwd h w w 1
analyzeVertical :: FT.CString -> F.Ptr FT.CBool -> F.Ptr Int32 -> F.Ptr Int32 -> Int32 -> Int32 -> IO ()
analyzeVertical grid vis fwd bwd h w = cAnalyze grid vis fwd bwd h w 1 h
data Intermediate = Intermediate
{ h :: Int
, w :: Int
, v :: VS.Vector FT.CBool
, u :: VS.Vector Int32
, d :: VS.Vector Int32
, l :: VS.Vector Int32
, r :: VS.Vector Int32
}
deriving (Show)
process :: BS.ByteString -> Intermediate
process bs =
let
w = fromMaybe 0 (BS.elemIndex '\n' bs)
h = (BS.length bs + 1) `div` (w + 1)
grid = BS.filter (/= '\n') bs
gridLen = h * w
in
unsafePerformIO $ do
v <- VSM.new gridLen
l <- VSM.unsafeNew gridLen
r <- VSM.unsafeNew gridLen
u <- VSM.unsafeNew gridLen
d <- VSM.unsafeNew gridLen
BS.unsafeUseAsCString
grid
( \gridptr ->
VSM.unsafeWith
v
( \vptr -> do
VSM.unsafeWith
l
( \lptr ->
VSM.unsafeWith
r
( \rptr ->
analyzeHorizontal
gridptr
vptr
rptr
lptr
(fromIntegral h)
(fromIntegral w)
)
)
VSM.unsafeWith
d
( \dptr ->
VSM.unsafeWith
u
( \uptr ->
analyzeVertical
gridptr
vptr
dptr
uptr
(fromIntegral h)
(fromIntegral w)
)
)
)
)
lf <- VS.freeze l
rf <- VS.freeze r
uf <- VS.freeze u
df <- VS.freeze d
vf <- VS.freeze v
return (Intermediate{h = h, w = w, u = uf, d = df, l = lf, r = rf, v = vf})
part1 :: Intermediate -> Int
part1 (Intermediate{v}) = VS.sum $ VS.map fromIntegral v
part2 :: Intermediate -> Int
part2 (Intermediate{u, d, l, r}) =
fromIntegral
. VS.maximum
$ VS.zipWith4 (\a1 a2 a3 a4 -> a1 * a2 * a3 * a4) u d l r
day :: Day
day =
ByteStringDay
( \bs ->
let ffiResult = process bs
in Right (definitive $ part1 ffiResult, definitive $ part2 ffiResult)
)

View File

@@ -18,12 +18,15 @@ import Days.D04 qualified as D04
import Days.D05 qualified as D05
import Days.D06 qualified as D06
import Days.D07 qualified as D07
import Days.D08 qualified as D08
import Data.ByteString.Char8 qualified as BS
import Data.Text.IO qualified as T
run :: Day -> FilePath -> IO DayResult
run (TextDay f) = fmap f . T.readFile
run (StringDay f) = fmap f . readFile
run (ByteStringDay f) = fmap f . BS.readFile
run (ParsecDay f) = \path -> f path <$> T.readFile path
days :: [[Day]]
@@ -35,4 +38,5 @@ days =
, [D05.day]
, [D06.day]
, [D07.day]
, [D08.day]
]