Compare commits

...

7 Commits

43 changed files with 3438 additions and 5 deletions

View File

@ -16,3 +16,6 @@ indent_size = 2
[*.ml]
indent_size = 2
[*.txt]
insert_final_newline = false

View File

@ -17,10 +17,10 @@
| 11 | ✓ | ✓ | [Crystal] |
| 12 | ✓ | ✓ | [Python] |
| 13 | ✓ | ✓ | [C++] |
| 14 | | | |
| 15 | | | |
| 16 | | | |
| 17 | | | |
| 14 | ✓ | ✓ | [Erlang] |
| 15 | ✓ | ✓ | [D] |
| 16 | ✓ | ✓ | [Haskell] |
| 17 | ✓ | ✓ | [Dart] |
| 18 | | | |
| 19 | | | |
| 20 | | | |
@ -49,3 +49,8 @@
[crystal]: https://crystal-lang.org
[python]: https://www.python.org
[c++]: https://isocpp.org
[erlang]: https://www.erlang.org
[d]: https://dlang.org
[haskell]: https://www.haskell.org
[dart]: https://dart.dev
[elixir]: https://elixir-lang.org

2
2021/day-14/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.beam
*.dump

6
2021/day-14/Justfile Normal file
View File

@ -0,0 +1,6 @@
@part PART INPUT_FILE="inputs/puzzle.txt":
erl -compile common.erl
escript part_{{PART}}.erl {{INPUT_FILE}}
clean:
rm -f *.beam *.dump

130
2021/day-14/common.erl Normal file
View File

@ -0,0 +1,130 @@
-module(common).
-export([parse_file/1, apply_rules/3, tally_elements/1, polymerization/3]).
-import(lists, [append/2]).
-import(string, [chomp/1, split/2, slice/2, slice/3]).
% File parsing
parse_rule(Raw) ->
[S, I] = split(chomp(Raw), " -> "),
#{{slice(S, 0, 1), slice(S, 1, 1)} => I}.
parse_seq(Sequence, Acc) ->
case slice(Sequence, 0, 1) of
"" -> Acc;
First -> parse_seq(slice(Sequence, 1), append(Acc, [First]))
end.
parse_lines(File, Mode, Sequence, Rules) ->
case {Mode, file:read_line(File)} of
{read_seq, {ok, "\n"}} ->
parse_lines(File, read_rules, Sequence, Rules);
{read_seq, {ok, Val}} ->
NextSequence = parse_seq(chomp(Val), []),
parse_lines(File, read_seq, NextSequence, Rules);
{read_rules, {ok, Val}} ->
NextRules = maps:merge(Rules, parse_rule(Val)),
parse_lines(File, read_rules, Sequence, NextRules);
{read_rules, eof} ->
{Sequence, Rules}
end.
parse_file(Path) ->
{ok, File} = file:open(Path, [read]),
parse_lines(File, read_seq, [], #{}).
% Helper functions
each_cons2(List = [A, B | _], F) when is_function(F) ->
Result = F(A, B),
each_cons2(tl(List), [Result], F).
each_cons2([A, B], Acc, F) when is_function(F) ->
Result = F(A, B),
lists:append(Acc, [Result]);
each_cons2(List = [A, B | _], Acc, F) when is_function(F) ->
Result = F(A, B),
each_cons2(tl(List), lists:append(Acc, [Result]), F).
succ(V) -> V + 1.
% Slow algorithm
apply_rules(Sequence, _, 0) ->
Sequence;
apply_rules(Sequence, Rules, Times) ->
NextSequence = apply_rules(Sequence, Rules),
apply_rules(NextSequence, Rules, Times - 1).
apply_rules(Sequence, Rules) ->
Cons = each_cons2(Sequence, fun (A, B) ->
[A, maps:get({A, B}, Rules), B]
end),
flatten_seq(Cons, []).
tally_elements(Sequence) ->
tally_elements(Sequence, #{}).
tally_elements([], Acc) ->
Acc;
tally_elements([Head | Tail], Acc) ->
Tally = maps:put(Head, 1 + maps:get(Head, Acc, 0), Acc),
tally_elements(Tail, Tally).
flatten_seq([[A, B, C]], Acc) ->
lists:append(Acc, [A, B, C]);
flatten_seq([[A, B | _] | Tail], Acc) ->
flatten_seq(Tail, lists:append(Acc, [A, B])).
% Fast algorithm
apply_rule(Pair, Rules) ->
maps:get(Pair, Rules).
update_tally({A, R, B}, Occ, Tally) ->
AddOccurences = fun(V) -> V + Occ end,
Tmp = maps:update_with({A, R}, AddOccurences, Occ, Tally),
maps:update_with({R, B}, AddOccurences, Occ, Tmp).
polymerization(Sequence, Rules, Times) when is_list(Sequence) ->
Cons = each_cons2(Sequence, fun(A, B) -> {A, B} end),
% first tally up all entries and build the counters
{Tally, Counter} = lists:foldl(fun(Pair = {A, _}, {Tal, Cnt}) ->
T = maps:update_with(Pair, fun succ/1, 1, Tal),
C = maps:update_with(A, fun succ/1, 1, Cnt),
{T, C}
end, {#{},#{}}, Cons),
% because the last one got skipped we have to add it manually
{_, Last} = lists:last(Cons),
Counter2 = maps:update_with(Last, fun succ/1, 1, Counter),
polymerization(Rules, Tally, Counter2, Times).
polymerization(_, _, Counter, 0) ->
Counter;
polymerization(Rules, Tally, Counter, Times) ->
{NewTally, NewCounter} = polymerization_step(Rules, Tally, Counter),
polymerization(Rules, NewTally, NewCounter, Times - 1).
polymerization_step(Rules, Tally, Counter) ->
maps:fold(fun({A, B}, Occ, {NewTally, NewCounter}) ->
Re = apply_rule({A, B}, Rules),
% Update occurance and element counters
NewTally2 = update_tally({A, Re, B}, Occ, NewTally),
NewCounter2 = maps:update_with(Re, fun(V) -> V + Occ end, 1, NewCounter),
{NewTally2, NewCounter2}
end, {#{}, Counter}, Tally).

View File

@ -0,0 +1,102 @@
KOKHCCHNKKFHBKVVHNPN
BN -> C
OS -> K
BK -> C
KO -> V
HF -> K
PS -> B
OK -> C
OC -> B
FH -> K
NV -> F
HO -> H
KK -> H
CV -> P
SC -> C
FK -> N
VV -> F
FN -> F
KP -> O
SB -> O
KF -> B
CH -> K
VF -> K
BH -> H
KV -> F
CO -> N
PK -> N
NH -> P
NN -> C
PP -> H
SH -> N
VO -> O
NC -> F
BC -> B
HC -> H
FS -> C
PN -> F
CK -> K
CN -> V
HS -> S
CB -> N
OF -> B
OV -> K
SK -> S
HP -> C
SN -> P
SP -> B
BP -> C
VP -> C
BS -> K
FV -> F
PH -> P
FF -> P
VK -> F
BV -> S
VB -> S
BF -> O
BB -> H
OB -> B
VS -> P
KB -> P
SF -> N
PF -> S
HH -> P
KN -> K
PC -> B
NB -> O
VC -> P
PV -> H
KH -> O
OP -> O
NF -> K
HN -> P
FC -> H
PO -> B
OH -> C
ON -> N
VN -> B
VH -> F
FO -> B
FP -> B
BO -> H
CC -> P
CS -> K
NO -> V
CF -> N
PB -> H
KS -> P
HK -> S
HB -> K
HV -> O
SV -> H
CP -> S
NP -> N
FB -> B
KC -> V
NS -> P
OO -> V
SO -> O
NK -> K
SS -> H

View File

@ -0,0 +1,18 @@
NNCB
CH -> B
HH -> N
CB -> H
NH -> C
HB -> C
HC -> B
HN -> C
NN -> C
BH -> H
NC -> B
NB -> B
BN -> B
BB -> N
BC -> B
CC -> N
CN -> C

16
2021/day-14/part_one.erl Normal file
View File

@ -0,0 +1,16 @@
-module(part_one).
-export([main/1]).
-import(common, [parse_file/1, polymerization/3]).
main(Args) ->
Path = lists:last(Args),
{Sequence, Rules} = parse_file(Path),
Counter = polymerization(Sequence, Rules, 10),
Values = maps:values(Counter),
Max = lists:max(Values),
Min = lists:min(Values),
io:format("~p~n", [Max - Min]).

16
2021/day-14/part_two.erl Normal file
View File

@ -0,0 +1,16 @@
-module(part_two).
-export([main/1]).
-import(common, [parse_file/1, polymerization/3]).
main(Args) ->
Path = lists:last(Args),
{Sequence, Rules} = parse_file(Path),
Counter = polymerization(Sequence, Rules, 40),
Values = maps:values(Counter),
Max = lists:max(Values),
Min = lists:min(Values),
io:format("~p~n", [Max - Min]).

1
2021/day-15/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.o

6
2021/day-15/Justfile Normal file
View File

@ -0,0 +1,6 @@
@part PART INPUT_FILE="inputs/puzzle.txt":
dmd -of=part_{{PART}} part_{{PART}}.d common.d
./part_{{PART}} {{INPUT_FILE}}
clean:
rm -f *.o part_one part_two

290
2021/day-15/common.d Normal file
View File

@ -0,0 +1,290 @@
module common;
import std.algorithm.iteration : filter, map;
import std.algorithm.searching : minElement, canFind;
import std.array : split;
import std.container.array : Array;
import std.container.rbtree : redBlackTree;
import std.container.binaryheap : BinaryHeap;
import std.conv : to;
import std.stdio;
import std.string : stripRight;
import std.typecons : tuple, Tuple;
private alias Buffer = Array!(Array!(uint));
struct CaveMap
{
private Buffer positions;
private const ulong tile_width;
private const ulong tile_height;
this(string path)
{
positions = parseFile(path);
}
this(string path, uint tiles)
{
auto buffer = parseFile(path);
tile_height = buffer.length;
tile_width = buffer[0].length;
tileRight(buffer, tiles);
tileDown(buffer, tiles);
positions = buffer;
}
private void tileRight(Buffer buffer, uint tiles)
{
foreach (tile_x; 1 .. tiles)
{
foreach (y; 0 .. tile_height)
{
foreach (x; 0 .. tile_width)
{
auto next_val = (buffer[y][x] + tile_x - 1) % 9;
next_val = next_val == 0 ? 1 : next_val + 1;
buffer[y].insertBack(next_val);
}
}
}
}
private void tileDown(Buffer buffer, uint tiles)
{
foreach (tile_y; 1 .. tiles)
{
const tile_y_begin = tile_y * tile_height;
foreach (y; 0 .. tile_height)
{
buffer.insertBack(Array!uint());
foreach (tile_x; 0 .. tiles)
{
const tile_x_begin = tile_x * tile_width;
foreach (x; 0 .. tile_width)
{
auto next_val = (buffer[y][tile_x_begin + x] + tile_y - 1) % 9;
next_val = next_val == 0 ? 1 : next_val + 1;
buffer[tile_y_begin + y].insertBack(next_val);
}
}
}
}
}
private Array!(Array!uint) parseFile(string path)
{
auto file = File(path, "r");
auto buffer = Buffer();
string line;
while ((line = file.readln()) !is null)
{
auto line_buffer = Array!uint();
foreach (weight; split(stripRight(line), "").map!(to!uint))
{
line_buffer.insertBack(weight);
}
buffer.insertBack(line_buffer);
}
return buffer;
}
void toString(scope void delegate(const(char)[]) sink) const
{
foreach (y; 0 .. positions.length)
{
foreach (x; 0 .. positions[y].length)
sink(to!string(positions[y][x]));
sink("\n");
}
}
}
private alias NodeId = Tuple!(uint, uint);
private struct Node
{
private NodeId id;
private uint weight;
void toString(scope void delegate(const(char)[]) sink) const
{
sink("(");
sink(to!string(this.id[0]));
sink(",");
sink(to!string(this.id[1]));
sink(";");
sink(to!string(this.weight));
sink(")");
}
}
struct Cave
{
private Array!Node[NodeId] nodes;
private NodeId start_node;
private NodeId end_node;
this(CaveMap cave_map)
{
auto node_id = NodeId(0, 0);
start_node = node_id;
uint y = 0;
foreach (row; cave_map.positions)
{
uint x = 0;
foreach (weight; row)
{
node_id = tuple(x, y);
nodes[node_id] = getNeighbors(x, y, cave_map.positions);
x++;
}
y++;
}
end_node = node_id;
}
uint lowestRisk()
{
auto safest_path = dijkstraFaster();
return safest_path[1][end_node];
}
private Tuple!(NodeId[NodeId], uint[NodeId]) dijkstraFaster()
{
uint[NodeId] distance;
NodeId[NodeId] previous;
foreach (node_id; nodes.byKey())
distance[node_id] = uint.max;
distance[start_node] = 0;
auto queue = redBlackTree(tuple(distance[start_node], start_node));
foreach (_, node; queue)
{
if (node == end_node)
break;
foreach (neighbor; nodes[node])
{
auto total_distance = distance[node] + neighbor.weight;
if (total_distance < distance[neighbor.id])
{
queue.removeKey(tuple(distance[neighbor.id], neighbor.id));
distance[neighbor.id] = total_distance;
previous[neighbor.id] = node;
queue.insert(tuple(distance[neighbor.id], neighbor.id));
}
}
}
return tuple(previous, distance);
}
private Tuple!(NodeId[NodeId], uint[NodeId]) dijkstraSlow()
{
bool[NodeId] unvisited;
uint[NodeId] distance;
NodeId[NodeId] previous;
foreach (node_id; nodes.byKey())
{
unvisited[node_id] = true;
distance[node_id] = uint.max;
}
distance[start_node] = 0;
unvisited.rehash;
distance.rehash;
while (unvisited.length != 0)
{
auto cur_node = unvisited.keys.minElement!(x => distance[x]);
if (cur_node == end_node)
{
break;
}
unvisited.remove(cur_node);
foreach (neighbor; nodes[cur_node])
{
if ((neighbor.id in unvisited) is null)
continue;
auto total_distance = distance[cur_node] + neighbor.weight;
if (total_distance < distance[neighbor.id])
{
distance[neighbor.id] = total_distance;
previous[neighbor.id] = cur_node;
}
}
}
return tuple(previous, distance);
}
private immutable int[2][4] DIRECTIONS = [
[-1, 0], [1, 0],
[0, -1], [0, 1],
];
private Array!Node getNeighbors(uint x, uint y, Buffer buf)
{
auto nodes = Array!Node();
foreach (dir; DIRECTIONS)
{
int dx = x + dir[0];
int dy = y + dir[1];
if (dx < 0 || dy < 0)
continue;
if (dx >= buf[0].length() || dy >= buf.length())
continue;
Node node = {id: tuple(dx, dy), buf[dy][dx]};
nodes.insertBack(node);
}
return nodes;
}
void toString(scope void delegate(const(char)[]) sink) const
{
foreach (id; this.nodes.byKey())
{
auto nodes = this.nodes[id];
sink("(");
sink(to!string(id[0]));
sink(",");
sink(to!string(id[1]));
sink(") { ");
foreach (node; nodes)
{
sink(to!string(node));
sink(" ");
}
sink("}\n");
}
}
}

View File

@ -0,0 +1,100 @@
1124751783612228519483416186391693192764152281421133194141163183224351733212394799536339411529842112
1299938854391228215712461147511117912185733411491416388811646391912138661213722223824151532652174491
3339197559983134739317425934547716331696227221882122961476799987711635499267472178182145359213635923
3275111279884782539314241187762113814171394161491634629424134127254634143155261122133724143114517171
3719252118791433135122231855197812222238914994648147192141951214948299478914959275216261881654181459
1611117951314292139456114142392662772939225937136486428161234281216234329234315111776511563151948482
2568826483341639224876553822412669632282339258375519267395999314194775717338955473111882125281113119
3211535497996954958315977618271374429983722314139733843419727946959246752499319415154271225547899217
9182381814515842193317619241122295417132515941811977373112934221316141138111911121121111793678163186
3844189817214722127981149242928145957137126937131386516329118218111198674162815191994371914762733967
2341991198198671797918854491942998311516141218456591158159195192211227471918835699934872448189793938
4914562622368117861639397331397217328431182986624263992197435816915439591962133158497224891382954532
7626651214813838216185911429272999894518636231382989678893369367388711391734813452975811156327428911
6619547343521975253174481211413831293662121339851815212317311237391545399111182897667911821424149598
9973191187241313192815214227191649743296915314888729322114168515823743777711899119191553298115729119
1139287494922611751257731929722771498336139611251121442114394245137973342111145499332316959261235284
2957197428427162517942347211164151149912112158641321995248419171621811597221619949431227171998811472
3942647388316719894411111531921126183713231811198382654685441319271454138942281133619242611612293827
7937119217256311112391437861121498616811956123353462521891125694135126297129995285155114368995531781
3451961913122271833382989211151286596622992323752134162138122516383189222433812253226845819142198221
2778119153629891339923532321818124533756116181684147179833125112111826952511175359231299984985971323
3111241849191534385261731569341927433476113958471723118832747854529179328115274125434719722218912131
3142339531392581988128137411211196234548128214999949588185228836196627923352221497911291281534111199
2247331434479875142918842833898559624238445292211715118881294135283574749565172271411631413491566199
5942278576394177315387294721122691617961774138211922471397191215938266718124567292193989959261637132
3165937631221963265792414421441393495719931248192344794567976762321141859115829128661211272472736862
6245216271127518123199222191484234611151315582117171596574729739922992724612599562343116361844622764
8113544322656226212151951279235114941989556194198115559251582213981835589429635885493383187341531965
9167334539972119189967382996641594933763662148772253141953186111414742999511119411388291132416516449
3613823811913288411123382135529243111267199921121439155729919326116169791514491996989971122517181152
8673611192477161631212112481894911858892968239143914865319658975331149334747126743512225484277694151
1573562476555619452428261559215411721579288335558515411134313992163812836653437129992833619198146362
1985275213511588337218921661953495211191671194622531866114745941231929893241192939732541431596251229
1265136118282217612545222191931962743537199362634214512441818421145212152171522295123221817416511192
8297798221482948311881157477219864767525628534952929138168821168196211119111519681828383199111919196
2534111997313111473186996839118152776719511994169115192212165984228917912783244345623614586619121326
5841498181267192895193154811932281737529524821838531213993721717189699211939288511893237393416182963
4291365191619323711913413926441339411267931111249294286234263722174939997111633217333235111582923441
1287162672582123747413148471918114922719181577167138269131143162782619895168443398922587114315692159
1265925622411611266789112299971891313715613359912627191225939742625214121139321211686759611131173819
2138953588999163543822384688714958315246965691333881631171314291246656696539111996811849918124146199
1246641611311144149732152211911939355725818779248359199268117115556131393567479697235189376137881341
2899323821125691382122622121279464139996512843263627599964991689326381239953514685697311811566519319
2736949532739218813892326217621918912123391961114292438971239114718244292915281445924621121161621333
3284227711481113791259114169152546556372395121491214478676766673451539272714243257528999117191132191
1491645992221246232691159831148693751711539199173418148515113374123227919399121713163369423119344294
9132112419279766149552388219119879126631964411873291514292382629182256527396923261916197289667422219
4435263531452645499818123111966429163563711994892138163281911392712947829833494132517185151159797235
3377999473376535692397871161267942211991447319627223732643859136911321291147933161219919912554143594
3949323991733462336411199416212721417161994737197381813716349241925143828318311249159179991229329171
1762136928289612837322111798838212828232194159395467913129898285979511558911359718111211715278482292
1118257643855683112121972927223668654922187717441698273158822189761169916992651219511457913769191141
1658133214212128183392871646163111119424394424612113962259435119311183885137744192432918197134375132
3591713174418138371811543613511348758114531127679321532212958111147949196891591688991927112311822659
1236514266615278952886111333113128112861958723136379141934411821192618183131222512832888648251713999
8123213361595969218132551112914729944243931512311795497816271296492513311341682399128274945195119112
2462825227696446183996491353919233459561152451155132169141431681617413626542619881461141223688519198
9621989515111471113381577698758628164221411666452251895517161458991756482464135232192737151721333241
1845633941916891433521922233371928968912324239271162428588753196413672815131973146761647212761387593
1213191632931181293214711139975148754136566435292974252811697693911887328591189183554433169371667213
4519131126388191338914531223891121466796183273431621945951424794146112514299112124121572531131372111
1331344969619935133794416261913442341424183712193444133541852317113515211181326734947129151289182833
1355758512615534971555911998128211268588155773916181718217932133414645114253821929111112911181223396
1921812718591189155234925136611421141621741789512111114849236968196293982164297416554297277314296498
2925818269222199331695127966441449818292484293218699694191219141796929886179788888289778893154112915
7349332956191336793938825411116431794116518627151175184126599498959181846349128914531693382871224114
2975711544499872811921879322745419629143299769241363453113298718372441111116129736331374245812629681
2419398835867978148157517197312837563211153716146118174293922233694112229384117648726494771916746336
2322473321962284111112435812293374144731592114895311931296931978723998962913118278111921783414789472
7421933294181593157278951313456166911311561151111468883991937345182554571275781533927232981213941792
1668835358177241114335636733193482471442299199859434499861711136613117473328576171139593142184617345
5339642815719926226879311379167325793396941892597215179614941121636812111539912741116971188971946499
7581333191573246312732795518731212368211299298495989164122116531125184283943222911391615243311251361
9492966914243222969499792183412424152773224381646928911135496174621299924524112331962952547214129323
2729194232211462151119459711313211822621531163797412446181172721913949189555142143791213834886518948
2754215791553781642269915399358262512494443343121198134218639979927842122994421127962456193396136699
8271611911227341219949383285981988595252121593129637541475392137413899839912239225135459931743267972
1332131171959982211855642861212718138325111114239233279171544919563891942832117949581464743292494391
5144166291493181763279457131141327146537961189933599395341461291371919123151359118199368625742376117
1636191619675379923419873222911119821251129276117414194193998142948136713325351617571519395951914216
6863238911796142259595658671251783127926389189168272138182549591741951937121824471372228139189226966
1398611275788896954682838421735924943417195641181143853286733633811931911189111341679192676374118319
7425912442414194918974222966129621141925526265112323617731363617133673511925955331462169117293471296
8311915233126172592295451734596934578641991127992454954549337724839691119685881916643781992923996572
7168461267393883112656311283191232322499117185912521188899182419918914911212513325386275539329721472
4418929132119621184239621272934448319225211997924183117861911136919317465941177911127948161449124731
9271153581452542386794695144559617972331134217961265186239771199325391879412411821372724989746391111
3752522113112162859371199119415298331514424128999524132149996846199915924629121214916277199845231181
8461129155427192357991128752552628161188794894374724397322312139214838121389889613819783991892292158
4999141138619713275215481369646529918918936887478711111135124192624311852137911719581517593373711112
9228956819912994881488113276489314945969876898139152128325918347915249723837311238669717631918756448
1272313111232619631582529173782417217912411245971957172218911853664936489571219898133821585115925152
1324983253974657485632276593196749111921819449973115611494598217724911344731933114417612111528118291
8521515271325847484517496514692991413334913117194153459926716822674627611191634943962214123151399931
1141639315518932691635973515217951611118329247113938399181114133617465682162932426295992195929458883
8229351197214731215324515139273121165384915712119675514893281751526119183679227515364941156137548174
6116894132781317191382191142114151317798773795981911112434921641114411589131331717998932176521898319
5362677393912312215419378899211815319464811111851912257961211293814411559971191515896993251933358962
6926527339383986515331739126963132928923957918814875739969162479336291216879152811764569629328261149
7598541186247351172883789213137911264491891391569216562276119911413437411237411934123311912324427449

View File

@ -0,0 +1,10 @@
1163751742
1381373672
2136511328
3694931569
7463417111
1319128137
1359912421
3125421639
1293138521
2311944581

12
2021/day-15/part_one.d Normal file
View File

@ -0,0 +1,12 @@
import std.stdio;
import common : CaveMap, Cave;
void main(string[] args)
{
auto immutable path = args[1];
auto cave_map = CaveMap(path);
auto graph = Cave(cave_map);
writeln(graph.lowestRisk());
}

13
2021/day-15/part_two.d Normal file
View File

@ -0,0 +1,13 @@
import std.stdio;
import common : CaveMap, Cave;
void main(string[] args)
{
auto immutable path = args[1];
auto cave_map = CaveMap(path, 5);
auto graph = Cave(cave_map);
writeln(graph.lowestRisk());
}

2
2021/day-16/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.hi
*.o

6
2021/day-16/Justfile Normal file
View File

@ -0,0 +1,6 @@
@part PART INPUT_FILE="inputs/puzzle.txt":
ghc part_{{PART}}.hs common.hs
./part_{{PART}} {{INPUT_FILE}}
clean:
rm -f *.hi *.o part_one part_two

139
2021/day-16/common.hs Normal file
View File

@ -0,0 +1,139 @@
{-# LANGUAGE NamedFieldPuns #-}
{-# OPTIONS_GHC -Wno-incomplete-patterns #-}
module Common
( parseFile,
parseRootPacket,
sumPacketVersions,
evalPacket,
)
where
import Data.Char (digitToInt)
import Data.Maybe (mapMaybe)
import Numeric (readHex)
import System.IO (readFile)
import Text.Printf (printf)
type Bit = Int
data Op = Sum | Product | Min | Max | Gt | Lt | Eq
deriving (Show)
data PacketData = Literal Int | Operator Op [Packet]
deriving (Show)
data Packet = Packet
{ version :: Int,
content :: PacketData
}
deriving (Show)
-- Parsing
parseFile :: String -> IO [Bit]
parseFile path = do
content <- readFile path
let intList = concat (mapMaybe hexCharToBits content)
return intList
hexCharToBits :: Char -> Maybe [Bit]
hexCharToBits char =
case readHex [char] of
[(val, _)] -> Just $ intToBits (val :: Int)
_ -> Nothing
where
intToBits i = map digitToInt $ printf "%04b" i
bitsToInt :: [Bit] -> Int
bitsToInt [] = 0
bitsToInt bs =
bitsToInt' bs (length bs - 1)
where
bitsToInt' [] _ = 0
bitsToInt' (0 : bs) p = bitsToInt' bs (p - 1)
bitsToInt' (1 : bs) p = (2 ^ p) + bitsToInt' bs (p - 1)
parseRootPacket :: [Bit] -> Maybe Packet
parseRootPacket bits = do
(_, packet) <- parsePacket bits
Just packet
parsePacket :: [Bit] -> Maybe (Int, Packet)
parsePacket [] = Nothing
parsePacket bits = do
(consumed, content) <- case kind of
0 -> parseOperator (drop 6 bits) Sum (6, [])
1 -> parseOperator (drop 6 bits) Product (6, [])
2 -> parseOperator (drop 6 bits) Min (6, [])
3 -> parseOperator (drop 6 bits) Max (6, [])
4 -> parseLiteral (drop 6 bits) (6, [])
5 -> parseOperator (drop 6 bits) Gt (6, [])
6 -> parseOperator (drop 6 bits) Lt (6, [])
7 -> parseOperator (drop 6 bits) Eq (6, [])
let packet = Packet {version, content}
Just (consumed, packet)
where
version = bitsToInt $ take 3 bits
kind = bitsToInt $ take 3 $ drop 3 bits
parseOperator :: [Bit] -> Op -> (Int, [Packet]) -> Maybe (Int, PacketData)
parseOperator bits op (consumed, memo) =
case bits of
(0 : bs) -> do
let totalBitLength = bitsToInt (take 15 bs)
let opConsumed = consumed + 16
let nextBits = take totalBitLength (drop 15 bs)
packets <- parsePacketsDense nextBits totalBitLength []
let newConsumed = opConsumed + totalBitLength
Just (newConsumed, Operator op packets)
(1 : bs) -> do
let subPacketCount = bitsToInt (take 11 bs)
let opConsumed = consumed + 12
let nextBits = drop 11 bs
(pkgConsumed, packets) <- subPackets nextBits subPacketCount (0, [])
let newConsumed = opConsumed + pkgConsumed
Just (newConsumed, Operator op packets)
_ ->
Nothing
where
parsePacketsDense bs 0 packets = Just packets
parsePacketsDense bs rem packets = do
(pkgConsumed, packet) <- parsePacket bs
parsePacketsDense (drop pkgConsumed bs) (rem - pkgConsumed) (packets ++ [packet])
subPackets bs 0 (consumed, packets) = Just (consumed, packets)
subPackets bs n (consumed, packets) = do
(pkgConsumed, packet) <- parsePacket bs
let nextBits = drop pkgConsumed bs
subPackets nextBits (n - 1) (consumed + pkgConsumed, packets ++ [packet])
parseLiteral :: [Bit] -> (Int, [Bit]) -> Maybe (Int, PacketData)
parseLiteral bits (consumed, memo) =
case bits of
(1 : bs) -> parseLiteral (drop 4 bs) (consumed + 5, memo ++ take 4 bs)
(0 : bs) -> Just (consumed + 5, Literal (bitsToInt (memo ++ take 4 bs)))
_ -> Nothing
-- Results
sumPacketVersions :: Packet -> Int -> Int
sumPacketVersions Packet {version, content = Literal _} memo = memo + version
sumPacketVersions Packet {version, content = Operator _ packets} memo =
version + sum (map (`sumPacketVersions` memo) packets)
evalPacket :: Packet -> Int
evalPacket Packet {content} =
case content of
Literal val -> val
Operator Sum packets -> sum (map evalPacket packets)
Operator Product packets -> product (map evalPacket packets)
Operator Min packets -> minimum (map evalPacket packets)
Operator Max packets -> maximum (map evalPacket packets)
Operator Gt [x, y] -> evalBinOp (>) x y
Operator Lt [x, y] -> evalBinOp (<) x y
Operator Eq [x, y] -> evalBinOp (==) x y
where
evalBinOp f x y =
let px = evalPacket x
py = evalPacket y
in if px `f` py then 1 else 0

View File

@ -0,0 +1 @@
A20D5CECBD6C061006E7801224AF251AEA06D2319904921880113A931A1402A9D83D43C9FFCC1E56FF29890E00C42984337BF22C502008C26982801009426937320124E602BC01192F4A74FD7B70692F4A74FD7B700403170400F7002DC00E7003C400B0023700082C601DF8C00D30038005AA0013F40044E7002D400D10030C008000574000AB958B4B8011074C0249769913893469A72200B42673F26A005567FCC13FE673004F003341006615421830200F4608E7142629294F92861A840118F1184C0129637C007C24B19AA2C96335400013B0C0198F716213180370AE39C7620043E0D4788B440232CB34D80260008645C86D16C401B85D0BA2D18025A00ACE7F275324137FD73428200ECDFBEFF2BDCDA70D5FE5339D95B3B6C98C1DA006772F9DC9025B057331BF7D8B65108018092599C669B4B201356763475D00480010E89709E090002130CA28C62300265C188034BA007CA58EA6FB4CDA12799FD8098021400F94A6F95E3ECC73A77359A4EFCB09CEF799A35280433D1BCCA666D5EFD6A5A389542A7DCCC010958D85EC0119EED04A73F69703669466A048C01E14FFEFD229ADD052466ED37BD8B4E1D10074B3FF8CF2BBE0094D56D7E38CADA0FA80123C8F75F9C764D29DA814E4693C4854C0118AD3C0A60144E364D944D02C99F4F82100607600AC8F6365C91EC6CBB3A072C404011CE8025221D2A0337158200C97001F6978A1CE4FFBE7C4A5050402E9ECEE709D3FE7296A894F4C6A75467EB8959F4C013815C00FACEF38A7297F42AD2600B7006A0200EC538D51500010B88919624CE694C0027B91951125AFF7B9B1682040253D006E8000844138F105C0010D84D1D2304B213007213900D95B73FE914CC9FCBFA9EEA81802FA0094A34CA3649F019800B48890C2382002E727DF7293C1B900A160008642B87312C0010F8DB08610080331720FC580

View File

@ -0,0 +1 @@
D2FE28

View File

@ -0,0 +1 @@
38006F45291200

View File

@ -0,0 +1 @@
EE00D40C823060

12
2021/day-16/part_one.hs Normal file
View File

@ -0,0 +1,12 @@
module Main where
import Common (parseFile, parseRootPacket, sumPacketVersions)
import System.Environment (getArgs)
main = do
args <- getArgs
intList <- parseFile $ head args
let rootPacket = parseRootPacket intList
let results = maybe 0 (`sumPacketVersions` 0) rootPacket
print results

12
2021/day-16/part_two.hs Normal file
View File

@ -0,0 +1,12 @@
module Main where
import Common (evalPacket, parseFile, parseRootPacket)
import System.Environment (getArgs)
main = do
args <- getArgs
intList <- parseFile $ head args
let rootPacket = parseRootPacket intList
let results = maybe 0 evalPacket rootPacket
print results

2
2021/day-17/Justfile Normal file
View File

@ -0,0 +1,2 @@
@part PART INPUT_FILE="inputs/puzzle.txt":
dart part_{{PART}}.dart {{INPUT_FILE}}

79
2021/day-17/common.dart Normal file
View File

@ -0,0 +1,79 @@
import "dart:io";
import "dart:math";
List<List<int>> parseFile(String path) {
final file = File(path);
final content = file.readAsStringSync();
final coordinates = content
.trim().split(" ")
.skip(2).where((e) => e.isNotEmpty)
.map((elem) {
return elem
.split("=").last
.replaceFirst(",", "").split("..")
.map(int.parse)
.toList();
})
.toList();
return coordinates;
}
List<int> step(int x, int y, int xv, int yv) {
final dx = x + xv;
final dy = y + yv;
final dxv = xv + (xv > 0 ? -1 : (xv < 0 ? 1 : 0));
final dyv = yv - 1;
return [dx, dy, dxv, dyv];
}
bool hasMissed(int x, int y, List<List<int>> area) {
var missed = (x - area[0][1]) > 0;
return missed || (y - area[1][0]) < 0;
}
bool isInTargetArea(int x, int y, List<List<int>> area) {
return
x >= area[0][0] &&
x <= area[0][1] &&
y >= area[1][0] &&
y <= area[1][1];
}
bool landsInTargetArea(int init_vx, int init_vy, List<List<int>> area) {
var x = 0;
var y = 0;
var vx = init_vx;
var vy = init_vy;
while (true) {
final result = step(x, y, vx, vy);
if (isInTargetArea(result[0], result[1], area)) return true;
if (hasMissed(result[0], result[1], area)) return false;
x = result[0];
y = result[1];
vx = result[2];
vy = result[3];
}
}
int? findMaxHeight(int init_vx, int init_vy, List<List<int>> area) {
var x = 0;
var y = 0;
var vx = init_vx;
var vy = init_vy;
var max_height = 0;
while (true) {
final result = step(x, y, vx, vy);
max_height = max(result[1], max_height);
if (isInTargetArea(result[0], result[1], area)) return max_height;
if (hasMissed(result[0], result[1], area)) return null;
x = result[0];
y = result[1];
vx = result[2];
vy = result[3];
}
}

View File

@ -0,0 +1 @@
target area: x=277..318, y=-92..-53

View File

@ -0,0 +1 @@
target area: x=20..30, y=-10..-5

23
2021/day-17/part_one.dart Normal file
View File

@ -0,0 +1,23 @@
import "dart:math";
import "common.dart";
main(List<String> args) {
final path = args.first;
final target_area = parseFile(path);
final max_xv = target_area[0][1];
final max_yv = target_area[1][0].abs();
var max_height = 0;
Iterable.generate(max_xv, (v) => v + 1).forEach((x) {
Iterable.generate(max_yv, (v) => v + 1).forEach((y) {
final result = findMaxHeight(x, y, target_area);
if (result != null) {
max_height = max(result, max_height);
}
});
});
print(max_height);
}

30
2021/day-17/part_two.dart Normal file
View File

@ -0,0 +1,30 @@
import "dart:math";
import "common.dart";
main(List<String> args) {
final path = args.first;
final target_area = parseFile(path);
final max_xv = target_area[0][1];
final max_yv = target_area[1][0];
var velocity_count = 0;
var yv = max_yv;
while (yv < max_yv.abs()) {
var xv = max_xv;
while (xv > 0) {
if (landsInTargetArea(xv, yv, target_area)) {
velocity_count += 1;
}
xv -= 1;
}
yv += 1;
}
print(velocity_count);
}

1
2022/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target/

19
2022/Justfile Normal file
View File

@ -0,0 +1,19 @@
@_run_day DAY PART INPUT:
just \
--working-directory "./day-{{DAY}}" \
--justfile "./day-{{DAY}}/Justfile" \
part {{PART}} {{INPUT}}
day DAYS="all" PARTS="one,two" INPUT_FILE="":
#!/usr/bin/env ruby
days = "{{DAYS}}" == "all" ? Dir["day-*"] : "{{DAYS}}".split(",")
input_file = "{{INPUT_FILE}}".then do |f|
(f.include?("/") || f.empty?) ? f : "inputs/#{f}.txt"
end
days.each do |day|
day = day.delete_prefix("day-")
"{{PARTS}}".split(",").each do |part|
part_num = part == "one" ? 1 : 2
puts "Day #{day}.#{part_num}: " + `just _run_day #{day} #{part} '#{input_file}'`
end
end

35
2022/README.md Normal file
View File

@ -0,0 +1,35 @@
# [Advent of Code 2022](https://adventofcode.com/2022)
## Progress
| Day | Part 1 | Part 2 | Language |
| :-: | :----: | :----: | :------- |
| 01 | ✓ | ✓ | [Rust] |
| 02 | | | |
| 03 | | | |
| 04 | | | |
| 05 | | | |
| 06 | | | |
| 07 | | | |
| 08 | | | |
| 09 | | | |
| 10 | | | |
| 11 | | | |
| 12 | | | |
| 13 | | | |
| 14 | | | |
| 15 | | | |
| 16 | | | |
| 17 | | | |
| 18 | | | |
| 19 | | | |
| 20 | | | |
| 21 | | | |
| 22 | | | |
| 23 | | | |
| 24 | | | |
| 25 | | | |
<!-- links -->
[rust]: https://www.rust-lang.org

7
2022/day-01/Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aoc-2022-01"
version = "0.1.0"

6
2022/day-01/Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[package]
name = "aoc-2022-01"
version = "0.1.0"
edition = "2021"
[dependencies]

5
2022/day-01/Justfile Normal file
View File

@ -0,0 +1,5 @@
@part PART INPUT_FILE="inputs/puzzle.txt":
cargo run --bin part{{PART}} -- {{INPUT_FILE}}
clean:
cargo clean

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000

View File

@ -0,0 +1,11 @@
use std::{env, io};
fn main() -> io::Result<()> {
let infile_path = env::args().nth(1).expect("input file");
let sums = aoc_2022_01::input_sums(infile_path)?;
let max = sums.max().unwrap();
println!("{max}");
Ok(())
}

View File

@ -0,0 +1,12 @@
use std::{env, io};
fn main() -> io::Result<()> {
let infile_path = env::args().nth(1).expect("input file");
let mut sums = aoc_2022_01::input_sums(infile_path)?.collect::<Vec<_>>();
sums.sort_by(|a, b| b.partial_cmp(a).unwrap());
let three_highest_sum: &u32 = &sums[..3].iter().sum();
println!("{three_highest_sum}");
Ok(())
}

44
2022/day-01/src/lib.rs Normal file
View File

@ -0,0 +1,44 @@
use std::{
fs::File,
io::{self, BufRead, BufReader},
path::Path,
};
pub fn input_sums<P>(path: P) -> io::Result<impl Iterator<Item = u32>>
where
P: AsRef<Path>,
{
let inputs = parse_input_file(path)?;
let sums = inputs.into_iter().map(|val| val.into_iter().sum());
Ok(sums)
}
fn parse_input_file<P>(path: P) -> io::Result<Vec<Vec<u32>>>
where
P: AsRef<Path>,
{
let file = File::open(path)?;
let reader = BufReader::new(file);
let mut inputs = Vec::new();
let mut current = Vec::new();
for line in reader.lines() {
let line = line?;
if line.is_empty() {
inputs.push(current);
current = Vec::new();
} else {
let value = line.parse().expect("invalid number");
current.push(value);
}
}
if !current.is_empty() {
inputs.push(current);
}
Ok(inputs)
}

View File

@ -8,4 +8,5 @@
- [2018](2018/README.md) (0% completed)
- [2019](2019/README.md) (0% completed)
- [2020](2020/README.md) (20% completed)
- [2021](2021/README.md) (52% completed)
- [2021](2021/README.md) (68% completed)
- [2022](2022/README.md) (4% completed)