Skip to content

Commit

Permalink
Solution and README fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkAD88 committed Dec 21, 2023
1 parent 83bc451 commit a335a87
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 6 deletions.
File renamed without changes.
4 changes: 3 additions & 1 deletion 2023/19/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Dictionary<string, Workflow> workflows = [];
// Day 19

Dictionary<string, Workflow> workflows = [];
List<Part> parts = [];

var readingWorkflows = true;
Expand Down
81 changes: 79 additions & 2 deletions 2023/19/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,86 @@ Day Time Rank Score Time Rank Score

## Part One

This was basically a lexical parser. Not too hard to solve for but took a bit of time to fix an issue with my workflow
switching. I missed a required break near the end of the loop which cost me.
This was basically a lexical parser. Not too hard to solve for but took a bit of time to fix an issue with my workflow switching. I missed a required break near the end of the loop which cost me.

## Part Two

Haven't figured out how to approach this part. I think I'm simply going to leave it for a later date.

---

--- Day 19: Aplenty ---

The Elves of Gear Island are thankful for your help and send you on your way. They even have a hang glider that someone **_stole_** from Desert Island; since you're already going that direction, it would help them a lot if you would use it to get down there and return it to them.

As you reach the bottom of the **relentless avalanche of machine parts**, you discover that they're already forming a formidable heap. Don't worry, though - a group of Elves is already here organizing the parts, and they have a **system**.

To start, each part is rated in each of four categories:

- `x`: E**x**tremely cool looking
- `m`: **M**usical (it makes a noise when you hit it)
- `a`: **A**erodynamic
- `s`: **S**hiny

Then, each part is sent through a series of **workflows** that will ultimately **accept** or **reject** the part. Each workflow has a name and contains a list of **rules**; each rule specifies a condition and where to send the part if the condition is true. The first rule that matches the part being considered is applied immediately, and the part moves on to the destination described by the rule. (The last rule in each workflow has no condition and always applies if reached.)

Consider the workflow `ex{x>10:one,m<20:two,a>30:R,A}`. This workflow is named `ex` and contains four rules. If workflow `ex` were considering a specific part, it would perform the following steps in order:

- Rule "`x>10:one`": If the part's `x` is more than `10`, send the part to the workflow named `one`.
- Rule "`m<20:two`": Otherwise, if the part's `m` is less than `20`, send the part to the workflow named `two`.
- Rule "`a>30:R`": Otherwise, if the part's `a` is more than `30`, the part is immediately **rejected** (`R`).
- Rule "`A`": Otherwise, because no other rules matched the part, the part is immediately **accepted** (`A`).

If a part is sent to another workflow, it immediately switches to the start of that workflow instead and never returns. If a part is **accepted** (sent to `A`) or **rejected** (sent to `R`), the part immediately stops any further processing.

The system works, but it's not keeping up with the torrent of weird metal shapes. The Elves ask if you can help sort a few parts and give you the list of workflows and some part ratings (your puzzle input). For example:

```text
px{a<2006:qkq,m>2090:A,rfg}
pv{a>1716:R,A}
lnx{m>1548:A,A}
rfg{s<537:gd,x>2440:R,A}
qs{s>3448:A,lnx}
qkq{x<1416:A,crn}
crn{x>2662:A,R}
in{s<1351:px,qqz}
qqz{s>2770:qs,m<1801:hdj,R}
gd{a>3333:R,R}
hdj{m>838:A,pv}
{x=787,m=2655,a=1222,s=2876}
{x=1679,m=44,a=2067,s=496}
{x=2036,m=264,a=79,s=2244}
{x=2461,m=1339,a=466,s=291}
{x=2127,m=1623,a=2188,s=1013}
```

The workflows are listed first, followed by a blank line, then the ratings of the parts the Elves would like you to sort. All parts begin in the workflow named in. In this example, the five listed parts go through the following workflows:

- `{x=787,m=2655,a=1222,s=2876}`: `in` -> `qqz` -> `qs` -> `lnx` -> `A`
- `{x=1679,m=44,a=2067,s=496}`: `in` -> `px` -> `rfg` -> `gd` -> `R`
- `{x=2036,m=264,a=79,s=2244}`: `in` -> `qqz` -> `hdj` -> `pv` -> `A`
- `{x=2461,m=1339,a=466,s=291}`: `in` -> `px` -> `qkq` -> `crn` -> `R`
- `{x=2127,m=1623,a=2188,s=1013}`: `in` -> `px` -> `rfg` -> `A`

Ultimately, three parts are **accepted**. Adding up the `x`, `m`, `a`, and `s` rating for each of the accepted parts gives `7540` for the part with `x=787`, `4623` for the part with `x=2036`, and `6951` for the part with `x=2127`. Adding all of the ratings for **all** of the accepted parts gives the sum total of `19114`.

Sort through all of the parts you've been given; **what do you get if you add together all of the rating numbers for all of the parts that ultimately get accepted?**

Your puzzle answer was `280909`.

The first half of this puzzle is complete! It provides one gold star: *

--- Part Two ---

Even with your help, the sorting process still isn't fast enough.

One of the Elves comes up with a new plan: rather than sort parts individually through all of these workflows, maybe you can figure out in advance which combinations of ratings will be accepted or rejected.

Each of the four ratings (x, m, a, s) can have an integer value ranging from a minimum of 1 to a maximum of 4000. Of all possible distinct combinations of ratings, your job is to figure out which ones will be accepted.

In the above example, there are 167409079868000 distinct combinations of ratings that will be accepted.

Consider only your list of workflows; the list of part ratings that the Elves wanted you to sort is no longer relevant. How many distinct combinations of ratings will be accepted by the Elves' workflows?

Answer: still unsolved :cry::cry:cry:
3 changes: 1 addition & 2 deletions 2023/20/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Parse lines

// Day 20
using System.Diagnostics;

List<(char Type, string Name, string[] Destinations)> lines = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>pulsepropogation</RootNamespace>
</PropertyGroup>

<ItemGroup>
Expand Down
144 changes: 143 additions & 1 deletion 2023/20/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,146 @@ full input when designing my classes.

## Part Two

Chinese Remainder Theory to the rescue once again! Glad my short-term memory goes back at least two weeks. :)
Chinese Remainder Theory to the rescue once again! Glad my short-term memory goes back at least two weeks. :)


-----

--- Day 20: Pulse Propagation ---

With your help, the Elves manage to find the right parts and fix all of the machines. Now, they just need to send the command to boot up the machines and get the sand flowing again.

The machines are far apart and wired together with long cables. The **cables** don't connect to the machines directly, but rather to communication modules attached to the machines that perform various initialization tasks and also act as communication relays.

Modules communicate using **pulses**. Each pulse is either a **high pulse** or a **low pulse**. When a module sends a pulse, it sends that type of pulse to each module in its list of **destination modules**.

There are several different types of modules:

**Flip-flop** modules (prefix `%`) are either **on** or **off**; they are initially **off**. If a flip-flop module receives a high pulse, it is ignored and nothing happens. However, if a flip-flop module receives a low pulse, it **flips between on and off**. If it was off, it turns on and sends a high pulse. If it was on, it turns off and sends a low pulse.

**Conjunction** modules (prefix `&`) **remember** the type of the most recent pulse received from **each** of their connected input modules; they initially default to remembering a **low pulse** for each input. When a pulse is received, the conjunction module first updates its memory for that input. Then, if it remembers **high pulses** for all inputs, it sends a **low pulse**; otherwise, it sends a **high pulse**.

There is a single **broadcast module** (named `broadcaster`). When it receives a pulse, it sends the same pulse to all of its destination modules.

Here at Desert Machine Headquarters, there is a module with a single button on it called, aptly, the **button module**. When you push the button, a single **low pulse** is sent directly to the `broadcaster` module.

After pushing the button, you must wait until all pulses have been delivered and fully handled before pushing it again. Never push the button if modules are still processing pulses.

Pulses are always processed **in the order they are sent**. So, if a pulse is sent to modules `a`, `b`, and `c`, and then module `a` processes its pulse and sends more pulses, the pulses sent to modules `b` and `c` would have to be handled first.

The module configuration (your puzzle input) lists each module. The name of the module is preceded by a symbol identifying its type, if any. The name is then followed by an arrow and a list of its destination modules. For example:

```text
broadcaster -> a, b, c
%a -> b
%b -> c
%c -> inv
&inv -> a
```

In this module configuration, the broadcaster has three destination modules named `a`, `b`, and `c`. Each of these modules is a flip-flop module (as indicated by the `%` prefix). `a` outputs to `b` which outputs to `c` which outputs to another module named `inv`. `inv` is a conjunction module (as indicated by the `&` prefix) which, because it has only one input, acts like an inverter (it sends the opposite of the pulse type it receives); it outputs to `a`.

By pushing the button once, the following pulses are sent:

```text
button -low-> broadcaster
broadcaster -low-> a
broadcaster -low-> b
broadcaster -low-> c
a -high-> b
b -high-> c
c -high-> inv
inv -low-> a
a -low-> b
b -low-> c
c -low-> inv
inv -high-> a
```

After this sequence, the flip-flop modules all end up **off**, so pushing the button again repeats the same sequence.

Here's a more interesting example:

```text
broadcaster -> a
%a -> inv, con
&inv -> b
%b -> con
&con -> output
```

This module configuration includes the **broadcaster**, two flip-flops (named `a` and `b`), a single-input conjunction module (`inv`), a multi-input conjunction module (`con`), and an untyped module named `output` (for testing purposes). The multi-input conjunction module `con` watches the two flip-flop modules and, if they're both on, sends a **low pulse** to the `output` module.

Here's what happens if you push the button once:

```text
button -low-> broadcaster
broadcaster -low-> a
a -high-> inv
a -high-> con
inv -low-> b
con -high-> output
b -high-> con
con -low-> output
```

Both flip-flops turn on and a low pulse is sent to `output`! However, now that both flip-flops are on and `con` remembers a high pulse from each of its two inputs, pushing the button a second time does something different:

```text
button -low-> broadcaster
broadcaster -low-> a
a -low-> inv
a -low-> con
inv -high-> b
con -high-> output
```

Flip-flop **a** turns off! Now, **con** remembers a low pulse from module **a**, and so it sends only a high pulse to **output**.

Push the button a third time:

```text
button -low-> broadcaster
broadcaster -low-> a
a -high-> inv
a -high-> con
inv -low-> b
con -low-> output
b -low-> con
con -high-> output
```

This time, flip-flop `a` turns on, then flip-flop `b` turns off. However, before `b` can turn off, the pulse sent to `con` is handled first, so it **briefly remembers all high pulses** for its inputs and sends a low pulse to `output`. After that, flip-flop `b` turns off, which causes `con` to update its state and send a high pulse to `output`.

Finally, with `a` on and `b` off, push the button a fourth time:

```text
button -low-> broadcaster
broadcaster -low-> a
a -low-> inv
a -low-> con
inv -high-> b
con -high-> output
```

This completes the cycle: `a` turns off, causing `con` to remember only low pulses and restoring all modules to their original states.

To get the cables warmed up, the Elves have pushed the button `1000` times. How many pulses got sent as a result (including the pulses sent by the button itself)?

In the first example, the same thing happens every time the button is pushed: `8` low pulses and `4` high pulses are sent. So, after pushing the button `1000` times, `8000` low pulses and `4000` high pulses are sent. Multiplying these together gives `32000000`.

In the second example, after pushing the button `1000` times, `4250` low pulses and `2750` high pulses are sent. Multiplying these together gives `11687500`.

Consult your module configuration; determine the number of low pulses and high pulses that would be sent after pushing the button `1000` times, waiting for all pulses to be fully handled after each push of the button. **What do you get if you multiply the total number of low pulses sent by the total number of high pulses sent?**

Your puzzle answer was `886701120`.

--- Part Two ---

The final machine responsible for moving the sand down to Island Island has a module attached named `rx`. The machine turns on when a **single low pulse** is sent to `rx`.

Reset all modules to their default states. Waiting for all pulses to be fully handled after each button press, **what is the fewest number of button presses required to deliver a single low pulse to the module named `rx`?**

Your puzzle answer was `228134431501037`.

Both parts of this puzzle are complete! They provide two gold stars: **
18 changes: 18 additions & 0 deletions aoc2023.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "code", "code\code.csproj",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests.unit", "tests.unit\tests.unit.csproj", "{C5AA8803-D969-40A2-B502-F93C6D9E9A5C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2023", "2023", "{FB48BA6E-3152-4382-8151-BBA4387C9354}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "APlenty", "2023\19\APlenty.csproj", "{DD75BD0E-9220-4DDA-A7BA-D465A7086681}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PulsePropogation", "2023\20\PulsePropogation.csproj", "{E21398AA-260A-4F4B-85B7-03BBE0F377DB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -21,11 +27,23 @@ Global
{C5AA8803-D969-40A2-B502-F93C6D9E9A5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5AA8803-D969-40A2-B502-F93C6D9E9A5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5AA8803-D969-40A2-B502-F93C6D9E9A5C}.Release|Any CPU.Build.0 = Release|Any CPU
{DD75BD0E-9220-4DDA-A7BA-D465A7086681}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD75BD0E-9220-4DDA-A7BA-D465A7086681}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD75BD0E-9220-4DDA-A7BA-D465A7086681}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD75BD0E-9220-4DDA-A7BA-D465A7086681}.Release|Any CPU.Build.0 = Release|Any CPU
{E21398AA-260A-4F4B-85B7-03BBE0F377DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E21398AA-260A-4F4B-85B7-03BBE0F377DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E21398AA-260A-4F4B-85B7-03BBE0F377DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E21398AA-260A-4F4B-85B7-03BBE0F377DB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2033C34D-9525-44D9-A8A6-5602388FA63C}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{DD75BD0E-9220-4DDA-A7BA-D465A7086681} = {FB48BA6E-3152-4382-8151-BBA4387C9354}
{E21398AA-260A-4F4B-85B7-03BBE0F377DB} = {FB48BA6E-3152-4382-8151-BBA4387C9354}
EndGlobalSection
EndGlobal

0 comments on commit a335a87

Please sign in to comment.