Hacky quick generalise
This commit is contained in:
parent
cf1dd7c28e
commit
9395bea26a
18 changed files with 169 additions and 91 deletions
3
aoc
Executable file
3
aoc
Executable file
|
@ -0,0 +1,3 @@
|
|||
# The `aoc` part is required as the first argument is the name of the script
|
||||
node --max-old-space-size=8192 -e "let main = await import('./output/PCC.Main/index.js'); main.main()" -- aoc --aoc "$@"
|
||||
|
2
ebc
Executable file
2
ebc
Executable file
|
@ -0,0 +1,2 @@
|
|||
# The `ecc` part is required as the first argument is the name of the script
|
||||
node --max-old-space-size=8192 -e "let main = await import('./output/PCC.Main/index.js'); main.main()" -- ebc --ebc "$@"
|
1
pcc
1
pcc
|
@ -1,2 +1,3 @@
|
|||
# The `pcc` part is required as the first argument is the name of the script
|
||||
node --max-old-space-size=8192 -e "let main = await import('./output/PCC.Main/index.js'); main.main()" -- pcc "$@"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module Year2024.Quest01 where
|
||||
module EveryBodyCodes.Year2024.Quest01 where
|
||||
|
||||
import PCC.Lib
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
module Year2024.Quest02 where
|
||||
module EveryBodyCodes.Year2024.Quest02 where
|
||||
|
||||
import PCC.Lib
|
||||
|
||||
|
@ -55,9 +55,12 @@ part2 input = fold do
|
|||
overlapsAll i = Array.any (overlaps i) allIndices
|
||||
Array.length $ Array.filter identity $ map overlapsAll (0 .. (String.length sentence - 1))
|
||||
|
||||
|
||||
part3 :: String -> Effect Unit
|
||||
part3 input = part2 input
|
||||
part3 _input = log $ "Part 3 ==> <TODO>"
|
||||
|
||||
transpose :: Array String -> Array String
|
||||
transpose matrix = map fromChars $ Array.transpose $ map chars matrix
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
|
@ -1,10 +0,0 @@
|
|||
module Main where
|
||||
|
||||
import Control.Alternative (pure)
|
||||
import Data.Unit (Unit, unit)
|
||||
import Effect (Effect)
|
||||
|
||||
main :: Effect Unit
|
||||
main = do
|
||||
pure unit
|
||||
|
|
@ -30,7 +30,7 @@ import Data.Show (show)
|
|||
import Data.String as S
|
||||
import Data.String as String
|
||||
import Data.String.CodeUnits (fromCharArray, toCharArray)
|
||||
import Data.String.Pattern (Pattern(..))
|
||||
import Data.String.Pattern (Pattern)
|
||||
import Data.Unit (Unit)
|
||||
import Effect (Effect)
|
||||
import Node.Encoding (Encoding(..))
|
||||
|
|
|
@ -2,35 +2,53 @@ import fs from "fs";
|
|||
// import request from "request";
|
||||
// import path from "path";
|
||||
import { exec } from "child_process";
|
||||
import {AOC, EBC} from '../PCC.Types/index.js';
|
||||
// import dotenv from "dotenv";
|
||||
'use strict';
|
||||
// dotenv.config();
|
||||
export const bootstrap = function (year, quest) {
|
||||
|
||||
function handleErr(rest) {
|
||||
return function(err, body) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
if(rest) rest(body);
|
||||
};
|
||||
}
|
||||
|
||||
export const bootstrap = function (env) {
|
||||
const year = env.year;
|
||||
let quest = env.quest;
|
||||
const puzzle = env.puzzle == AOC.value? 'AOC' : 'EBC';
|
||||
// Left-pad quest!
|
||||
quest = `${quest}`;
|
||||
quest = `${env.quest}`;
|
||||
if (quest.length == 1) {
|
||||
quest = `0${quest}`;
|
||||
}
|
||||
// Write file
|
||||
fs.mkdir(`src/Year${year}`, { recursive: true }, function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
fs.readFile('templates/QuestXX.purs.template', 'utf8', function (err, body) {
|
||||
fs.mkdir(`src/${puzzle}/Year${year}`, { recursive: true }, handleErr(function () {
|
||||
fs.readFile(`templates/${puzzle}.purs.template`, 'utf8', handleErr(function (body) {
|
||||
let b = body.replace(/__YEAR__/g, year).replace(/__QUEST__/g, quest);
|
||||
fs.writeFile(`src/Year${year}/Quest${quest}.purs`, b, function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
console.log(`Open src/Year${year}/Quest${quest}.purs in your editor`);
|
||||
});
|
||||
});
|
||||
});
|
||||
fs.writeFile(`src/${puzzle}/Year${year}/Quest${quest}.purs`, b, handleErr(function () {
|
||||
console.log(`Open src/${puzzle}/Year${year}/Quest${quest}.purs in your editor`);
|
||||
console.log(`Creating blank input files at location ../../quests/${puzzle}/year${year}`);
|
||||
fs.mkdir(`quests/${puzzle}/year${year}`, { recursive: true }, handleErr(function () {
|
||||
fs.writeFile(`quests/${puzzle}/year${year}/quest${quest}-1`, 'ADD INPUT HERE', handleErr());
|
||||
fs.writeFile(`quests/${puzzle}/year${year}/quest${quest}-2`, 'ADD INPUT HERE', handleErr());
|
||||
if(puzzle === "EBC") fs.writeFile(`quests/${puzzle}/year${year}/quest${quest}-3`, 'ADD INPUT HERE', handleErr());
|
||||
}));
|
||||
}))
|
||||
}));
|
||||
}));
|
||||
};
|
||||
export const download = function (year, quest, cookie, filepath, cb) {
|
||||
|
||||
export const download = function (env, cookie, filepath, cb) {
|
||||
// TODO
|
||||
let year = env.year;
|
||||
let quest = env.quest;
|
||||
const puzzle = env.puzzle == AOC.value? 'aoc' : 'ebc';
|
||||
const puzzleName = env.puzzle == AOC.value? 'AOC' : 'EBC';
|
||||
return;
|
||||
|
||||
// const exists = fs.existsSync(filepath);
|
||||
|
@ -67,23 +85,36 @@ export const download = function (year, quest, cookie, filepath, cb) {
|
|||
// }
|
||||
};
|
||||
|
||||
export async function run(year, quest, part, inputfilepath) {
|
||||
export async function run(env, part) {
|
||||
let year = env.year;
|
||||
let quest = `${env.quest}`;
|
||||
// Left-pad quest!
|
||||
quest = `${quest}`;
|
||||
if (quest.length == 1) {
|
||||
quest = `0${quest}`;
|
||||
}
|
||||
const puzzle = env.puzzle == AOC.value? 'AOC' : 'EBC';
|
||||
runner(year, quest, puzzle, part, `quests/${puzzle}/year${year}/quest${quest}-${part}`);
|
||||
};
|
||||
|
||||
export async function test(env, part) {
|
||||
let year = env.year;
|
||||
let quest = `${env.quest}`;
|
||||
// Left-pad quest!
|
||||
if (quest.length == 1) {
|
||||
quest = `0${quest}`;
|
||||
}
|
||||
const puzzle = env.puzzle == AOC.value? 'AOC' : 'EBC';
|
||||
runner(year, quest, puzzle, part, `tests/${puzzle}/year${year}/quest${quest}-${part}`);
|
||||
};
|
||||
|
||||
async function runner(year, quest, puzzle, part, inputfilepath) {
|
||||
exec('spago build', async function (err, stdout, stderr) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
let Module = await import(`../Year${year}.Quest${quest}/index.js`);
|
||||
fs.readFile(inputfilepath, 'utf8', function (err, body) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
let Module = await import(`../${puzzle}.Year${year}.Quest${quest}/index.js`);
|
||||
fs.readFile(inputfilepath, 'utf8', handleErr(function(body) {
|
||||
if (part == 1 || !part) {
|
||||
console.time("Obtained in");
|
||||
Module.part1(body)();
|
||||
|
@ -94,12 +125,12 @@ export async function run(year, quest, part, inputfilepath) {
|
|||
Module.part2(body)();
|
||||
console.timeEnd("Obtained in");
|
||||
}
|
||||
if (part == 3 || !part) {
|
||||
if (part == 3 || (!part && puzzle === 'EBC')) {
|
||||
console.time("Obtained in");
|
||||
Module.part3(body)();
|
||||
console.timeEnd("Obtained in");
|
||||
}
|
||||
});
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
module PCC.Main where
|
||||
|
||||
import Options.Applicative
|
||||
|
||||
import Control.Alternative ((<|>))
|
||||
import Control.Apply ((<*>))
|
||||
import Control.Bind (bind, (=<<))
|
||||
import Data.Distributive (collect)
|
||||
import Data.Eq ((==))
|
||||
import Data.Foldable (for_)
|
||||
import Data.Functor ((<$>))
|
||||
import Data.Functor ((<$>), map)
|
||||
import Data.Maybe (Maybe(..), fromMaybe, optional)
|
||||
import Data.Semigroup ((<>))
|
||||
import Data.Show (show)
|
||||
|
@ -13,51 +14,57 @@ import Data.Unit (Unit)
|
|||
import Effect (Effect)
|
||||
import Effect.Uncurried as EFn
|
||||
import Node.Path (FilePath)
|
||||
import PCC.Lib (inputFileLocationYearQuest, testFileLocationYearQuest)
|
||||
|
||||
type Year = Int
|
||||
type Quest = Int
|
||||
type Part = Int
|
||||
type Cookie = String
|
||||
data Command = Bootstrap Year Quest | Download Year Quest Part | Run Year Quest (Maybe Part) | Test Year Quest (Maybe Part)
|
||||
import Options.Applicative (Parser, ParserInfo, argument, command, execParser, flag', fullDesc, header, help, helper, info, int, long, metavar, option, progDesc, short, subparser, (<**>))
|
||||
import PCC.Lib (inputFileLocationYearQuest)
|
||||
import PCC.Types (Command(..), Cookie, Env, Part, Puzzle(..), WithPuzzle)
|
||||
|
||||
configOptions :: Parser Command
|
||||
configOptions = subparser
|
||||
configOptions =
|
||||
mkConfig <$> (flagAOC <|> flagECC) <*> commandOptions
|
||||
where
|
||||
mkConfig puzzle makeCommand = makeCommand puzzle
|
||||
flagAOC = flag' AOC (long "aoc" <> help "Advent of Code puzzles")
|
||||
flagECC = flag' EBC (long "ebc" <> help "Everybody Codes puzzles")
|
||||
|
||||
commandOptions :: Parser (Puzzle -> Command)
|
||||
commandOptions = subparser
|
||||
( command "bootstrap" (info bootstrapOptions ( progDesc "Bootstrap a solution for a particular quest" ))
|
||||
<> command "download" (info downloadOptions ( progDesc "Download the puzzle input for a particular quest" ))
|
||||
<> command "run" (info runOptions ( progDesc "Run the solution for a particular quest" ))
|
||||
<> command "test" (info testOptions ( progDesc "Run the solution with the test input for a particular quest, the test input must be manually saved in a file called test<quest>" ))
|
||||
)
|
||||
|
||||
bootstrapOptions :: Parser Command
|
||||
bootstrapOptions =
|
||||
Bootstrap
|
||||
<$> argument int ( metavar "YEAR" )
|
||||
<*> argument int ( metavar "QUEST" )
|
||||
envOptions :: WithPuzzle Parser Env
|
||||
envOptions = mkEnv
|
||||
<$> argument int ( metavar "YEAR" )
|
||||
<*> argument int ( metavar "QUEST" )
|
||||
where
|
||||
mkEnv year quest = \puzzle -> {year, quest, puzzle} -- puzzle: fromMaybe AOC mpuzzle}
|
||||
|
||||
downloadOptions :: Parser Command
|
||||
bootstrapOptions :: WithPuzzle Parser Command
|
||||
bootstrapOptions =
|
||||
map Bootstrap <$> envOptions
|
||||
|
||||
downloadOptions :: WithPuzzle Parser Command
|
||||
downloadOptions =
|
||||
Download
|
||||
<$> argument int ( metavar "YEAR" )
|
||||
<*> argument int ( metavar "QUEST" )
|
||||
collect Download
|
||||
<$> envOptions
|
||||
<*> argument int ( metavar "PART" )
|
||||
|
||||
runOptions :: Parser Command
|
||||
runOptions :: WithPuzzle Parser Command
|
||||
runOptions =
|
||||
Run
|
||||
<$> argument int ( metavar "YEAR" )
|
||||
<*> argument int ( metavar "QUEST" )
|
||||
collect Run
|
||||
<$> envOptions
|
||||
<*> optional (option int
|
||||
( long "part"
|
||||
<> short 'p'
|
||||
<> metavar "PART"
|
||||
<> help "Use this to run only one part from that quest. Valid options are 1 or 2 or 3" ))
|
||||
|
||||
testOptions :: Parser Command
|
||||
testOptions :: WithPuzzle Parser Command
|
||||
testOptions =
|
||||
Test
|
||||
<$> argument int ( metavar "YEAR" )
|
||||
<*> argument int ( metavar "QUEST" )
|
||||
collect Test
|
||||
<$> envOptions
|
||||
<*> optional (option int
|
||||
( long "part"
|
||||
<> short 'p'
|
||||
|
@ -76,27 +83,26 @@ opts = info (configOptions <**> helper)
|
|||
foreign import pcc_cookie :: Effect String
|
||||
|
||||
doit :: Command -> Effect Unit
|
||||
doit (Bootstrap year quest) = do
|
||||
doit (Bootstrap env) = do
|
||||
-- doit (Download year quest part)
|
||||
EFn.runEffectFn2 bootstrap year quest
|
||||
doit (Download year quest part) = do
|
||||
EFn.runEffectFn1 bootstrap env
|
||||
doit (Download env part) = do
|
||||
cookie <- pcc_cookie
|
||||
loc <- inputFileLocationYearQuest (show year) (show quest) (show part)
|
||||
EFn.runEffectFn4 download year quest cookie loc
|
||||
doit (Run year quest mpart) = case mpart of
|
||||
Nothing -> runParts year quest [1,2,3]
|
||||
Just p -> runParts year quest [p]
|
||||
doit (Test year quest mpart) = do
|
||||
loc <- testFileLocationYearQuest (show year) (show quest)
|
||||
EFn.runEffectFn4 run year quest (fromMaybe 0 mpart) loc
|
||||
loc <- inputFileLocationYearQuest (show env.year) (show env.quest) (show part)
|
||||
EFn.runEffectFn3 download env cookie loc
|
||||
doit (Run env mpart) = case mpart of
|
||||
Nothing -> runParts env (if env.puzzle == AOC then [1,2] else [1,2,3])
|
||||
Just p -> runParts env [p]
|
||||
doit (Test env mpart) = do
|
||||
EFn.runEffectFn2 test env (fromMaybe 0 mpart)
|
||||
|
||||
runParts :: Int -> Int -> Array Int -> Effect Unit
|
||||
runParts year quest parts = for_ parts \part -> do
|
||||
loc <- inputFileLocationYearQuest (show year) (show quest) (show part)
|
||||
EFn.runEffectFn4 run year quest part loc
|
||||
runParts :: Env -> Array Int -> Effect Unit
|
||||
runParts env parts = for_ parts \part -> do
|
||||
EFn.runEffectFn2 run env part
|
||||
|
||||
foreign import bootstrap :: EFn.EffectFn2 Year Quest Unit
|
||||
foreign import download :: EFn.EffectFn4 Year Quest Cookie FilePath Unit
|
||||
foreign import bootstrap :: EFn.EffectFn1 Env Unit
|
||||
foreign import download :: EFn.EffectFn3 Env Cookie FilePath Unit
|
||||
|
||||
-- TODO: 'run' is async
|
||||
foreign import run :: EFn.EffectFn4 Year Quest Part String Unit
|
||||
foreign import run :: EFn.EffectFn2 Env Part Unit
|
||||
foreign import test :: EFn.EffectFn2 Env Part Unit
|
||||
|
|
18
src/PCC/Types.purs
Normal file
18
src/PCC/Types.purs
Normal file
|
@ -0,0 +1,18 @@
|
|||
module PCC.Types where
|
||||
|
||||
import Data.Eq (class Eq)
|
||||
import Data.Maybe (Maybe)
|
||||
|
||||
type Year = Int
|
||||
type Quest = Int
|
||||
type Part = Int
|
||||
type Cookie = String
|
||||
data Puzzle
|
||||
= AOC -- Advent of Code
|
||||
| EBC -- Everybody Codes
|
||||
derive instance Eq Puzzle
|
||||
type Env = {year :: Year, quest :: Quest, puzzle :: Puzzle}
|
||||
type WithPuzzle :: forall k. (Type -> k) -> Type -> k
|
||||
type WithPuzzle f a = f (Puzzle -> a)
|
||||
data Command = Bootstrap Env | Download Env Part | Run Env (Maybe Part) | Test Env (Maybe Part)
|
||||
|
25
templates/AOC.purs.template
Normal file
25
templates/AOC.purs.template
Normal file
|
@ -0,0 +1,25 @@
|
|||
module AOC.Year__YEAR__.Quest__QUEST__ where
|
||||
|
||||
import PCC.Lib
|
||||
import Data.Function (($))
|
||||
import Data.Functor (map)
|
||||
import Data.Semigroup ((<>))
|
||||
import Data.Unit (Unit)
|
||||
import Effect (Effect)
|
||||
import Effect.Class.Console (log)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Write your solutions here
|
||||
|
||||
part1 :: String -> Effect Unit
|
||||
part1 input = do
|
||||
let result = "<TODO>"
|
||||
log $ "Part 1 ==> " <> result
|
||||
|
||||
part2 :: String -> Effect Unit
|
||||
part2 input = do
|
||||
let result = "<TODO>"
|
||||
log $ "Part 2 ==> " <> result
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
module Year__YEAR__.Quest__QUEST__ where
|
||||
module EBC.Year__YEAR__.Quest__QUEST__ where
|
||||
|
||||
import PCC.Lib
|
||||
import Data.Function (($))
|
||||
|
@ -26,5 +26,4 @@ part3 input = do
|
|||
let result = "<TODO>"
|
||||
log $ "Part 3 ==> " <> result
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
Loading…
Reference in a new issue