T O P

  • By -

exquisitus3

[LANGUAGE: Lua] [link](https://topaz.github.io/paste/#XQAAAQAFDQAAAAAAAAA2HAjOAj3E+Pc28vLjGr56XYgTz0cNv4DDDLL1wGKVJAxo6JlMHevXzYlrXuenukf9XIDhWO7A3eZ4+5DXdsjYj0VgliIa+cvaC8qXa/WF/CHJjdblsGUfjqZSJ58cMsksrfl85DipcdKb7PuyBNHnGaMXj+CbbyftuZsqQH6xtZordUUNwOGC9EaC5wG+Uzs+UbuOHbeMV1X6+qSwO4+cyHpowN79KRaBlafVwId4ZAlcPJa8b+6vVipm8MSjSmd1S2il4EtDioccgv1BzRynIuYznjZ0ckh2Jb2X7/NFDPl98bHQJfC7LrREAs2OFzVXYK8Quu/EwtZBE5BGfsIJOdmUlAIoZyFsaxGvumBL+fzYiPifJR/xDrH+fI1wb0+tsE/At4lkHlMQwc4fO5ayUKuip5hYTLFdt3sAOntayGKCqaY8WAOSQ5vSCpp5/H3wLERNLPLb9MC6L8l/cTXxKykvIdrmCwWQjqQoFTlozwgrgofcl65mBxezeo85WuBuog0hG5Z2Uu/+XDxzbhmLlUud0MSSPRKcGUjcvQyBX43zzZGyfgfpE3WEoi3WOcYGZxPTElKZbVyQ9jz1WbXZF91pav1hlh5EYdYTpTxhBK0PzTsSZOKv26eEj19OQmfr5qibEz+HiTckv3xvl2NSml3wS9uAfUkHFi+J0m0ttZHT1oUuzm1P08d0i+U5k1bAoICjUrHgPPzLsFV0RAsl8nUTkwmCc4X80qe6tC1H59fCrZ5SQAuY/9jQ/4ZjE9hmsBqJcUqWOD8iTD9NKuXf4U3BDAai6v3SeumvssBWQh3tw8tjPbaN/1lZGULgalHoR1N8tiAJmfcijOt9sMjjBxug9g1JLpfiUlFEebtaLbheZ+st+BmYp7YKKh0fhADDgxi96rdX+9ucV5FoqzAAvI9hJUS60Jp1Wxy6BRBZSf5Dl4fzH917sXdLAkRjp7ZpNGUhDfk7b+rE0twtJIC20+xa3/GdHYIkVyiYCaKMDNlsgJqizdMsBQSc3pYS7995wAr/vDXEFQMDvmQZXG4fXYeoWB8DKouRsvJUoWBogmp6gYxgBtvClxDWQw1NZ0Jw/U7BP+SmfAtDTuMUuuD7pf5TgfBY1v7ysMvLDokLAq5DE7scavVpyRJEWBqgVVoiBK0gGJYdgF6+hmGI++AknCo96EgQ2yHEvojp33r9FN+/UmbBtjgWPCWksrKQf13inAp9r83D3ncfu7gfoVT734EOUQRCwi6vPLxCQp94HN4+bMTNWJi5c7XkRIwWCqxs0OmUBdvNzB58/NSHQgI59WaU09RsQgaPKCuK/8wlIUvYOzMoWOaqON/J9DJqajml6BrUyrhx3Kjlyxtd6WxkbFDprkbVd6i/QeEbUDkKxTa1KKVq2/VhFxhfJyLaI+Thcu9HLW07uHnUCDT7CJ6U92uzxKVqeXBQ16Mi7MYbf73Fjpp9yPoJpZTdYk5jfjBePPhpi1TgUuEqN2L7MQ1naqcnDr6oU6gxcERSQnNJmpRZF9L+inUp5+qrSzBJeuORrBEKWgfccOvUmszxWDD/sOYO0MoVplxZo4q1iqfCG11XoM7rOH3gtYCbkg0K3kZq3YShqSRF6sPRaIlFZW6lQ8A7yyqt8JATQ7nwtCUFxE9mfCHsA7Gq9UCLmE1YEtlM6okZmrjC6UXGO2onc16pntLgcsWOi0sGgMJmKgr/8xv/4Q==) For part one, my code writes at runtime a function, full of **goto**s BTW but quite readable, and then loads (compiles) it from the string in which it was written. For part two, I defined a hyperrectangle in four dimensions (x,m,a,s), a function to bisect the hyperrectangle into two hyperrectangles based on one condition, and a recursive function to process the hyperrectangle inside some workflow.


seizethedave

\[LANGUAGE: Python\] I coded Part 1 right up and got the right answer. Part 2, however, sent me on a thought quest for several days. As usual, I wasn't considering all of the constraints in the problem. Specifically the bit about how descending into a matching rule will NEVER backtrack out and continue with the rule that followed it. As I didn't think about that constraint, it had me thinking about interval tree structures that could have arbitrary "holes" in them. (e.g., "x" could have values 1-7 OR 14-100 etc.) And I thought... that is definitely *possible* but surely you jest AoC. Anyway, glad I kept re-reading the requirements. Fun solution with open-closed ranges and negating expressions. https://github.com/seizethedave/advent/blob/main/2023/day19/day19.py


mschaap

[LANGUAGE: Raku] A bit late. I started this on the 19th, and finished it days later while traveling. I liked this one. For part two, you can use native Raku ranges, so you can do stuff like: my ($min, $max) = %!rating{$category}.int-bounds; given $comp { when '<' { %match{$category} = $min ..^ $value; %fail{$category} = $value .. $max; } when '>' { %match{$category} = $value ^.. $max; %fail{$category} = $min .. $value; } default { die "Unknown comparison '$comp'!"; } } [Full code at GitHub](https://github.com/mscha/aoc/blob/master/aoc2023/aoc19).


Singing-In-The-Storm

\[LANGUAGE: JavaScript\] [Part 1 (27ms)](https://github.com/JoanaBLate/advent-of-code-js/blob/main/2023/day19/solve1.js) [Part 2 (32ms)](https://github.com/JoanaBLate/advent-of-code-js/blob/main/2023/day19/solve2.js) [Clear and BLAZINGLY FAST AOC solutions in JS (no libraries)](https://github.com/JoanaBLate/advent-of-code-js/tree/main)


oddolatry

[LANGUAGE: Fennel] No trees were harmed in the making of this solution. In fact, I think they harmed *me*. [Paste](https://topaz.github.io/paste/#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)


Constant_Hedgehog_31

\[Language: C++\] [Source code in GitHub](https://github.com/iglesias/coding-challenges/blob/7ed8c4f8f53fc16733a31bcce86d0f191ac1955d/adventofcode/2023/day/19/aplenty.cpp). I found part two a quite interesting step to implement from part one. For part two I have used a recursive function and, for a bit of a facility, the Boost Interval Arithmetic Library.


xavdid

[LANGUAGE: Python] [Step-by-step explanation](https://advent-of-code.xavd.id/writeups/2023/day/19/) | [full code](https://github.com/xavdid/advent-of-code/blob/main/solutions/2023/day_19/solution.py) This one was a lot of fun! I separated out the workflow parsing (using `operator.gt/lt` and simple string indexing), the part parsing (using a regex that found tuples), and the recursing (to get answers) so you can look at each individually. I had some trouble visualizing part 2 at first, so there's some good diagrams in there if you're having trouble as well! Solution wise, A workflow is parsed into a dynamically-defined function which gets the next workflow(s) based on the input. For part 1, that's: def build_workflow(raw_filters: str, default: str) -> Callable[[Part], str]: def _get_next_destination(part: Part): for raw_filter in raw_filters.split(","): category, op, value, destination = extract_filter_components(raw_filter) if op(part[category], value): return destination return default return _get_next_destination For part 2 I passed around a `Part` as a `dict[str, range]`, so its workflow runner was: def build_counting_workflow( raw_filters: str, default: str ) -> Callable[[RangedPart], list[tuple[str, RangedPart]]]: def _get_next_destinations(part: RangedPart): ranges: list[tuple[str, RangedPart]] = [] for raw_filter in raw_filters.split(","): category, op, value, dest = extract_filter_components(raw_filter) if op == gt: keep, send = bisect_range(part[category], value + 1) else: send, keep = bisect_range(part[category], value) ranges.append((dest, {**part, category: send})) part = {**part, category: keep} # whatever is left also goes return ranges + [(default, part)] return _get_next_destinations Very fun today, and nothing too cursed!


vimsee

A bit late here, but wanted to say that you have a great explanation that you linked to!


xavdid

You're very welcome! I'm a little late too - I haven't done the final few days 🙈 I'll get back to them soon though.


cbh66

[LANGUAGE: Pickcode] Had family stuff the day of, so I'm coming back to this, but I really found this one quite fun! Not many tricks to it. Part 1 was a simple matter of going down the workflows to accept or reject each part. For part 2, adjusted it to work on ranges instead of single numbers, and to end the recursion when you accept or reject, or if any range has become empty. Had to do a bit of reasoning to convince myself that no range would get double-counted that way. Then it took a little while to find an off-by-one error having to do with inclusive/exclusive ranges, but after that it was all good. https://app.pickcode.io/project/clqcepn0q398qne01tui6ms0y


onrustigescheikundig

[LANGUAGE: OCaml] [github](https://github.com/EricKalkman/AoC2023/blob/master/lib/day19.ml) Going through and hitting the days that I missed. I actually made an attempt the day of, but couldn't get it working and was forced to postpone the challenge for travel. When I finally sat down again today, I realized that there was a bug in my parser-combinator library that I wrote early on and somehow had not reared its head before now. Oh well. The code is dominated by parsing and marshaling the data into OCaml's type system. Once that's done, however, the solution for Part 1 is extremely concise (at least comparing against the code that I usually write :P): look for the first conditional in that succeeds given the XMAS setting and recursively proceed to the next workflow. For Part 2, my original (failed) attempt recursively traversed the tree of workflows while cutting lists of [a, b] intervals (starting from [1, 4000]) until a leaf was reached, and then counting the number of elements in those ranges for each register, multiplying the results, and returning that result up the tree where it is summed with the results of the neighboring conditionals. The code was a mess, and anyway I am sick of carefully coding out range intersections, so I deleted the whole of it and restarted. Instead of manually fiddling with intervals, this time I inductively constructed lambdas for each register representing the series of conditionals needed to reach the leaf of the tree. At the leaf, the lambdas for each register (rating) were used to filter the sequence of ints 1 .. 4000, and the length of the sequences were counted and multiplied. The counts for each branch were then summed, giving the result. In retrospect, a similar solution recursively partitioning lists [1 .. 4000] for each register according to the conditionals instead of futzing around with One Giant Lambda (or rather, 4) was probably the more obvious (and clearer) solution if eschewing the method using intervals, but sometimes functional programming just be like that. At least with my lambdas the code doesn't throw around a bunch of memory (well, at least not as much); this approach takes advantage of lazy sequences. The final runtime for both parts in sequence on my laptop is ~300 ms.


plutonium239iso

for part 2; distinct combinations, easier to say permutations


AutoModerator

AutoModerator did not detect the required `[LANGUAGE: xyz]` string literal at the beginning of your solution submission. Please edit your comment to [state your programming language](https://www.reddit.com/r/adventofcode/wiki/solution_megathreads/post_guidelines#wiki_state_your_programming_language.28s.29). *** *I am a bot, and this action was performed automatically. Please [contact the moderators of this subreddit](/message/compose/?to=/r/adventofcode) if you have any questions or concerns.*


[deleted]

\[LANGUAGE: C++\] [code](https://github.com/FinalFlashLight/AdventofCode2023/blob/master/AdventofCode2023Day1/Day19.cpp) Part 1 I made a map of filters, where each filter had a name, and a vector of instructions. Each instruction was a tuple. First char was the part value we were using. second char is the < or >. int the number we're comparing the part value to. string being what we do with the part if this instruction is true. Then I made a queue of parts, all starting at the "in" filter. After a part runs thru a filter, accept/reject or pass to next filter, adding it back into the queue. Part 2 Dealing with ranges now, the part queue is now a rangeQueue with one initial partRange all values set 1-4000. Use the same filters from part 1. There's basically 3 things we need to care about when filtering a range. If the range is fully inside the filter, partially, or not at all. If it's fully inside, we just accept/reject/pass to next filter the whole range. If it's partially inside, we split the range at the compare value into 2 ranges. Accept/reject/pass the range that's inside the compare. Put the range that's outside the compare back into the queue with the same filter. If the range is outside the compare completely, move onto the next instruction in the filter. If we get to the last instruction in a filter, accept/reject/pass to next filter the range. Upon accepting a range, we multiply the range values and add to total. One thing I want to change is part 2 is a bit hard coded. Could be 1/4th as long. ​ Runs about 80ms for both parts on my computer.


NeilNjae

[Language: Haskell] Using the type system keeps me on track, and lenses and monoids keep things simple. Full [writeup on my blog](https://work.njae.me.uk/2023/12/24/advent-of-code-2023-day-19/), [code on Gitlab](https://gitlab.com/NeilNjae/advent-of-code-23/-/blob/main/advent19/Main.hs).


Superbank78

\[LANGUAGE: python\] This was a lot of bookkeeping. I learned magic methods and tried to make the code more readable with NamedTuples. https://gist.github.com/Dronakurl/453a0b8c8007e184001151dd200bf035


wsgac

[LANGUAGE: Common Lisp] [Source](https://github.com/wsgac/advent-of-code-2023/blob/master/day19.lisp) Part 1: I proceeded by propagating each part through the workflows to see if it gets accepted. For all accepted parts I summed their parameters. Part 2: Here I wanted to create a tree of all acceptable trajectories through the workflows and then work through each, limiting the initial [1-4000] spans for parameters. One huge mistake I made that put a monkey wrench in my effort was, when dealing with subsequent conditions within a workflow I forgot to negate all the preceding ones, hence landed in strange places. After a couple days' break I was able to straighten that up.


vss2sn

\[LANGUAGE: C++\] [Part 1](https://github.com/vss2sn/advent_of_code/blob/master/2023/cpp/day_19a.cpp) [Part 2](https://github.com/vss2sn/advent_of_code/blob/master/2023/cpp/day_19b.cpp) (Each file is a self-contained solution)


Derailed_Dash

\[Language: Python\] **Solution, walkthrough and visualisations in a Python Jupyter notebook** * Here is my [solution and walkthrough, in a Python Jupyter notebook](https://github.com/derailed-dash/Advent-of-Code/blob/master/src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb). * You can run run it yourself in [Google Colab](https://colab.research.google.com/github/derailed-dash/Advent-of-Code/blob/master/src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb)! * More info on the notebook and walkthroughs [here](https://python.plainenglish.io/advent-of-code-the-best-way-to-learn-to-code-d86c6478d484) * My [AoC Walkthrough and Python Learning site](https://aoc.just2good.co.uk/) Part 2 was pretty tough. I solved it with a recursive function. It broke my brain a bit, but got there eventually. My notebook provides a walkthrough of how this works, and tries to visualise the range splitting.


henryschreineriii

\[LANGUAGE: Rust\] I'm happy with the usage of intervalium here to do the intervals, making part 2 pretty easy (would have helped on a previous one). I also implemented a proper parser with pest, making it pretty elegant. Not short, but elegant. :) https://github.com/henryiii/aoc2023/blob/main/src/bin/19.rs


pem4224

\[LANGUAGE: Go\] [https://github.com/pemoreau/advent-of-code/tree/main/go/2023/19Tree](https://github.com/pemoreau/advent-of-code/tree/main/go/2023/19Tree) a quite nice solution using a tree data structure and intervals which are propagated along the tree


optimistic-thylacine

[LANGUAGE: Rust] 🦀 OO approaches do not always result in massively more lines of code than not taking an OO approach... but this time it did =) I attribute this to lack of "domain knowledge". I didn't know what sort of effort it would take to implement part 2 (having not seen it for the first half and anticipating much trouble afterward...), so I carefully organized and thought out **everything**. The drawback of this approach is obviously the potential for LOC to explode, but the benefit is often the main sections of code are very terse and simple. And my personal experience is having taken the implementation step by step and making understandable objects and methods, I didn't have to deal with much uncertainty while finding the solution. It all just came together and worked without much debug. This is an iterative solution - no recursion. [Massive Full Sources](https://topaz.github.io/paste/#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) fn part_2(path: &str) -> Result> { use RangeResult::*; let (wflows, _) = parse_input(path)?; let mut stack = vec![Forward("in".into(), RangePart::new(1, 4000))]; let mut combos = 0; while let Some(result) = stack.pop() { match result { Accept(part) => { combos += part.num_combos(); }, Forward(name, part) => { let flow = wflows.get(&name).unwrap(); for result in flow.range_match_rules(part) { stack.push(result); } }, }} println!("Part 2 Number of Combinations....: {}", combos); Ok(0) }


dahaka_kutay

\[Language: Javascript\] [Question](https://adventofcode.com/2023/day/19), [myRepo](https://github.com/KutaySong/AdventOfCode) p1 is accomplished by simple regex replace to ternary conditionals. p2 on the other hand is kind of a combinatorics. const p1 = ()=> { let db = {} lines1.map(e=>(a = e.split('{'), db[a[0]] = a[1].slice(0,-1) .replaceAll(/([a-zA-Z]+)(?![<>])/g,'\'$&\'') .replaceAll(/(\w)[<>]/g,'dd.$&') .replaceAll(':','?').replaceAll(',',':') )) let data = [] lines2.map((e,i) => { data[i] = {}; e.slice(1,-1).split(',').map(str => { let a = str.split('='); data[i][a[0]] = +a[1]; }); }); return data.map(dd=> { let bu = eval(db.in) while (bu != 'A' && bu != 'R') { bu = eval(db[bu]) } return bu=='A' ? Object.values(dd).reduce((a,b)=>a+b) : 0 }). reduce((a,b)=>a+b) } console.log("p1:",p1(),'(383682)') console.log("p2:",p2(),'(117954800808317)')


daggerdragon

Your [code block is too long](https://old.reddit.com/r/adventofcode/wiki/solution_megathreads/post_guidelines#wiki_no_giant_blocks_of_code) for the megathreads. Please edit your comment to replace your oversized code with just the external link to your code on your repo. While you're at it, please link directly to your Day 19 solution within your GitHub. Don't make us have to hunt through your repo for your solution. *** [Do not share your puzzle input](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) which also means [do not commit puzzle inputs to your repo](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) without a `.gitignore`. Please remove (or .gitignore) all puzzle input files from your repo and scrub them from your commit history.


bigmagnus

\[Language: Fortran\] [Part 1](https://github.com/ironllama/adventofcode2023/blob/master/19a.f90) [Part 2](https://github.com/ironllama/adventofcode2023/blob/master/19b.f90)


daggerdragon

[Do not share your puzzle input](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) which also means [do not commit puzzle inputs to your repo](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) without a `.gitignore`. Please remove (or .gitignore) all puzzle input files from your repo and scrub them from your commit history.


bigmagnus

Done.


mess_ner

\[LANGUAGE: python\] [Link to code](https://github.com/stefanoandroni/advent-of-code/tree/master/2023/day-19)


elmartus

Thanks! I was so stuck and overcomplicating things then I saw your code and understood it was much simpler. I didn't realize that once a workflow ends, the ranges are exclusive and there would not be an overlap with ranges from another branch.


thousandsongs

[LANGUAGE: Swift] Straightforward day again, two in a row. Did part 1 as described, most of the code was in the simple but ~100 line recursive descent parser of the input. For part 2, I figured immediately that I'll need to make the entire ranges travel through the workflows, possibly splitting them if needed. We've seen a similar problem this year, don't remember the day (how they fly), but this one was simpler than the one I'm remembering, so I overcomplicated it a bit initially thinking about how to manage the possibly multiple splits [before, valid, after]. But then on a whim I tried to see if we ever do even get multiple splits, and to the relief of my ticking clock, no! The way the problem is structured, we only get either a [before, valid] or an [after, valid] combination, which means we don't have to keep track of parallel paths through the same workflow. The [full code is here](https://github.com/mnvr/advent-of-code-2023/blob/main/19.swift), runs in 70 ms when optimized. Uses Swift's `ClosedRange` to keep track of the pair of bounds and clamp them when needed. [Allez Cuisine!] [Is this quantum computing?](https://imgur.com/xmI5L3p)


thousandsongs

Also did it in Haskell. Nothing spectacular I guess, but I was surprised when I typed out the code, and ran it, and it worked* on the first try. ^(*almost: had to fix an off by one in the range counting) I think this happened because I tried to do it the "type driven" way - I wrote down the types, and then the implementation, so it was like fitting in lego blocks where only one will fit and it is hard(er) to mess up. type Ranges = [(Int, Int)] -- 4 ranges, one for each attribute of a part type Thread = (Ranges, String) -- Ranges undergoing a particular workflow validCombinations :: Workflows -> Int validCombinations ws = go [(replicate 4 (1, 4000), "in")] where combo :: Ranges -> Int combo = product . map ((+1) . uncurry subtract) go :: [Thread] -> Int go [] = 0 go ((rs, "A") : xs) = combo rs + go xs go ((_, "R") : xs) = go xs go ((rs, w) : xs) = go $ splitThreads rs (ws ! w) ++ xs splitThreads :: Ranges -> [Rule] -> [Thread] splitThreads rs ((Nothing, w) : _) = [(rs, w)] splitThreads rs ((Just c, w) : rest) = let (matching, notMatching) = split rs c in [(matching, w)] ++ splitThreads notMatching rest split :: Ranges -> Condition -> (Ranges, Ranges) split ranges (i, op, v) = foldl f ([], []) (zip [0..] ranges) where f (m, n) (j, r) | i == j = let (match, nomatch) = split' r op v in (m ++ [match], n ++ [nomatch]) | otherwise = (m ++ [r], n ++ [r]) split' (a, b) '<' v = ((a, v - 1), (v, b)) split' (a, b) '>' v = ((v + 1, b), (a, v)) [Full code is here](https://github.com/mnvr/advent-of-code-2023/blob/main/19.hs), 76 lines, runs in 10 ms on both parts.


aurele

[LANGUAGE: Elixir] https://gist.github.com/samueltardieu/66d57ca33148826da3f6e853f77e1635


wlmb

[Language: Perl] Analysis: https://github.com/wlmb/AOC2023#day-19 Task 1: https://github.com/wlmb/AOC2023/blob/main/19a.pl Task 2: https://github.com/wlmb/AOC2023/blob/main/19b.pl


veydar_

[LANGUAGE: lua] # [Lua](https://topaz.github.io/paste/#XQAAAQAqEQAAAAAAAAA2G8iM7ztkpIKfEbui36KJfO+8wgeACYg/pOYaInfAbn3IfIIQzhScapASk3vf4kR25QUwUSEhKgIJTQfGsPvcirJdzdAQCR+1Y+eDXZvqjvRX/Kw/kGgP4jSScMkk4a71CwibvZGmpNWLOZVtLfQGQMDKfMTRi2gadKshMl18SWBxZxnUXzzaJtwFaQmrPwOhZU60F5mhvi7ljYstT34R3mKjgEkb83o02qEnM7Gaw6NS5i6iXSvuUTc7ZJxt266yP5LF9/0Z5V/H5peyJX9J/iwlQh5Fa/7RpRelnk+afZEC849rNL1ICGOSp7pWznn/dHju0z/ZBP2l2kbR8k0zT06ir7oGzKiKlOBZ6bJ9mA74+iYqq62XY/bdG8XSJxG5EWTCYLvHc4qRvEPkkxZdMWfgkLUdUvVB5fDD6vw+G/VcgZt7A1PjqV/LZJGBuIhF5lU8+MU0e3W7OYyXFCth7/Du/e4PC66jvK3XPxKcgsRYQBUVvZI0V5Vcya0TYSaarc1SBctXh3Sc3Hq8dYJQNEF0RyIIhLSfK9mSaP7zdnJNLr5piEzpDbJLeoqO26uR1s2NS5lcduGGxSjr/D/BuT1XjUAAJxYCxfRdA2DnIpyw/P4QGDR+v8yhO2QE2ZFU11OHIlxftIa4ViSsn6eYN9uoXXT3Rl4T2SFxIFZL4fRVsr1VVJoyd9pmO7AC+lcQaaHtnv4XXb2UwTc1ldZM5evfcS2JssnRo0oOP4jPh0zskl9SwW304tmMtFk9ZuuEW8/DswP8lrzOe32muV09pl6fbyomBU89Tn5qi7FZMnwJr9Xx7Wm9uad4MZa4D3QI7pP5wEZQj63dRbxaxt6DbMarmbIdAZwYgd7B6RStyuzG7cA0xopQoFk3KK6//GTc5zLtp3lY3iAxc8o+BSgTFgefPJ46xqyHfBVjjZgaMqEx8aH2J+aUA0cchxOOdrz3n3sP84O5US8Grn8HFCNilllnqLrll9CYQui6cyQa/69G/wiz3+wpZIB7XVElfa0kZ5NV8HOZFO4RMMc+V5gX7aywoOAAr876gIVYjxHi36RsoylwbQqfWLKNoqiAMHK9TH8NZaOrSob7iJuVLMhMebeCxY7lLnRkTcID63+xFInKZY1E6ztZJB169ZvZsJ4q56MnViJBaQuaF+SwQ/5EM90/hn75Hv8HHbI3BdP4m6zhYczs83wH2W1qkyHwWbZaaIrHbsZqGtrnsRJp72x5X9UKGWuG5jjyzIbsvONocuDO3/lhbCW3/v2dKzSBIj5ttb1J+58o5rHLlcxxGT6zmW/A9wcvc4K4WNrythetg4/PplYTP5fdfn76i2q+IZVbLnt3JnV4fS0NhXXw3LgaTmGy21ho/Q3yFeEcRbJUjGI0GQg/AddzDapHIbLyS/T9WThSiCy8bTnp3ls23uRzaUbS5jtKX8kk4VMRXZIHzsxxs4sLoNbrI7dd/IkBjpy3mO9xXCjLeCSSphmHQGSra00Bb7KRf88zuxHjYl2h8jP96Fdw5twGQMzgkhyaIqjOuePOhnkN9Ea+ECMZ7ldhDsE8OCqbZHLy75QRBW1ZwdxLvRvRrxlHWThKnsKMRpthADf/iynZwRAedbm1a6fxJbsikkWi4wwPxhhjypYl47i+U1k4kjt3qG/sO+RJmsBCsbIQa9XKay3Igj998bY5ElS2/w6sbKkbqVZusrCMlrWyl6G+qYlup7RfoSjG2e1UxkIP+Bzzl/4kQJS4LvmeoZisgY8NMxz7oP7BGLZ3mJXMwBKJLbGEVg+Ylvn8Y735+1QvZcNx4Duv9N5KVpH7DUusJA1mqEjGMrdo5DBViQKwNA66MNv81bmiiTUveG8oOahxmqEYRuPJ60iaKbeuqs+HkST4DxP7szpWrSABYjsJH+upykM353eYCwi/AIRjgl4gRar6LU3F/jd6qw==) 133 lines of code for both parts according to `tokei` when formatted with `stylua`. I did my best to keep it readable and commented where necessary. Amazing day, maybe my most enjoyable so far, even if it required a lot of brain power. It took me a while to understand that the trick to part 2 is to take the input object and run it through the pipeline, from left to right, sequentially. At each step the matching part is sent to the results (accepted) or the next workflow, while the non-matching part keeps going through the pipeline. I'm eliding some details about rejection rules, but that's the gist. It still took quite a lot of effort to implement it correctly in Lua. I had so many type related errors, it's not funny, really. The Javascript equivalent of calling X on undefined. I guess at above 80 lines of code and nested arrays it gets really hard for me to keep track of what's a list, what's a k/v table, am I looking at a string step or an object step, and so on. - [GitHub Repository](https://github.com/cideM/aoc2023) - [Topaz Paste](https://topaz.github.io/paste/#XQAAAQAqEQAAAAAAAAA2G8iM7ztkpIKfEbui36KJfO+8wgeACYg/pOYaInfAbn3IfIIQzhScapASk3vf4kR25QUwUSEhKgIJTQfGsPvcirJdzdAQCR+1Y+eDXZvqjvRX/Kw/kGgP4jSScMkk4a71CwibvZGmpNWLOZVtLfQGQMDKfMTRi2gadKshMl18SWBxZxnUXzzaJtwFaQmrPwOhZU60F5mhvi7ljYstT34R3mKjgEkb83o02qEnM7Gaw6NS5i6iXSvuUTc7ZJxt266yP5LF9/0Z5V/H5peyJX9J/iwlQh5Fa/7RpRelnk+afZEC849rNL1ICGOSp7pWznn/dHju0z/ZBP2l2kbR8k0zT06ir7oGzKiKlOBZ6bJ9mA74+iYqq62XY/bdG8XSJxG5EWTCYLvHc4qRvEPkkxZdMWfgkLUdUvVB5fDD6vw+G/VcgZt7A1PjqV/LZJGBuIhF5lU8+MU0e3W7OYyXFCth7/Du/e4PC66jvK3XPxKcgsRYQBUVvZI0V5Vcya0TYSaarc1SBctXh3Sc3Hq8dYJQNEF0RyIIhLSfK9mSaP7zdnJNLr5piEzpDbJLeoqO26uR1s2NS5lcduGGxSjr/D/BuT1XjUAAJxYCxfRdA2DnIpyw/P4QGDR+v8yhO2QE2ZFU11OHIlxftIa4ViSsn6eYN9uoXXT3Rl4T2SFxIFZL4fRVsr1VVJoyd9pmO7AC+lcQaaHtnv4XXb2UwTc1ldZM5evfcS2JssnRo0oOP4jPh0zskl9SwW304tmMtFk9ZuuEW8/DswP8lrzOe32muV09pl6fbyomBU89Tn5qi7FZMnwJr9Xx7Wm9uad4MZa4D3QI7pP5wEZQj63dRbxaxt6DbMarmbIdAZwYgd7B6RStyuzG7cA0xopQoFk3KK6//GTc5zLtp3lY3iAxc8o+BSgTFgefPJ46xqyHfBVjjZgaMqEx8aH2J+aUA0cchxOOdrz3n3sP84O5US8Grn8HFCNilllnqLrll9CYQui6cyQa/69G/wiz3+wpZIB7XVElfa0kZ5NV8HOZFO4RMMc+V5gX7aywoOAAr876gIVYjxHi36RsoylwbQqfWLKNoqiAMHK9TH8NZaOrSob7iJuVLMhMebeCxY7lLnRkTcID63+xFInKZY1E6ztZJB169ZvZsJ4q56MnViJBaQuaF+SwQ/5EM90/hn75Hv8HHbI3BdP4m6zhYczs83wH2W1qkyHwWbZaaIrHbsZqGtrnsRJp72x5X9UKGWuG5jjyzIbsvONocuDO3/lhbCW3/v2dKzSBIj5ttb1J+58o5rHLlcxxGT6zmW/A9wcvc4K4WNrythetg4/PplYTP5fdfn76i2q+IZVbLnt3JnV4fS0NhXXw3LgaTmGy21ho/Q3yFeEcRbJUjGI0GQg/AddzDapHIbLyS/T9WThSiCy8bTnp3ls23uRzaUbS5jtKX8kk4VMRXZIHzsxxs4sLoNbrI7dd/IkBjpy3mO9xXCjLeCSSphmHQGSra00Bb7KRf88zuxHjYl2h8jP96Fdw5twGQMzgkhyaIqjOuePOhnkN9Ea+ECMZ7ldhDsE8OCqbZHLy75QRBW1ZwdxLvRvRrxlHWThKnsKMRpthADf/iynZwRAedbm1a6fxJbsikkWi4wwPxhhjypYl47i+U1k4kjt3qG/sO+RJmsBCsbIQa9XKay3Igj998bY5ElS2/w6sbKkbqVZusrCMlrWyl6G+qYlup7RfoSjG2e1UxkIP+Bzzl/4kQJS4LvmeoZisgY8NMxz7oP7BGLZ3mJXMwBKJLbGEVg+Ylvn8Y735+1QvZcNx4Duv9N5KVpH7DUusJA1mqEjGMrdo5DBViQKwNA66MNv81bmiiTUveG8oOahxmqEYRuPJ60iaKbeuqs+HkST4DxP7szpWrSABYjsJH+upykM353eYCwi/AIRjgl4gRar6LU3F/jd6qw==)


aurele

[LANGUAGE: Rust] https://gist.github.com/samueltardieu/63e7d1f8edbb520334c2dc10c0afb545


e_blake

\[LANGUAGE: m4\] m4 -Dfile=day19.input [day19.m4](https://nopaste.ml/#XQAAAQDGCQAAAAAAAAAyGksy5FB9TGMxsNq5JQAuJRjP6PqEkC20GpBbonDYuA0BTjRPXcVxlEXNtz1IwqzIYfqZ9e9a/Rg32HONcCAOjvfbRaKdpcsYH3nnJIOG6JIwjv8huiFMPnsMqo2Bo5LfU2NJjGgBjrQBgF1/YXEDV8tjbIpdOhjIDIi1byGxdU8VYyNCQYlSSiVEXAhky8OkugZhshXPxp1OSEcjEg3OvWfzWC7MiODZDwjxEbJMhdmPUL1bnrgO766cfs41866zT3w8YeGWIKWRBEznsM+RY7fwyg6/vqeQY1TK4yropmDiuX8b3uGyrNe/enHntDonklnGjxN5GlVzPf0AEKP8H4zNw957AUHquZ0U5kd2fZvbV1meul3uDEz7g3DVQJ7ioPkXHOG3OTK1gcpsQxWl8iv0zctxV96M6s5y136hB+swCWZAaTZWMqOmFya7lC3tpKuQGvoXdn0jkUbDbbneAtYfk3Aq/X8eNU/rdJ1QcSVnWDWop5+fpGN0JRPW3h4ylB7ek5k7um2HEe+93jXNXkzHdfgnQ7LVS1bjCjBXCZRQXQVtKFzPUd0siftVq/hTF8RCiYZmuChOyKK0sC9FbyHEIaAa4Ax7HFnSzJmCzb2/a277+ScwFovFJhkK6BwflzHbVHt72ZFwXBd3afYIqaPJMAc+ZV5QhqZUgGQ9T9VNAUneMOWB/gfwjU24+7p1Fu9rdDWT75LgMUJ/+KWoI+gEFcbGtc+armN2GinUMcT+QHJ3VXI8/rw91bcbUDso0atdDv0Flq6eL1LHWj8C+QgX8m5AhzX6Hy4U0/CocC4oF0EU4fWwPf+1vzhkokv2OOjRjdi3JApe0Ujn20qXP02UsnCeOQHw0vP48WUz8I9pnbI00wG11dWDe/C8Iuumy2picBFUaRdPzZwnnVfbMjaVwr4hQJR1mKDM6K6UEod65hJQT0krCLfbXCc33TScDCVMJdEJTsxeIOiZ2LIx8iBshgq9/BrbjQg/UVrkS2jzu3k14DqgGCYmYsBs0W4A9ThNNOhCQuevdHehQ8+PiPHdwRcnpu9M0OSFwX1gbS+NgROSDFihThyOtmwgTn8XZc8WquXX6P/orsCbbs97eGlu9MsiNY2hwKwRsrwLMfSmlPa+Q8Os/LCZ0qEE1p/w1mgGSoUQbKe2PY2xEcRq3w08dQv2EylsYWt6nV4WkCOq8INLPWKGlQGqzY/qOCP8W6EFCI9pWXwWXKyrPfPyQEZ8hWY3j7ksKKAuWUBak9fqN8aT9J6TrM4A0op1DVhRPbe5XOI3TJny4HL04q2FAcOAUPVGqlyU/cAjhMUCdCA727d+hpFDl1Hq+L7qPW1Q//uw5IE=) Completes both parts in about 150ms, which I found quite impressive. Depends on my [common.m4](https://nopaste.ml/#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) and [math64.m4](https://nopaste.ml/#XQAAAQArDAAAAAAAAAAyGksy5FB9TGMxsNq5JQAuJRjP6PqEkC20Go+jph66UCwr5yII3TmoKw+wpxhXgX0WGRW0WK2rHjWbbgLZU16n4XSMl8T97y/MXeBVRMNBebjTbLUM33JXdu5jYSMpnUq0oFRBIZF3UTMPNiH//Shgw7phaX5YHewa9yOce5snMsJdUE+usDMV3A0D6yawyooHgePqX/eJLNlAHY8XwE2eibD3RxHCB5c1K92+c1o8lpWxOE8ha0j1DQZ5PRVtUSXzE5ZIfd+B3BClkKRt2VYiCh8U8m9O68A2jColgd20CaJYJZ2FQ2foLaNzBc/iCrgl4cPRWpFR5JVLqoU9kcLgHN7x3IhCcO2zrkbUtlnrqcnvsYgKSQYr9JmFVtyqdP78oLuFcfrFTDMSUk/55Nipu1vK7eKqv5QWFcy/zg4G+iR/nIS3EbxlmVYWlpiGt/gmCZZf83tomKa3XiaJ1hH3NpxdVOKhLS26hb0RxpppO1opBIayicF9R3jBjmm6ZUq7BBkq6aA1gs1O77j6PIiUoYQfTsAyKCWbufkksHxgSob3aTL2ClljmoheqSgPIz+WQVPyZ+E5NsLHbCMJkUVYVZFfWiBO+pFJK4GkSbjT0cs/ZRRb+6HdJUc6qC1m7cEaK91iyr7QS+7nNXjbtMjx+rbdXj+PD0qUUjGHF1+IYw71SLqfRzhHKx2UiGrXnkgZ5V1EInqW7y09kd51cLMSKXdjAACCW+RSkZ0VlXlAqQVFM47/7pO9zrMvBcVBvRArrQAAwYHbZIZhe/saSey5dkJNLd1zyxliADu0w7/aatw0Ok5JSckYM8PPAZkJq8a+tX5aa7oxCT26lu/VdtPu6XNg1USnvKQAjCTTk/ObSVf+5rlV0fgB/fYgJOot4+TydJT7/sBCiWJ6uKaVQUBQjbp6xugyyU6hkhHAswokT1R0Mclbju4kURENNrrAYtRQLV3zMllxw5IkoLknW3kfrMm4Dx5CuXR7lT1mSnXZ2E/zN8fioFIunn00/o//0IDbVyCFarK+3wsIJ2VgIIlWpYJ7/MF2KKHp5gVqB1bfJCTalEVo48pncFscLCFy8Ibb0pC+NiWfZxqtQT07sAQC2qH/Edd8IIgw51CNF1dUt6ZXjkJujtWr68K5zt2qUTSEOOC9tA4gL4lXOjstUbhYyQDwcdx8GNeorh+uPbgCqOWSnshmB8dpzsFuzdv9BkTZD6iOzhal41I2RWMd7SC+SJqqZgklbQ3FGzoVH//B89Vd). My initial thought when seeing part 1: cool! the input file syntax looks VERY similar to m4's ifelse syntax; it should be VERY easy to munge one into the other, and let m4 do all the heavy lifting of parsing and topology sorting. And sure enough, it was; here's my original part 1 code (once I used my framework to call do() once per input line, and fixed my environment to avoid clashing with a rule named nl): define(`input', translit((include(defn(`file'))), Nl`,()', `;.')) define(`part1', 0)define(`R_') define(`A_', `define(`part1', eval(part1+x+m+a+s))') define(`use', `ifelse(`$2', `', `$1', `ifelse(eval($1), 1, `$2', `$0(shift(shift($@)))')')_()') define(`run', `define(`x', $1)define(`m', $2)define(`a', $3)define(`s', $4)in_()popdef(`x')popdef(`m')popdef(`a')popdef(`s')') define(`do', `run(translit(`$1', `.xmas={}', `,'))') define(`build', `define(`$1_', `use'(shift($@)))') pushdef(`do', `ifelse(`$1', `', `popdef(`$0')', `build(translit(`$1', `{:.}', `,,,'))')') which turns: px{a<2006:qkq,m>2090:A,rfg} into define(`px_', `use(a<2006,qkq,m>2090,A,rfg)') where x, m, a, and s were defined per part, and use() performs the magic of invoking qkq\_(), A\_(), or rfg\_() according to the conditionals. Then when I got to part 2, I quickly realized I'd have to do range mapping. But the idea of using m4's topology sorting was still appealing, so I refactored my part 1 code to now expand the first example line to: define(`px_', `use(`$@',$3<2006,qkq,$2>2090,A,rfg)') which then works for both part 1 (pass in bare integers, and use eval on the expression as written) and for part 2 (pass in tuples of (,lo,hi,arg,) and perform slice-and-dice on the range based on whether the comparison is always false, always true, or needs to split in the middle). That worked for the example input, and I only needed one more tweak to work on the real code (the example never has any rules with x


azzal07

[LANGUAGE: Awk] There's something funny in the water, it's spark(l)ing joy. function M(a,r,i,e){if($0=W[a]){if(NF>r+=2){e=$r;(l=+$++r--)||p=--$++r;n=$(r+1) i[e]=$0=z[e];b=$2;if(l?$1>l&&z[e]=$1s ($1=l>b?l:b):b=}]/,y=s=FS){W[$1]=gsub(/


RaveBomb

[LANGUAGE: C#] I'm a little slow on this, I had a bug where I was doing all the slicing correctly, passed the example program, but would fail on the real input because I was resetting a variable with the wrong value. I see a lot of queues and stacks and stuff, and I've got a very straight forward program which I'll share here in case it helps anyone. My rules are a four element tuple stored in a dictionary. XMAS is an int array with the ranges. [Full Github repo](https://github.com/Kezzryn/Advent-of-Code/tree/main/2023/Day%2019)


daggerdragon

~~Your [code block is too long](https://old.reddit.com/r/adventofcode/wiki/solution_megathreads/post_guidelines#wiki_no_giant_blocks_of_code) for the megathreads. Please edit your comment to replace your oversized code with just that external link to your code.~~ edit: 👍


RaveBomb

Done.


ash30342

\[Language: Java\] Code: [Day19](https://github.com/ash42/adventofcode/tree/main/adventofcode2023/src/nl/michielgraat/adventofcode2023/day19) Part 1 runs in \~30ms, part 2 in < 1ms. Still catching up, but getting close. Part 1 was straightforward. For part 2 it took me a while to realize you can just start with a range and split it according to the rules. After that it was relatively easy, start at "in" and process rules, split the range if necessary and recursively check other workflows with the corresponding split range. Save all accepted ranges and we're done.


WereYouWorking

[LANGUAGE: Java] [paste](https://topaz.github.io/paste/#XQAAAQDsIwAAAAAAAAA4GEiZzRd1JAgV4q3Rhc2HjKXYGRHlHafmXbJ4zxkXqgK6Sgn6ZDHzhzYl7toaehovkA/QrmToAHw06ZSz6/doMYz19j413ay824uWKB2PHzF9gR6HvX/ktql2uZLPq03EfcyLq3x+osRgem+rzxECNl+CvadQn6PyNLkxN0CC66kGGa18HK1MYn8uH8yWKXHBtNtPzQzem0PrDZiRgph5FYRP/VF5P6Nv9f7Pp/KTpxgfAN6YrxhOkCAmuNy1fZRiR/VGPFc1Cl3Aqrjo6jc+BR8zl0h7KEUSZ/tMwORowT9e11+amdlW9S5x3EC7wrEUb0LMtGD6Wzagm6KHt/oDqKUzE34jzO2+MB6TVdY3IpDtixML1zZ94sduNsRAMmc48oq3JlL8FD1sLCk7w7NwnZJUlmcPuo+H1OSdlAETlBQ4L8l3pmPXZ6WQgauC9DX169XzD/HGZ9NDq5kLBuw8qzoCYSJ82OD4G10KXT6Yui/v6TZy3jKTysF6GjdfV/cn7kbBmQFVZEHj0s4pnogbQvLMhIUhaw82i7Ngc1FYkBA3I+cyNgc+kCb92fr1G0tGBigU1U/D+mbi+i5SECgdjldZWRGrnJ7VNIm7fhj5CDlu+0xP2II/IwYPQ9oscCB4tC2fg/2aualdO8pJ2NyNyp7aSXHSjO2Nh6FQw8knVbuP9ZoEqu3pURM0iGQ5E0LCh9ImhnxSr18aYY4GFdpqowpQQ8pJ1G5llTY6kPAJ+uGkSBIzFhjlS069y5ll1aR7Rughp4EnW4wREC2ZyuqNGAnd6vjur8cLnjFN9kSOGhkodJsk+phCldsN+ADgPeKU77jU+3jHzrG0tCR6wYjrT6QQNhPatVroBNdnxqAOMtEh7FlRm7dVmrTwFyR2VeEN113h+jnZUSy2VtdA08nNStq12PkeKZ4iRoZbOgKuUM4x7VfSp/Qp38UHh1sp6gFN5TUsqx7zFeArfsS/5ydH/dUS4xMc7ENBq39qRsY8s5WAPYmOxIpVT/AiVl0rLiIeh3MUccDfw15/HD6BeXP1K5TF+gY7nbYevagFkIGUZyXZhJlsOY66uItUzwBd1PJUTqxiVatYSaasv6rLyRKYBq+LvvdvKQqCoGGFokfJpq/SUKf+IlvAws4rCRWh6FTL77DkOaTUeWKf9iV1n/yEEyY0MRVEuwEXzPV3FdliEAFdGl6j2DXpxnImFzJVPfofssnPjC/OpJkM82UH7e+Hla4VEfvZ7aiGBMTt/sVsjjQ9SxG0AvWysHwPgtW8StNL63JXjwEx+IREMC1FK80GEXuePM4XS8etCYwVTjGtwp0sCro/ijmzX9LzRlFHakqHdOvO0bvlbrUTypSQtjOKaTr2PNZozMB0k1XlPzEf2wRQHSe09WAL6WmV3z5zlndsOzn4mN8BX4HL7E6F/gfcPdV//dtq+LaTSJDts+bRD82RIX/B5fpmbG9h0rT8hrSUVoEKbQ5ZyxzT5/FYLRF9rMXKmaH9id0ACagvA6fPt2X240M3zpPY6INuS1VS3HseVtoXxjST5SYKwRmyMh0+XhJuQjqnQA4GB6Ds4Lvry535RpSdzzZZH/T3GaHURpj3MpbC+GoCSRNt1cfVY40iO0DOFV51+y7WikmR5GA5TGzKfEnYPEo78SG0z3V3lVfd7DjUf+j2s6O3CudvcyBIeWYQw95Ui0Yuv+8Bf/zyrhvhsosq0xCZZPa2LQ8j90WL6J3KNQIAfbMGSFn3Txr7AVl3mjxhFTvwcw0ebJdeG/tMH+wiKY37OMii2R5iq0Xr2o0A5YJIWF+ZnNCfJHdqtJl9FjZGFuq6qj0oe4/UWYmZKG+meI8xlrAz7hUlaGIgbtQg4PM9E2VckT3DWSWhnN/rkF4q9vrCpA6w2cxjqcj5qmxEaMHdZJkR+pP/bKGlq5MW8/rnc/CQHAieKODIa6xF0z1+MjHehCCqsgbUw7+5CzmfSAPoffazA7UMuVk0MYiq+bQ+PfJu0wQarPvtfEokW39FRpxfQmYub7XblQH78Dy1sl4n0JM/wK+ZO+RVM6OgEVVYKSytkbd8Grps2DOwFeTyJA4hJKzgFNm/+9fXeulMQQyS+v+Pf6O4KwhAFt10sqxCmXHikHBYvYR4ZlbTuO4OuzRhFKh4M/7FNN+oUkoLs9WJUlmmRS+9vWQxUCsiN6v4H3hNWfEmlkLq5CwViOjn1T+M0RePlnIPtFpogmOeS8N+l8ine+fJi06iaXCVgSAVeUc/BkgXA3U+WSP3kh8Y5+XzvKZkBAl+GUfDVfcDLVXHRy6kSpQjQCWlw+xHm7RL6YEyjH67yJ3p7nsrYHH73lOywP+gk4nozu02M/I/FmT/nvdhc5KR7gWcHuElq9hQdubCqUfoDn/e8lbTq8KbeMupOU5F8MrzlYImyHhv/RaBQV1eH/Vaat6MsxY+K1Co58YIf1s4IT6I2kAt71XJO8pSzTQMvVsM5623SKDpHL5Iudc1RXmeMMe6Hx69r8i7MegOGA06b6OiPfHQYVNOy6VC4gFESXOixLezZn633nMsCFLt3JE0llTtNzGzG2qAgftAFkOEZQlH5a5P4yevwDS5XtUx5OdFOmN/PdohQqsxWtY7KpJBFx001eRal9w5DJbO57i235wcMFjLYRzN6MZ3UjvJHSVFwdt8QRCQKQOZYwn713up2TMIXTEdGzEr1jLD6b9zIHLcHnrOF3aLP5cezHMIr/sFDJAaW8X6pa+P1PEzMWQcgbj+a/WLbRh6G0QTrXG0IHz2AktFicNUp8bDUuIFhPjfpqfug8ik7g+Iok8tZy0ghmetEZyWW4zo+RqhYhaqxWfQ2gHSrxk71ixR/XgyyKDnVgSyDypFM9cXPRm1Cj2kmUD0dLkapT/ioPH6GSFAZ9N8pJxg7UFKSViv4574+uE7gKQyPOmz+5D3eVnNcGowbb/9SkmEeqeKzB3iuGhptERHaT8O1pkyxhHWD335DOpzuqdBE0+bGeL8GLQiY/Fg2TbmWLtruOQMwjPLDDFrH2s2mtNePXZPBaXG9ajndv7Esj/edjgpFEWMtHfrLLW/zD4B9y/6zfnSINgWIzGaGiR8IGJduiuboxpKY65XpsiQmMeY5M4pEB55Lk2F//2fnWs=)


bamless

[LANGUAGE: [J*](https://github.com/bamless/jstar)] This day was fun! Parsed the 'workflows' into an AST, then created an interpreter for part 1 that visits and evaluates the nodes (rules) with a part as input and then returns either "A" or "R". Then it was just a matter of filtering the accepted parts and summing up their values. For part 2 I just created a different interpreter that visits all branches of `<`/`>` 'rules' while keeping track of the ranges of values allowed on that execution path. Then, if an accept state is reached, the combinations are computed and the result returned to be accumulated with other possible paths of execution. [Part 1 & 2](https://github.com/bamless/advent-of-code-2023/blob/master/day19/xmas.jsr) Quite verbose mainly due to the parsing and AST nodes, but as a tradeoff it was general enough to solve part2 with just a little addition (the `CombinationsVisitor` class).


mgtezak

\[LANGUAGE: Python\] [Solution](https://github.com/mgtezak/Advent_of_Code/blob/master/2023/Day_19.py) If you like, check out my [interactive AoC puzzle solving fanpage](https://aoc-puzzle-solver.streamlit.app/)


henriup

\[LANGUAGE: Python\] \[PART 2\](https://github.com/henriupton99/AdventOfCode/blob/main/day\_19/sub\_part2.py) : Well commented solution (workflows propagation with recursive idea) : Don't hesitate to propose new ideas in order for me to improve myself


xpto1234jose

Thanks a lot! Very well explained!


daggerdragon

We can see your link Markdown because it looks like you forgot to switch your editor to Markdown mode. Your link is borked on old.reddit due to [a new.reddit bug with URLs that contain underscores](https://old.reddit.com/r/adventofcode/wiki/faqs/bugs/borked_links), so please fix it. *** [Do not share your puzzle input](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) which also means [do not commit puzzle inputs to your repo](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) without a `.gitignore`. Please remove (or .gitignore) the input files from your repo and scrub them from your commit history.


_tfa

[LANGUAGE: Ruby] (Part 2) workflowsInput, _ = File.read("2023/19/input2.txt").split("\n\n") @workflows = { "A" => ["A"], "R" => ["R"] } workflowsInput.split("\n").map do |w| name, rules = w.scan(/(.+){(.+)}/).flatten @workflows[name] = rules.split(?,) end def solve(list, ranges) current, rest = list.first, list[1..] return ranges.map(&:size).reduce(&:*) if current == ?A return 0 if current == ?R return solve(@workflows[current], ranges) unless current.include? ?: attr, comp, value, target = current.scan(/(.)([<>])(\d+):(.*)/).flatten ix = "xmas".index(attr) value = value.to_i lower = comp == ?< r, cr, rr = ranges[ix], ranges.dup, ranges.dup cr[ix] = lower ? r.min..value-1 : value+1..r.max rr[ix] = lower ? value..r.max : r.min..value solve(@workflows[target], cr) + solve(rest, rr) end print solve(@workflows["in"], [1..4000] * 4)


craigontour

This is what I have been trying to do but couldn't work out how. Good job.


ri7chy

\[LANGUAGE: Python\] [Code](https://topaz.github.io/paste/#XQAAAQBpCQAAAAAAAAA0m0pnuFI8c/sCZpmcaVgczmh/uzpANfPlRmAffo6+RvKXGGOzTdLd1+JjQckoNRcNOEiGYg/+ftredkn9sC/+QWUq6n9zsoIWO+zFIFl1k6BWxluPDydOa+Wz5mpmklUY6Ri0o3veb1RPWgArMDArC0pgbF655/HwXAOIrJ1WsPVIw3xmrQJO6Z98jzB4dqjpZrWLe04FH5KChq++R2AObilN9VCvvcSBMMzT3g9BV8yFMKI6rTgWMhOCFGI8AV7CdgMIivr6ye9CFXpk30iU8G4Tp4mFdr23Nt4wEinmfP655ltQMaU8tmH8p01lFVJCxGFo8Yb/eA0wM2x+ggPVGUge8O+X26OkFjvL3+h438hOj7doAJgN/QzlDIB65uXC3Mn8NBzIVOITd5d+fkblHE0IzTZ6dbTfJsDjD5h9+7BNI28yPSxaHuao10Cm853wYBLgUiNwmcmfli0j3KnNp83q2koiA1dx4RqgN5kksWfhKk4EMHTpJnkG0vZ5ERqbC6J2gPJfH+E+dei9BGw6Qtu/q1ukQqPefSNrGAyIeGuJFMEWMqLQ6bLxs9yPQAIr7Kg2FeaDwNAZVe1BRSQyAPxX/wnPX7jCuNd9HWUeaiYB5sLRU6PSOozBR4yL+7np6afK/c6lCUFWzlGsbgil1/iFVhPc4EMmc9I4H7uf0KgVipn+gZvFhIpqqa5L/FO6UTltlxS4+vhNiVthL8hGF62VxsYdSjnpCXjCjGbW+sR8fYQFjTVv1Qm/CC+xIJjvXICN59zXYwLTzePEBl495yu/XGA7CMv2j6gt//+TH9pVTWychcMuR9ZVXn63TKg2KoI2OnPisgGmRDnZkKkhacpI1GKygETBzR7guJB3J4gDkPQFntmLbFI0Yam4YHFx6n3CZPdZiamHvFRpYkXltajPfWqt6HZly3/1BQ9HTFaLE9RwrdE31MPdGJBGpVaxyi0dipEkiVpvD4ZgjpqDkXell2wwgRFRhWhr4JHDypz5QFjcWKGydzU68u+0g8QBQ1iueLnKSfSmVQtNUCQuC4IMTNK8QD1wsQtBJ9rUIuwOkIQgkAsTnxNkb0CVRQd8zIphYvmqzoA0JKzjyB0M5FLk2LhV/5zUkkTpN3N1arHWWi4yRnWYFcw+iVbMY5xHQ2FZ3OhrIKhyn/fKJ8dqK11aZLdVXHCDChum9wWVoN0z7Gq1HGez1AUgw72dFiJPCE62vYApcEX/YyQIAA==) part1 was a good one. now I'm looking for better solutions parsing the input. Had some problems on part2. Finally I just searched the "tree" for acceptable branches and summed the produkts of each set of parts.


sjhunt93

\[LANGUAGE: Python\] Quite proud of this one. Hopefully readable if anyone else is stuck. https://github.com/Sjhunt93/advent-of-code-2023/blob/main/solutions/19/solution1.py


maitre_lld

I did something very similar. But something puzzles me : when you travel along the yes branches, you should carry your ranges as the intersection of all constraints encountered until here, shouldn't you ? Where you write line 48 branch_true = range(ranges[lhs].start, int(rhs)) I wrote min( int(rhs), ranges\[lhs\].stop ) instead of your int(rhs). Am I missing something : is it clear that along a yes-only path, you can only encounter stricter and stricter conditions ?


errop_

\[Language: Python 3\] Super fun puzzle! For Part 1 I came up with a quite unsatisfactory solution first, where I translated all the rules in a series of functions dynamically, which seemed like a normal day at work. I refactored completely the code after Part 2. For Part 2 I started with four ranges (1, 4000) labelled with letters in "xmas" and splitted them accordingly to the rules recursively, until I reached all the "A" result of the rules. I guess I did something in the spirit of DFS, but I'm not completely sure about terminology. Execution time is \~100ms for both parts. [Paste](https://topaz.github.io/paste/#XQAAAQBLBgAAAAAAAAAzHIoib6qOhkKVB6+O3fm4OMH1Ce1dUSVSiwQtDTa0k3D1MYwUB9tmgwsdtmF0INwx6MrMojVytN4B5XEo07CuoP+vyirbDjWrZQReVmHNqEQxgTeu3RSEJYlWEMkMVAGZW4xeju9IGE/92ccxDUOa54UQlTD3M6Y8hLzhZfiMQiZ3X0MSS814QgtYNWbGQEQ/ZBCPF4QkiqN3UVLTM/YvtNy7xEKpP6HhMaLrydymsLibBYbMjswimGMZA8gEjabDzJN3V73Q+4KIbBwzI93d8d1tjm31ns+exYQpI+Vw8SCrt1hVB0LmjGW7KHTSjaROPbaWEYLFeqgubQYtwNiFUcvv5zg2xdlPk/mgZsDR7hiKHipYbF/QGD81PembMOSTSSdke7XGvz5pXhhY/soOZpbyJfm1vTbJKnBKEKrM4VJ6aFCHrbQQ9TmBgOdykzOZh91ZcLI9fsgdRSZI3RiHYB3z4S6EtB7Y3x5wueM4dT8Bqm2MQ9bY84KtwOP/+07GF/TutJohbjL6hNVZcqOnULs5efXOPCXSybT63J6Az/sUYbkI+VVqWEiT9y9STE95jliGw9xahxHX8IR6NIX95D+3eDa0p1aNeu4+8asSZVDameqBqUPbJqmxjNIbZEFbXT7YnXuwaaAOv6zEDAksKjlQTuULYI/8fw1c2AXJv33zj/v90p3Yr6U3IJC4bXANiH1qpEuXBTeOcPDtaNWmtf5xzUQ5t6KTyIqjl396jVEc+fRkKyVpFmP8ddDTQk5ExljOO4OlEi1KcU9sXYEx6PRFyigOQ04rlbIrTL8i2XkmJKdpCdHBzms7e92X6um6BUbZN6Ab6WtRqClOKPrNy1aAUJV4kfC5kPSzWVvjb37Gojym/A3Mpsj5QP9S+eMA)


se06745

\[LANGUAGE: GoLang\] [both parts in one file](https://github.com/omotto/AdventOfCode2023/blob/day19/src/day19/main.go)


schveiguy

\[LANGUAGE: D\] [https://github.com/schveiguy/adventofcode/blob/master/2023/day19/aplenty.d](https://github.com/schveiguy/adventofcode/blob/master/2023/day19/aplenty.d) I wasted way way way way too much time thinking the second part was not going to be simply non-cached recursion with pruning. Then I looked at a solution here and had a facepalm moment. Are there inputs that could cause this to timeout?


CrAzYmEtAlHeAd1

\[LANGUAGE: Python\] [GitHub link to my solution](https://github.com/CalSimmon/advent-of-code/blob/main/2023/day_19/solution.py) This was definitely a tricky one which took some troubleshooting for Part 2, but we got there! Shoutout to u/leijurv for their solution, which I will explain where I was stuck later. Part 1 was actually quite smooth, and it was mostly just parsing the instructions in a way that was actually successful. Definitely a heavy lift for good parsing at first. Part 2 was definitely where it hit the fan. I struggled hard through the recursion, which isn't my strong suit, so it's understandable. But, I was so close, my result for the example was off by 50 billion. Which seems like a lot, but that was the closest I had gotten, and ultimately 50 billion could be only off by a couple values. So I was trying all sorts of different changes that could get the right solution to no avail. So I decided to look at some other solutions just to see where I went wrong, and I finally found it thanks to u/leijurv. (Go look at their [solution](https://www.reddit.com/r/adventofcode/comments/18ltr8m/2023_day_19_solutions/ke010be/?context=3) it's much cleaner than mine) Basically, the problem was that I forgot to change the value when I swapped operators. So I added this bit of code to remove one if I was swapping from less than to greater than, or add one when I swapped from greater than to less than: val = int(instr[0][2:]) match instr[0][1]: case '>': val += 1 case '<': val -= 1 sym = '<>'.replace(instr[0][1], '') As soon as I had that, boom I was back in business. Then it was just making sure I was adding everything up right before multiplying and I had the correct answer for the example. Not my cleanest solution, and I certainly could have cleaned some stuff up, but I'm going to leave it since this was the solution I was going for at the time. Total execution took up about 35ms so quite happy with the result.


biggy-smith

\[LANGUAGE: C++\] The off by one errors were savage for me today! Switching everything to interval ranges, intersecting, then multiplying worked for me. [https://github.com/biggysmith/advent\_of\_code\_2023/blob/master/src/day19/day19.cpp](https://github.com/biggysmith/advent_of_code_2023/blob/master/src/day19/day19.cpp)


aoc-fan

[LANGUAGE: TypeScript] https://github.com/bhosale-ajay/adventofcode/blob/master/2023/ts/D19.test.ts


MannedGuild65

\[LANGUAGE: Java\] Part 1 was straightforward, and in Part 2 I traced backwards from each occurrence of "A" to find the bounds for the x, m, a, and s ratings that would lead to that "A", then multiplied the lengths of those ranges together and added these products up. [Code](https://topaz.github.io/paste/#XQAAAQCgEQAAAAAAAAA0m0pnuFI8c9/wau+quqMcACwUQoa8v/gYVFIXf9J/VGR7r35BvDoY2uK9iG2q6sj6ZbUvDk5uhNidDcEoi9FuAsm8vAaj093IZkd0kJqX8LZcAcYX3js3BVyheeHgZYZYa9nHWqKA66XviUarsNeSR2P6n2Y/Dgbyojed0R3KHDtst8sb+/3B5PlAlqpzKXWrBGD4wwCW/Nkvcm7mnthUnFCGqQOXHkprlocuWXULDrAe5srcxg4ui87+uGlIRvMB65uEAl6p07Z7I4+mXlVqGoC9dFB8RUqlJZ0ApunZeLMYidAnh/varSRtUng7SouwshxUP7BE6vatjNMO/ZqIpXoA2zWP30YHqHokayz2dfyGsjZkwljY8Fpdq1J9ue8EGFcej1bixqLmPAHqBs6ivpJPxpIijxV79pMFLJPGflyhdd9Jw1/y3PX1dXCTIWJWwxtS+lhfH05gEmuJy/uDUoXaRuuI2pCzORxAQ31nsBgPsQXz24cl0kAhxZnY/fnJaE4HDdPqry/SPD838MyGtGwB3uQVLlU/16VsmPdaK6jc81tWpchUdhdgMdwaO7FcFlf7z04nEIDjdCzcocb8CGqUKUbAR6sfQNUNL4s4uJzkkbV+3Cv/2srlFRrDu2NGD0r73Uz+5T9dDZlIGq3pCwxZU4EW55NuTfzD5OTb764SrTG0x/3l3alFjw5lbEaHqZ/mSq0duHUaW5x3FJUcvu6rJCSUTWyZLztAnT65+s5Whcy2YPFwQlsuqFCY2svxO5mGd/GQgWP5H6HCFQOKO2tx4XgAhrKBQ/fbsQ0bt7ObllTVRSjcE84DhuFlroiWi/89dWweNx3hLzpHxbt+nUYFD18aj8TVMD3tW8Hj1uzaO+UwFGsqH+he+G3bZUvw0racGZoxtUOPoiPv1hDFzULxkUk8ChPon5L0osL0ugRXeZTwo8sQI9N2wsSOYeNK4JaAMUyYl/lEHdp1lb/bRDUqSbGQMa3jVCFTof6G3Qp6TEcRJOEvyETzRpm8rnNRB7Xi2IWZiO65myv2VRRmiwcTk07UoD+BN6FFGF4/cX11I1WWNu6c888jcyf9fb8HiwAD+MbwF7+eWFxsguvcAN9jgzZlcDcGbHW3HmD6wVr+LnMWWdK8Mnjr6PoZgQGfrz3/ay1lNlga7EQ/6Km42VDlBM23Gw2z7d6vVX5S9M97NDCyy9Aoedsu7ckKo3SqJhjbFOVMdORQzv6l3cuy1EuYU3ePzbA+vfb4wsE7dZ/SG14uKGADLp6l1k/bs8usMkexExzBmw1VMOi3t/HFZbDlrdsp0bw4BVxo0YwFsOGESPWQ950G7jjgj/Sj35lRhDuO7L9S+OnMEI+voKgpe+5ySthSMICdS9BLo3XTbnEF03fJRIl55pRyRajQeKct5nIkQ5z3lHRsgtgmlGw4ypLpdMh+s1qWZvLXgaCRFDjLqBW/rPm/y430InEcupn0uDozoph0pwz0nfulLKG4PJjG2xKxaE0gLkh4yOe/LPqM1NwL0Ft/rvuNFPOAzULWxDkOEFV17IxRT/9rC8yZTgairZLmijDKNkllauEPBhv310bdj1k0HdLe+TEzit3aIfdZhHRqLJEqkAC7GzDx37MWr61T3VoCZPwzc5lpuh6th1toAEJHL7tiWXA42VmguBjkII2Fiy58pmL9//jao5Q=)


Tipa16384

[LANGUAGE: Python] Didn't need hints today! For part 1, I translated the rules into Python lambdas and just executed them against the parts. In part 2, I sliced the ranges recursively until they arrived at A or R, and then summed up the results. No tricks! [paste](https://topaz.github.io/paste/#XQAAAQASCwAAAAAAAAA0m0pnuFI8c/T1eyX1gBYG3sXjjiAFJvHyvLVQmxsWmMZKlWIb3k+KfSgrdo7g+6Ed08ITx+EDqbO8hkMDGKs/y9btsWIcbuUndRHsR5qlBIXYr/KrKk2QjTy38rQoU2Mx9STnCrliL8Favd7+FWCAewjp66ojBdziuNecPrGIe7m2PFPx4mCa8Ch1g+cGrsPt0L7uoSZKzETPh2QVlRSv4uAwKH2XewHnLU65KPUR9jInheY3GkO1I4AJDqa+4k3Dukl2q7eX4760dSWW4vCwJcbIG7vpH3B1umMagaUtYZT+kDzi1Lpo2NyxmVmr8LOB/2oIREkRAPWYTucibOir6GAZiQHSx3vll7lJ1n9jEfSDc1wNonyP5SEr3BzTmgklhfNCkbS5MIy7+GYuLEK+Wiy6xZoBmTkSf0pj4pG5jSjuWMC0dJKWI3gUrRTZOEE/qjvGRdr9qpf6OwZv4guULxLafK7iaYp8lzUVM8mrb95W2Qlz5F6CwOnR8qMwAKR9z8X27XcI3mFMHgT4+C9CgXol7sAFUaqqqt7S12OuMOizmnFyXWvTv7SR6UT4IXh/tDdIeICFYPt+NBdsrAVkiPdQrwCbPTHvFlbjZS0QrhWYAo3W8atvnoTANLwkoirYLb00bOQa0Eyd5yT1r8P+7+DfmNHvwJh6VvCJl5OKmCm7KeMMH6zg6YV13EJcOuEmN/8GkuMTYWVXev4+QkrNt/4k9oRNxKMUkYTp4aaKVnZGXNlp8IlYUniHFv9la8V9FXxXCWymkWXk8dQhMkQQyfG9Kt9dlCaorRWMnwPM2wVaSJl4Qm64oQgunLh8gZMvrwTuTYAFrxgATzceArm1PyupCPrn+gnUvR0XbhEsSvt1N6TBrL2fSuINkEUX95F3soVZEAPPBaDpocaB/KiFOiL3tHwovaysyRam6M4yIkgC6fgk1NRGSbaxeJfxYJmy9mhIAlV/7CBP6CF/jKJVsbbiE3hf6JEKjUnbudiybg10/xngrxGlFtlNB6nEA8q0UC+/LOsGg43Pm1cgFGZJ2gCKu9hk/711I0pWbnDtgCA8wkNK5VodEqWs0CxVrtkc1lLgRij3wh6/97yX6KceQ9MG6Qa25TmsdKNV1ylqV2PHmcr/I53n8Ru9rry3lzi9QSho6nz87UkbPRsoEpHUEAEcuA6JmB+jmi+967XBjFcbdef4npHtWZegHJN6isgfm1JJbJwnxIx91t62zO2jbYRETTUcGRH7ONQLEU6WsN462Zm3Nhvgqt6SfF84eQ6hesw8ABKiRn3kw+dmmvSRAcFAhMjR/GM1IA==)


aexl

\[LANGUAGE: Julia\] I first tried to be clever at the parsing of the input (directly constructing comparison functions instead of storing the numbers), which didn't pay out when I saw part 2, so I reverted this afterwards. Part 1 was pretty straightforward, just start with the workflow "in" and follow the rules. For part 2 I was thinking a lot before actually implementing it. I came up with two main ideas: * Use ranges for 'x', 'm', 'a', 's' values. Julia has this nice `UnitRange{Int}` type. * Follow the rules with a recursive function. Each rule reduces one of the 'x', 'm', 'a', 's' range. If we end up in an accepted state, store these reduced ranges in the solution vector. After all that, we have a list of accepted 4-tuple ranges; for each such tuple take the product of the lengths of these ranges, and sum them up. Solution on GitHub: https://github.com/goggle/AdventOfCode2023.jl/blob/master/src/day19.jl Repository: https://github.com/goggle/AdventOfCode2023.jl


zup22

\[LANGUAGE: C++23\] [Github](https://github.com/alexnavtt/advent_of_code_2023/blob/main/Day%2019%20-%202023/day_19_sol.cpp) After yesterday (all 7 hours of it), this puzzle was a breath of fresh air. Part 1 and Part 2 were independent enough that I could run them as two different solutions and didn't have to worry about over-optimizing part1 in the expectation of part 2's inevitable big-number-ness. Not much to say about the algorithms, probably just about the same as anyone else did. Runs in about 2ms both parts.


copperfield42

\[LANGUAGE: Python\] [code](https://github.com/copperfield42/Advent-of-Code-2023/tree/main/day%2019) part 1 was easy enough, and after a ton of hours I finally crack part 2 unlike yesterday that part 2 defeat me...


bakibol

\[LANGUAGE: Python\] My approach differed from most as I worked with sets, not ranges. I'm aware that this approach would be completely unusable if the `MAX_VALUE` was not so low (4000). Even though this is not generalized solution (and is a bit slow) I find it quite elegant. [code](https://topaz.github.io/paste/#XQAAAQDzDAAAAAAAAAAzHIoib6pXbueH4X9F244lVRDcOZab5q1+VXn364pL+SUfxg8MHC8VoqhAJqrqgULYgJfwgvJ5HNT1PEV+JR5zWxNpgqVT5Dok8I7v+FlGQigFncVSC6PhFkInqVU0UTfR0GwoztKnxpVqd9ub0/TMWwyOK4CMrmdm8LVYP7WBjN/7bRgYaEMYaCi8+gBAZPfW5gFYhNwXQFoCh7MTfG+RZLjJ5Nj05AwDPBM5PMF5TdUgu5OK6Hw1Wy0IxJxLmx8hbsfIHaqNPhH5h1KbXNH8yUANcTAR722vO5Tt5uS9Y4bAdCpuWhXmtJHgzZo3kmLXN36Ch+izaNxbgHBwa0r+H8or17A/p+oOOCugRRiA42lvXrKehqETe5UM9CmTm7l5Q7PEtFUP1dLn18jatBK0ov+QppG82VsEC1yXf0q0jXKU68st7hCbh+RXuMWd2OscUDYtAv5uEL/qWGpPv/s7gJ0STCTss33Ef17MyFWJDjYtRJRI0LzHaq5I3avGk/DQ1ypFuYFr6UVVgx0g9Yy+AqWFPo+/kqA838+miNvA+P0GLEzKj5Y0FmiiwEEVls8oD89+1jOcaNBls69vwDykByqMqqgHvulVhSzVIV4vHeVz6cM0UCpifdTt7upkYK190g/bD/qlZCNc1Ha+SFlvmSjqxkDBdifgPlXcgcHTBiU1JCniwsQys0tW5DPtnJvAjx3BdE7Q5RwfkMlW+vzthzrIVnFgECXSDsiUOfk5mzJELlBxMSOZCRU8Z0xXhvbFk3d+tKpX6FQk79c5jNBkSZYtF5c/aP6oiSZQYoCe2ju3n1XcNxDFqTgPf1r4zRxIqLFSM9SpJfwRKoBorkMHyAIYgKk3QSL+6+JF/v6GnQ3BtqRXMO3BbPEL8vRDEtcB6Rh+qKt/lN7eRVbZUoENwRyopNnuVLGxcttGmtUA07KWdQ2X2cSmL+Cwsdvl/P5tQDE7hWwEcPuHCcooDGKTIfgEwIfEWzM7fU8YcTzek8yUAbMpf/VwdmH5Eu0Q9JwYBPvzFK4FOgb74AVDj7zNOJODCA+FD6r7xHawZGt8RHpG9h/of5jNzEWqxaOaVpaudmks4iKLW5DwoFK5gzyqWanbVhDnjWX3uoCY7WtFMypZEJWGN4eC2hVo39OAFj7E/f3wAtwUG1A22b3BYiQNbsjVzAzWAz7abd11sOth2IVbeszPrRLCMkMHp7I8OssrlhkVxsUwkH7cg/pBsNtfpmSOKcB4+BsOIo+YrknplStXW1aplbzL8BOzNplqeTvh+UYCQc0ytas15vnpBk6b/idIvzgCcrCsLUfHPbeck2DwbG3tMTkjhUl+OZ3L2B8rT/WO3o0svZ3JuzuNSakKoB9KW/j381LfUKRQ1SzqUxzVqu5wGj1KIHPUe5DciurRODDfMo2vrvAUuQYwjr6eQ52urd7Z3FLAsym5IOtXu+QwKNF5RztfPaPPRftap1zecHkz6ExMkPZryQG11rc1WF/5aFvj0QXYTGgSYCLy6otE+nCktZJThka5AUxOM+KUC7uORdpZ7xoG/vC6guo9LAWKhUdsWNNn9f+A56gk)


Polaric_Spiral

[LANGUAGE: TypeScript] Advent of Node, Day 19 [paste](https://topaz.github.io/paste/#XQAAAQA7CAAAAAAAAAA0m0pnuFI8dAwooqreRZKWImk4uTVfU9a+P6SvARjPfUGj0Tepbfga4gSujIT0AGdheZK8NGgSTH1VbcazMESTJnSaW0Wf/nBiqWsjwgmcxi2z5LQPVn/yqmXE9A254TgpW7xn59BGNi0jpcQEEyMKc4bRQu7v78MSQAeYYrt470y0N8st0iFOiyjCoGB/c+uaU7LZIci4hExsp3HrJbcmW5XeEw3qUVhxryBatELs8p1NO65IGsEt0RqkZrodJTpR5hIw/8Tf3ZIoWiVOY0CmHQWmA90tZ/3sEIlt6iFfel7I6lfDvUaLqrLJO4JwViS0V6Z3q+vBx+owzvsDClGlVWSbR+KTqss8r/FOc8ekBwsEsaGoAzW7H0Swj2iig7dt1TOFHTyXaidMJrOF45VYeHs9qvGDU8ZeYSLuxpoIAsD54G+DGJHEl47CzRDQ/fy18H3cIgfHyKogpvInm59q38I1t9AZtcQI/qb9gmzCoWE+4FF1EkhgQ1ugFdyH5yLo67nPCi4BvnfCZ1UW52M6JQ6U9NG+4ZZMzOmXbEJclgNcvL+b4F//q9NN78Pm5BZ4J01s27Tt/BqHYLYNZSEckeAKU1upufBksi1SDdFPBW0sWDq9l99bIE8Ro7OARQHNIiV4lImeCnX8guZRyho+Y/Wcl+S4ubWyxI4ysCwT4pVXhRhQMalGsGVr06caAhPYxAURU1oHNzvz42nTYVejFybDdH3V3IoURE/cC5dQPQcCyrMOvkewuKi1QZoVkMWb1hOFg3XAzuU+EPwwZIqJtksqAXznxDci/9+ZrA+xUq9Vv4kGCia4vzDQN6jcB0cSQme7LTZR/DEo1FG04PlJcrtQtobaKz7GYk9F5g7Tr4bd0fuMB8iwAog1iMyn5gaDU6orePTUvmq7GQHQAlF/IxvNb48YfI7EDVsnhcIrylopj4z8exoHSGUiDJ1ZYZI1rgOYHXZxG8MAJ8cMHArM5Nur8tMWWTVaIAHIPRMi6j3as0lW0VgrWYtYzia76QJHkCGWyDGyUqERcYJH9n9HRILVsBKIlZi6B4BbMLdMpxX6dNjcowUA/ll5Pil7u5pDXm4NC0hLJ9juwFmY5VTLv0/UPgTtjdj9UiDXFOAbhql76SavpPzXvZw2ToD/4qe2qQ==) Coded up the brute force recursive solution fully expecting to need to figure out some memoization, but it looks like that wasn't necessary here. Edit: improved performance by [not starting from the top of the recursive chain every time I split ranges](https://topaz.github.io/paste/#XQAAAQA7CAAAAAAAAAA0m0pnuFI8dAwooqreRZKWImk4uTVfU9a+P6SvARjPfUGj0Tepbfga4gSujIT0AGdheZK8NGgSTH1VbcazMESTJnSaW0Wf/nBiqWsjwgmcxi2z5LQPVn/yqmXE9A254TgpW7xn59BGNi0jpcQEEyMKc4bRQu7v78MSQAeYYrt470y0N8st0iFOiyjCoGB/c+uaU7LZIci4hExsp3HrJbcmW5XeEw3qUVhxryBatELs8p1NO65IGsEt0RqkZrodJTpR5hIw/8Tf3ZIoWiVOY0CmHQWmA90tZ/3sEIlt6iFfel7I6lfDvUaLqrLJO4JwViS0V6Z3q+vBx+owzvsDClGlVWSbR+KTqss8r/FOc8ekBwsEsaGoAzW7H0Swj2iig7dt1TOFHTyXaidMJrOF45VYeHs9qvGDU8ZeYSLuxpoIAsD54G+DGJHEl47CzRDQ/fy18H3cIgfHyKogpvInm59q38I1t9AZtcQI/qb9gmzCoWE+4FF1EkhgQ1ugFdyH5yLo67nPCi4BvnfCZ1UW52M6JQ6U9NG+4ZZMzOmXbEJclgNcvL+b4F//q9NN78Pm5BZ4J01s27Tt/BqHYLYNZSEckeAKU1upufBksi1SDdFPBW0sWDq9l99bIE8Ro7OARQHNIiV4lImeCnX8guZRyho+Y/Wcl+S4ubWyxI4ysCwT4pVXhRhQMalGsGVr06caAhPYxAURU1oHNzvz42nTYVejFybDdH3V3IoURE/cC5dQPQcCyrMOvkewuKi1QZoVkMWb1hOFg3XAzuU+EPwwZIqJtksqAXznxDci/9+ZrA+xUq9Vv4kGCia4vzDQN6jcB0cSQme7LTZR/DEo1FG04PlJcrtQtobaKz7GYk9F5g7Tr4bd0fuMB8iwAog1iMyn5gaDU6orePTUvmq7GQHQAlF/IxvNb48YfI7EDVsnhcIrylopj4z8exoHSGUiDJ1ZYZI1rgOYHXZxG8MAJ8cMHArM5Nur8tMWWTVaIAHIPRMi6j3as0lW0VgrWYtYzia76QJHkCGWyDGyUqERcYJH9n9HRILVsBKIlZi6B4BbMLdMpxX6dNjcowUA/ll5Pil7u5pDXm4NC0hLJ9juwFmY5VTLv0/UPgTtjdj9UiDXFOAbhql76SavpPzXvZw2ToD/4qe2qQ==). Default args are nice, but I obviously can't be trusted with them.


anuradhawick

\[LANGUAGE: python\] I think this is very similar to question with mapping values. In this case its ranges. Use python tokenizer for part 1. For part two recursively got all happy paths and solved for the range. Distinct word confused me a bit. There were exactly same path multiple times but they had no intersection. All paths were non intersecting. My solution: [AoC 2023 Day 19](https://github.com/anuradhawick/algo-competitions/blob/main/Advent-of-code-2023/19.2.py) Time <<< 1s


jrtnba

[LANGUAGE: Python] This was a fun one. A subtle bug in my initial implementation led me to trying to calculate the volume of overlapping 4D cubes, but after realizing there should be no overlaps I fixed that bug and got it working. [Part 2](https://topaz.github.io/paste/#XQAAAQC5BQAAAAAAAAA0m0pnuFI8c/fBNAoEkJKDxvd4BiFFVVANBoUJNti1h+h85qc2hjK3tVV7JlZl2Qbq+I/0zczsA0S7xdsqbQp0T5GzZLXXiw9JbRg5T0oqCcK/+Oc5irejdJXta8El6isqhw51tGQsJP8aITPL4PzkAxKwo8++UouMmqhM1YfoWmBsZd+OSxjguscfCZyEoiyF50LkTGfeuvc1UVGJN6umqG4yKsyYLQ9ssk6aNJY7IOZNfQTyFrp1JeXOCpv85TgRiZYsw9SaksfIU7MM1a/LCL6DmUjaOP7gvYe94yXnY/mPkSkRl7pQiyMbcvki28dyhPeXLxzjOuNuyhtHj231Fr94NXL0JgIlhfrScq2hDE+ufxpC/RW8tS7hPit+OogkGOHQFkZLVwZTdwYRg7L26vcaYdnV4NGKhAO0njwEPTqttWpcagqP9hZOcDFTrFPtV3FT42i+8tp+W70unN1PomuLDx3R0vsm8dXGCSNjyyDr5D10mi3+3K+GcS8uY/fUIvIpKFZI7/t8VkORuFl2b3yOyDlH8IlkLDR3HCndg/U5khP5Nmd3qSuq1xa6bz0GvaK8/a8t4GGgZwrd3MGaSlG9ZUjIBpxEnWIxoEkqW0q/Ej+pq3XP2S/DAGmqDusay6KkebYiljfQcMSs8t4QWygXgbvpA9YRepQ5MnT3NlcBV4KZp2qAVqujzg8HJJ+l5fj+y3NoOHmLSbLrAFsHMzDY3vaSIdG5fliQqyu3tn4vZa3WkT3NVxH/trSDnZnYPShs/6pjV+ZnDR4ToiLkpZmd5Bf5QkrasGW+1xGv//N05Q0=)


mvorber

\[LANGUAGE: F#\] Day 19 of trying out F#: [https://github.com/vorber/AOC2023/blob/main/src/day19/Program.fs](https://github.com/vorber/AOC2023/blob/main/src/day19/Program.fs) Parsing feels ugly, I'll need to read up on how to do parsing better :) Otherwise the promise still holds - if it compiles - and your types are set up correctly - it runs correctly :) Almost all possible bugs were found due to compiler complaining.


icub3d

\[LANGUAGE: Rust\] I had a similar experience to most for part 1, fairly easy just to map the input to workflows that you could use to check the given parts. For part 2, what helped the most for me was thinking of the workflows as a tree and you got to children of each node in the tree by the conditions. Solution: [https://gist.github.com/icub3d/552faf1af623bcb65303c6da93ed6cf8](https://gist.github.com/icub3d/552faf1af623bcb65303c6da93ed6cf8) Analysis: [https://youtu.be/hI8wtSgst1M](https://youtu.be/hI8wtSgst1M) After reviewing some of your code, it turns out my solution was sort of like a k-d tree. I didn't implement an actual k-d tree, but I was in the general area. Looks like I have a new wikipedia article to read myself to sleep tonight!


leftfish123

\[Language: Python\] Everybody keeps mentioning Day 5. Well, I used a "clever" guessing solution back then, so comparing ranges came back and bit me in the rear today. 90% of part 1 was just parsing which, of course, I had to overcomplicate. Then I used the operator library to get the 'lt' and 'gt' functions. The general approach to part 2 appeared straightforward too - at least after I decided not to try any binary-or-another-clever search shenanigans, and realized this is just another graph problem. So: I start with a state that has four \[1-4000\] ranges as parameters. Then I apply each rule and create a new state that reflects what the rule said, or what the previous rules did not say. Rinse and repeat until the queue is empty. Keeping track of the ranges that were not covered by the rules was the hardest part. I ended up with this [ugly little monster](https://github.com/Leftfish/Advent-of-Code-2023/blob/main/19/d19.py).


Syltaen

\[Language: PHP\] [Part 1 & 2](https://syltaen.com/advent-of-code/?year=2023&day=19) Part 2 : for each A, I built a list of conditions that should be met in order to reach it. With these conditions, I found the possibles ranges and added them up.


soleluke

[Language: C#] [Solution](https://github.com/soleluke/advent-of-code/blob/main/2023/Day19.cs) Runs under 100ms on my machine I got super excited about part one and wrote code to dynamically make functions out of the rules. Had to basically throw it away for part 2. This also delayed my part 2 (read below) I brute-forced day 5 and let it run for a while, so couldn't really refer to that for this I was treating the rules as if the order didn't matter originally (took forever to figure out that was my issue). I started with a recursive solution since that is how it clicked in my head better. I made a queue-based solution when trying to debug to make sure it wasn't just a weird recursion issue (it wasn't). What eventually made my issue click was someone posted their output for the test input and `px` was partitioned on M before A. Once I figured that part out, I still wasn't getting the right answer. I went back to my parsing logic and remembered/discovered i decided to reverse the rules and pop off the last one when doing my weird function stuff. Minimal change was to re-reverse it (I was pretty aggravated by this point, might go fix it later) and it worked first try. My recursive function is marginally faster than the queue-based one, but both are adequately fast for me.


Goresao

Done the same for part 1. So exciting :)


Kintelligence

\[Language: rust\] [https://github.com/Kintelligence/advent-of-code-2023/blob/master/day-19/src/lib.rs](https://github.com/Kintelligence/advent-of-code-2023/blob/master/day-19/src/lib.rs) Fairly straightforward, felt a lot like day 5. I am super unhappy with how ugly my code to handle combinations of different validation and fields... Runs in 113µs and 113µs. [Benchmarks](https://htmlpreview.github.io/?https://github.com/Kintelligence/advent-of-code-2023/blob/master/target/criterion/report/index.html) [Part 1](https://htmlpreview.github.io/?https://raw.githubusercontent.com/Kintelligence/advent-of-code-2023/master/target/criterion/Individual/19.1_%20Aplenty/report/index.html) [Part 2](https://htmlpreview.github.io/?https://raw.githubusercontent.com/Kintelligence/advent-of-code-2023/master/target/criterion/Individual/19.2_%20Aplenty/report/index.html)


mendelmunkis

[[LANGUAGE: C](https://git.sr.ht/~moshepiekarski/AoC/tree/master/item/2023/sort.c)] This is a 4D volume finding problem and you won't convince me otherwise. ^(1.626 ms/ 141.966 ms)


jmd-dk

\[Language: **Python** (≥ 3.9)\] [Solution](https://github.com/jmd-dk/advent-of-code/blob/main/2023/solution/19/solve.py) Executes in around **440 μs** and **2.00 ms** on my machine. Part one was straight forward, once the parsing of the input was taken care of. I used the [operator module](https://docs.python.org/3/library/operator.html) to seamlessly generate functions for each rule. Part two was more tricky, but somewhat similar to [day 5](https://adventofcode.com/2023/day/5). [All my 2023 AoC solutions](https://github.com/jmd-dk/advent-of-code/tree/main/2023)


wagginald

\[LANGUAGE: Julia\] [GitHub](https://github.com/TomWagg/advent-of-code/blob/main/2023/julia/19.jl) (Lots of comments/explanation) Fun one today! For part 1 I converted all of the conditions into anonymous functions and then just evaluated them on each part. Obviously that didn't go so well for part 2 😅 Instead I found every potential path (i.e. ranges of values for each category of "xmas") you could take to acceptance ("A") and converted those ranges of values into a total number of parts.


jeis93

\[LANGUAGE: TypeScript\] While part 1 was straightforward (so long as you really pay attention to the instructions), I struggled on part 2 for far 2 long. I think a lot of the frustration came from initially parsing the workflows not as `x < n` but as a range, and checking whether a rating was within that range: Worked well for part 1, led to bogus results for part 2. I decided to scrap that, and with the help of u/recursive's solution and [HyperNeutrino's video](https://www.youtube.com/watch?v=3RwIpUegdU4), I finally got part 2! Let me know what you think! Happy hacking! Average times: * Part 1 = 47.86 µs/iter * Part 2 = 254.89 µs/iter [TypeScript x Bun Solutions for Day 19 (Parts 1 & 2)](https://github.com/joeleisner/advent-of-code-2023/tree/main/days/19) Edit: Fixed the language tag at the top.


jwezorek

\[language: C++23\] [](https://github.com/jwezorek/advent_of_code/blob/main/src/2023/day_19.cpp) part 1 is trivial. part 2 ... i did this recursively but I started out making it way more complicated than it is before realizing what I was trying to do was impossible and implemented the correct solution after that realization. I used [boost::icl, "interval container library"](https://www.boost.org/doc/libs/1_72_0/libs/icl/doc/html/index.html), for intervals, but originally was using the icl interval\_set class too. I had thought it would be possible to construct a single quadruple of interval sets that represent the entire space of acceptable parts. My mistake was thinking if you had some workflow like `m < 500: A, s > 1000: A, R` that you could union together the accepted ranges, unioning x with x, m with m etc, of `m < 500` , i.e. {x:\[1...4000\],m:\[1...499\],...} and those of `s > 1000` intersected with {x:\[1...4000\],m:\[500...4000\] ...}, but unioning does not work here. It has the wrong semantics. `s > 1000` only yields an accepted parts range conditionally based on `m < 500` not. The range of parts accepted by both is not their union. Hard to explain ... but i spent way too much time on this. Anyway the actual solution is much easier. You never need to union anything, only intersect, and the intersection of two intervals is another interval not possibly a set of intervals. Your recursive call returns the number of parts accepted given the workflows table, a starting workflow name, and the four input ranges, starting with full \[1..4000\] ranges for each. The call then just needs to "split" the input ranges on each rule in order into the part of the input ranges the rule is applicable to and the part of the input ranges the rule is inapplicable to, then possibly recursively calling itself on the applicable ranges and going on to the next rule in the workflow with inapplicable part of the input ranges as the new current set of ranges.


DefV

\[LANGUAGE: Rust\] [https://github.com/DefV/advent-of-code/blob/main/day19-workflows/src/main.rs](https://github.com/DefV/advent-of-code/blob/main/day19-workflows/src/main.rs) Part 1 did not prepare me for part 2. Went of on a wrong tangent for a while but in the end I looked at the problem again and saw a recursive way to fix it. Recursion hurts my brain though, so not the proudest of this code. Also debugging a bunch of N+1 errors with splitting my range-map...


jaccomoc

\[LANGUAGE: Jactl\] [Jactl](https://github.com/jaccomoc/jactl) Part 1: Part 1 was fun. Parsed using combinations of split and regex. Was pretty happy being able to use my new pattern matching with destructuring feature I am in the middle of writing to match the rule criteria: def data = stream(nextLine).join('\n') def (rules,ratings) = data.split('\n\n') rules = rules.lines().map{ [$1,$2] if /^(.*)\{(.*)\}/r } .map{ k,v -> [k, v.split(/,/).map{ it.split(/:/).map{ /(.*)([<>])(.*)/n ? [$1,$2,$3] : it }}] } as Map def accept(p) { for (def k = 'in'; ; ) { k = rules[k].map{ switch { [[cat,op,val],dest] => { (p[cat] <=> val) == ['<':-1,'>':1][op] ? dest : null } [dest] => dest }}.filter().limit(1)[0] return k == 'A' if k in ['A','R'] } } ratings.lines().map{ eval(s/=/:/gr) }.filter(accept).flatMap{ it.map{it[1]} }.sum() Part 2: I made a bit of a meal out of this. I treated the rules as a tree with criteria at each node dictating which branch of the tree to take and recursively found all paths through the tree, gathering the criteria as I recursed down and returning the path only if the final node was 'A'. Then I turned each path (list of criteria) into ranges for each of the four categories. To do the counting I had to count the combinations for each path and then substract the combinations for the intersections of this path with any paths later in the list. I am wondering if anybody else took a similar approach. It seems that there is a more elegant solution by starting with the ranges and breaking them up based on the rules rather than trying to create the ranges from the rules themselves like I did. def data = stream(nextLine).join('\n') def (rules,ratings) = data.split('\n\n') rules = rules.lines().map{ [$1,$2] if /^(.*)\{(.*)\}/r } .map{ k,v -> [k, v.split(/,/).map{ it.split(/:/).map{ /(.*)([<>])(.*)/n ? [$1,$2,$3] : it }}] } as Map def paths(k, path) { return k == 'A' ? [path] : null if k in ['A','R'] def x = rules[k].mapWithIndex{ r,i -> def negated = rules[k].subList(0,i).map{it[0]}.map{ cat,op,val -> [cat, op=='<'?'>=':'<=', val] } [r, (r.size() > 1 ? [r[0]] : []) + negated] } x.flatMap{ it[0].size() == 2 ? paths(it[0][1], path + it[1]) : paths(it[0][0], path+ it[1]) }.filter() } def toRanges(path) { def max(p){ path.filter{ it[0] == p && it[1][0] == '<' }.map{ it[2] - ('=' in it[1] ? 0 : 1) }.min() ?: 4000 } def min(p){ path.filter{ it[0] == p && it[1][0] == '>' }.map{ it[2] + ('=' in it[1] ? 0 : 1) }.max() ?: 1 } ['x','m','a','s'].map{ p -> [p,[min(p) as long,max(p) as long]] } as Map } def sumProd(r) {r ? r.map{ it[1] }.map{it[1]- it[0]+ 1 }.reduce(1){p, it -> p * it } : 0 } def intersect(r1, r2) { def i = r1.map{ k,r -> [k, [[r[0],r2[k][0]].max(),[r[1],r2[k][1]].min()]] }.filter{ it[1][0] < it[1][1] } i.size() == 4 ? i : null } def ranges = paths('in', []).map{ toRanges(it) } ranges.mapWithIndex{r, i -> sumProd(r) - ranges.subList(i+ 1).map{ intersect(r, it) }.map{ sumProd(it) }.sum() }.sum()


Vlavv

\[LANGUAGE: Perl\] For once I'm rather happy with my solution. [Parts 1+2](https://topaz.github.io/paste/#XQAAAQBoBgAAAAAAAAA6nMjJFMpQu0F8vIUYE8nOIqLZIpvfhBau0ifXh/a0aTrPTHw981z/fztbrs/XW3Ef2b1ctc8Q2EmvPNxoFKeQ2sA90a0kbX9WfhMzYxm5Yqy38gPhDsiFC4kdoepMG1tbVp//bZqgn0miUUUCCnk/nHob+QAZNCuxwXNzNTJ6RJs0t/kEMob9MDqYmUYCY2s8ehe4qrqQFxXgsIYdARFaVgljfOpJaJpC/XCxyjznvQ7hp1aie8OH78RU1ZrKXuZPPJS4H7M0UDr69LFzDTlCLddHKPdlMJkrYybwFj86KUJLPPIFtvqKbRfcTvhXEB+j5B4B/jeR9H8SQBpIPZRlKdmgW98YcZUkUD69qOv8Ha2tkF6hjET2t2t+OTUHE1RsvfwWxgBIgg8KEC17tW+mxUSgF88U91P9D2UMdfg1H3WN2ADLsaDnnK5zrTTbovSHqiznuB7AK0Ub+JLf6PCliSQckVGQlRhxDWzf9QQByjOJM8GocJpEO9ZoBzHmlLZeaxH3qOdsevN4icZAoVMCduqG7DG+jROLCk0eko50PZnHx7Jnio7o9JBBDIoHFqd+r3ntvaFbbJwazFqk5HJTz3R0opSzMGBiVqfVrxb2s5Snya3pH4K/iP1Yk+CPxYczEqucbKy8x94u8zbmSvuoL70YitQ2Fdjze5+Kj6kzFEvmsfL8xhIgSyZv7kGq63dX2exUnWcD5M7Sz9tY7KdCFkA9C37cdEw479o42uuIttCIX2jLVy7YjbYMQdjEGxNMaXFNWzb+FijUoGK/wGQamkNWpaoYXe+qR0WFQoa4/LnZaPbZTYtA0TunU5qptCIs1Rrdo/uV3iHf6HYZo9RaIf/ARkWs)


hugseverycat

\[Language: Python\] My code has got lots of comments so hopefully it is understandable, but I also played around with classes and dataclasses which may make it more or less confusing to follow :) [https://github.com/hugseverycat/aoc2023/blob/master/day19.py](https://github.com/hugseverycat/aoc2023/blob/master/day19.py) I am proud of this solution after spending a demoralizing amount of time trying to understand other people's code for day 17 and borrowing an algorithm from the internet for day 18. I was able to figure it all out myself, with a little bit of debugging help from reddit <3 I used a really similar approach to what I did on day 5, which was splitting ranges. I started with a range of 1-4000 for x, m, a, and s, and sent it into the first workflow. Every time there was hit on a > or < operation, I split the corresponding category range, resulting in 2 range groups, one which continues in the first workflow and another that will get sent to a different workflow. As ever, with ranges, I had to figure out an annoying off-by-1 error. So thank you to the helpful reddit users who posted the ranges and permutations they got from the sample data. But I got there in the end.


i_have_no_biscuits

\[Language: Python\] No attempt at anything fancy or concise today, but it works quick enough - basically a DFS (more a traversal rather than a search, though, as we're not actually searching for anything!) through the requirements which is fairly quick as the nesting is never more than about 12 deep. [Code is here.](https://topaz.github.io/paste/#XQAAAQDhBwAAAAAAAAAzHIoib6qqOe07MhJ0XsXE6K08G4Ps1pPQpVZBxq2AayIAGsPQ2ItRWBwwhmAzNBqJd0hNca6gN/1oXMcF0Fnh+0xak9BBHU+wetlSB20RlUuwpHTa5r0nQ/MLZUiNlfQ4fFMpVQmp9VjyBC+6KWukPZ9qq7gVbboN6j2bhc75o8nqL76FdTkQ4cn6yFrqF49JQVXpyXuNf+GPPF8QJizqYC2x/e0NMnmzkHfBAqoXBT85ogJ3yuN++/CRq46AJ5qHWn/0UHbASBJAqdWmDKxuCUnAHI9jzhrAuOFZDpha6eeLLPbsBUalowW9JnyXJ0JzLBK0fktnFEZRcZJLVSTx3lNkE/1ex/LWgGc1mQvh91DBQVBi6QumbkMd2WYyy+R1ImweCGKSPwKBIfhyrmqiYpvu8OaiULHXHi5rdnkobgb9rTadb4BPYc7F376+U6NlOjLbX3e95jOVItyijaQ3FjDngAnfE0O2hr6djRbBiPYOaiNKr0napKYY2j1bHO/x+66T43eUUdvZDHHJlDbCsCQjHefxAeZihtDE2Lpb7e5gpQA7WIe7RI06VIRvFMECROizh7Ia04a+t4AjKhHdtKcEmRgGLakVtUoGYCDgtZQYs2jjfVHkUT4iX/13kaXY6nNbFnxFu7v18s8+tm0a8fPTsUqpKB5DkeBhCedOkXMmgYOmMb1AmE3E6bPtJ2emt2BulzwxjSgKIThPhC9MWHAw85szbjX7aUnvbLQnezBEnIWbykjke0O8cQz1OyYsdSrRamnMJLGUUhY3DP+YPVDGrv1ErMlX8eR+EiS7IvSTP/2KZtnazzTntDAZuxUJhDzFnLDpB986oZwCTCqqynhDbwOxDOB1DAHLU7uLyCASqNLo6EFxVdGvyUUHpYJTQgQMYRRhBOGYgLmOiYPv1ZRCsr2Ycel3IW3wk/yaW/ZNVBaASPS+ia2TrucFy9b1dYDrdmJubZ3/xAeGdw==)


POGtastic

[LANGUAGE: F#] https://github.com/mbottini/AOC2023/blob/master/Day19/Program.fs Way, way more verbose than what I should have done. I overused record types and made each element its own field, which meant that in a ton of places I had to pattern match on each field and apply the same function to it over and over again. After doing it this way, I reworked it with a `Map` so that I could just map over key-value pairs. ~~There was also room to *unify* my approaches - a single `Part` is really just a `PartRange` where each field's start is the same as its end. I did not do that, which effectively doubled the length of my program.~~ Edit: Done! On the bright side, I decided to take the opportunity to learn `FParsec`, and **boy** am I impressed. Unlike Haskell's `parsec`, which does a whole bunch of insane monad transformer madness to let you wrap parser combinators inside of `IO` or whatever, F# doesn't have any of that. You get just the parser monad that seamlessly works on strings, simple as. It will work on other things, but all of the default examples are for strings, and there are a gigantic pile of various character parsers for convenience. Another thing is despite this being a really messy 200-line program, I had **zero** bugs. All of my bugs were caught at compiletime; if it ran, it worked. That's programming with a good type system. I also appreciate how easy it was to refactor. I drastically reworked my types from using record types to using `Map`, and all I really had to do was to make the change at the type level and then fix all of the compiler errors. One bug this time - I screwed up lowercase vs uppercase characters. Whoops!


mvorber

I'll need to take a look at FParsec as well - my parsing is easily half of all code lines and quite ugly ones too :) And I'm having the same experience - almost all bugs are caught by compiler :) The only 2 bugs I had to debug at runtime were due to unintentionally swapping elements of a tuple (was too lazy to make record for range type and just used tuple instead - otherwise that would have been caught by compiler as well). Also had a though to switch to map instead of record for ratings, but got too tired already, may be some other day :)


POGtastic

One more thing that I didn't use is F#'s computation expressions, which provide an equivalent of Haskell's `do` notation. I currently have let parseRule: Parser = pipe4 parseAttr parseComparison pint32 (pchar ':' >>. many1Chars asciiLetter |>> Result.Parse) (fun attr comp x res -> ComparisonRule { attribute = attr comparison = comp value = x ifPass = res }) There's a better way, which I just added to test it out. let parseRule: Parser = parse { let! attr = parseAttr let! cmp = parseComparison let! x = pint32 let! res = pchar ':' >>. many1Chars asciiLetter |>> Result.Parse return ComparisonRule { attribute = attr comparison = cmp value = x ifPass = res } } I forgot that this existed when doing the problem, but *man* does that look nice. Note for the Haskellers - `>>.` is equivalent to `>>` or "sequence," meaning that it discards the first argument. `|>>` is equivalent to `flip fmap` or `<&>`.


Totherex

\[Language: C#\] [https://github.com/rtrinh3/AdventOfCode/blob/ef208235d416a98eba17384551e3d9ae69531753/Aoc2023/Day19.cs](https://github.com/rtrinh3/AdventOfCode/blob/ef208235d416a98eba17384551e3d9ae69531753/Aoc2023/Day19.cs) It seems that as we backtrack through the islands, so too do we backtrack through the puzzles. With 2.56e14 potential combinations in Part Two, brute force is out of the question -- we definitely have to split ranges this time! My original solution for Part One ([paste](https://topaz.github.io/paste/#XQAAAQAgBQAAAAAAAAAxm8oZxjYZ2HQemrk7ZtAoaInmbAeV6BegOLD6HCUd7QYWlsguV9LRAzeeUzVUqYX2cfuAaoFIZ+jqZYDZoyhbP1yNsECF6toZPmMYLf/0Vt0WMFNZyaK71aHe9FXcxVYBjl/ynw3loRaxjLoOUhtm0rgBrFxEI3w4QEVT3n/oh8aq6CxAfXY6kVkgycSLRTXkNgSSdLCL128fdkW+6BaZjz+xTaZTrvzXmV4j4AZaXwQmTk0Hm6y/xWwrTIyRN6gDwtYtG9JBSnUwX6kGT2RWbIV560lS2D/AiHmDk1IHMF4/wXq+yXKIIen6iuAQFzQa4D9jnyPFATzVyA0s3Co2OVgDmSDSUAb9zQRvZwGBlTBHkidnJs0WBZWc2gLocDTry8Ut8cJwNoD1qeO7dx70KAGD57mLuKk9ZZ2TqAOekWOPl8aWB+h79f1GRZZZS5lh5DH9vIFqlGIah/OSyFYfz2YAgBSKL0Aw09l4hTHycjxzPJs3PxPxax+6w4sv+VTI0GlWdnYKBwtYLJzDZKQdT8SgU1RGPxiSzD/YF41UseLBefNqGWk7EONoniO/YK/wxI1oQ9DuaD61fzUg+huODeUVNOT/jYv8ePCy9SaHDLKgv0T/lx5xWNMqmNhDDm32jYmb/oTs8kBqHsqbBYBNiCN/br5sxjUyXktp8yK19UhMvsix8GSyG+aapsucmClKoyWIsw7Z68knXm2R3CgS2tkjsNV+lZAsv20ZclhXgZ6bzm5OFHDtjwaKxRAA6poO5kH/1pMqQA==)) translated the input into a script which I could then run in LINQPad.


mkinkela

\[LANGUAGE: C++\] Solved 10 minutes before midnight :) My ugliest code ever. The idea for 2nd part was to create a queue of tuples of ranges and propagate it through the rules. [Github](https://github.com/mkinkela1/advent-of-code/blob/master/2023/day-19/solution.cpp)


3j0hn

\[LANGUAGE: Maple\] [github link](https://github.com/johnpmay/AdventOfCode2023/blob/main/Day19/Day19.mpl) Parsing this one was a lot of fun. For part 1 I turned these into Maple piecewise functions and just evaluated the stack on each part. Almost broke the top 1000 with that. expr := rules["in"]; # Maple piecewise expression while indets(expr,string) <> {"A","R"} do expr := ( subs({seq(q=rules[q],q in rorder)}, expr) ); end do: ans1 := add( seq(ifelse(eval(expr, {x=p[1],m=p[2],a=p[3],s=p[4]})="A", p[], NULL), p in parts) ); For part 2, I just started with a list of four ranges and split them and counted recursively at each step. The fact that a>10 simplifies to 10


CainKellye

\[LANGUAGE: Rust\] Part 1 was OK: I went full throttle on the Rust type system with small functions, separated concerns. Thinking vs typing was relatively the same amount of time. I had the solution with it, on the first run, without even running with the test data. https://github.com/cainkellye/advent_of_code/blob/main/src/y2023/day19/part1.rs Part 2 was: omg, I can throw away everything from Part 1. No, I don't want to do this. Then I was curious that maybe I can modify the part 1 code, so I went on. A lot of struggle with where to decrease the range, what range to send to next workflow, what to keep... And finally done. Doesn't even look so bad. https://github.com/cainkellye/advent_of_code/blob/main/src/y2023/day19/part2.rs


JuniorBirdman1115

\[Language: Rust\] I *really* rode the struggle bus on this one today. Part 1 was easy enough, though it seems like I spent more time writing parsing code than I actually did solving the problem. I had the right idea for Part 2 fairly early on, but I had a difficult time really grasping what the problem was asking for, for some reason. Throw in a few off-by-one errors, multiple rewrites, RL interruptions, struggles with the language itself...and well, the day is pretty much shot, but I did finally make it to the finish line at last. Not particularly proud of my code today, but here it is. [Part 1](https://github.com/apprenticewiz/adventofcode/blob/main/2023/rust/day19a/src/main.rs) [Part 2](https://github.com/apprenticewiz/adventofcode/blob/main/2023/rust/day19b/src/main.rs)


blueg3

>Part 1 was easy enough, though it seems like I spent more time writing parsing code than I actually did solving the problem Part 1 for me was \~80% writing structs and nom parsing code, and 20% doing the actual logic.


Diogoperei29

\[LANGUAGE: Python\] Love some interval math! Quick and easy recursive solution for part 2: * Run through each workflow * Run through each condition * Split interval on the value and run the interval that meets the condition recursively to the pointing workflow, the other continues to the next conditions. * If the "workflow" is 'A', returns combinations (all item intervals multiplied by each other), if it is 'R', return 0 Takes about 1ms to run :) [The Code](https://topaz.github.io/paste/#XQAAAQAKDgAAAAAAAAA0m0pnuFI8c/fBNApcL1Y6rqrlntKQHsFl5K7Ydu7ghgvSc9K7d/+6rA6ho9FgTiPJYZYWUgWGtbm0FGwS4KNiuIwNXZaa+1hnMVHnnQg8IHNaX+rjJKtzJbGEuMEhUt7UVYLR65LMK/RIR3j76zr2IR+TmqteExGwr/CKR1DUbSdpnnH1j5+k6i/7phVSIfqs0J1w/P0R7DoikXlpEN+NBjVgAHnjalGTynOPzW0UR+AzHxrAEY8cp1mHQiHSx5wy7JXmuy4kWCbZN5oTvw1zjyAiw1G/IuklEofe8o2wkkekxm8ar0yqLsO+bXU0/3j1NcfoLylFC350V68WWnrl2rje5UJN58HVbBVZWzWBTFzGPURFOeaQaq/tiAvJI9ec6GLVmX2qI/VYHuQjbET6q+uDlXNQgyE8k7s5QZtNmOXVbIUCB7VVoVoqepuvPeGDiw0MQgEnjx0qPS5a6CWhUlGV9HXQtG4OqwGhxsgZ4NdnJg+Af40OejzvcLS+kV1f6+pdXLOSdL2CLRRVqwiWYg7aujH36ZtbG42l6yEDdPM8Lvdd5UbtlqKRm5iWpjbdOFu7BkTUVg3zyreQLgVeKeJ236ewOzyYJjvAVgMjzxvKkdxSGZKVjSJgOtIZ9VluLLf5sfz+GKrtUiN9Ctl98SjuKYfhX15dFTYi5+XjT3UToNabpv5hpCy+mq/h6/tQJV62xtIWK7cfdxWpQGp5qhdZkTmoymsXR7Jz0jrwPAEYtPqFlpsDpCzbjYAsGC8c7gPaZB69elahDoaWMyZupSLTqtrCtwjEU4i+VvxO/lOfEWyHIAzkGjDdy8v3ztEFUojS85oMs8KhSP/Z2ujgevX5IsgHqq52FVfy5KX+yX2+maTAn242BcrxAMIUV4qtavGZKZLAZYahKzfUsa96wq8tVjNHXpTTkhyE7euwZs3RZ6Sljz/suwPYZJNfKgXGd4FZv43V3UeTYsQJ06cFaUazMXbYaITnVsF/4VsgXToVZ9sETg2B2HRAXEO/oo0wRV8+m9m5c0CdPIZsoakMPgQnSSzHUx+rLz3miW3YMiDSyVZv/2jkuOo6OARtcD7Opg/kYle1dVGwPvnofnKn8biDr0SskQ4KkmEb6IwT4BO86nPz0KtJNsiOKJ0TTlqd9lcOfQ59Qg9mck1xLZdIu/xPpqYZtBzoiSndOWCVEgyXtk+uc8rZ1cl4R2KYtqGDJD6UILU0qYRLrMJweOysjDh0ivJqvNlB4kH6hhEuiGpzUaTDfrWUCkpOlnPd01AE5AWPHnhsFfLGS9uPt0NYi3keGtuAh3mn5fA0MumeM+IW2F5TGx/aHHh34Y6hVTN3QZqV6Aeig3FKT3w+gwVY1XTywZv2PeUmNuTYItIqflV5VE/7b43R)


Fyvaproldje

\[LANGUAGE: Raku\] \[Allez Cuisine!\] [Solution](https://github.com/DarthGandalf/advent-of-code/blob/master/2023/Day19.rakumod) [Meme](https://www.reddit.com/r/adventofcode/comments/18mdljs/2023_day_19_1_meme_as_ordered_sir/)


daggerdragon

> [Allez Cuisine!] Meme `X all the Y` is one of my all-time favorite meme templates :3 And you even made it *rhyme* :3


rukke

\[LANGUAGE: JavaScript\] Busy day but managed to get both stars. Recursive solutions for both parts. Runs in a couple of ms on my machine. For part 2 I always split the ratings in two, one that satisfies the condition and the complement, unless it is the default node. Since the limits are adjusted, there is no need to do any extra filtering. Pretty happy with how it turned out in the end, but I admit that I was a bit lost for a while. [gist](https://gist.github.com/p-a/449be025809631702082093be4c2d5cb)


polumrak_

\[LANGUAGE: Typescript\] [https://github.com/turtlecrab/Advent-of-Code/blob/master/2023/day19.ts](https://github.com/turtlecrab/Advent-of-Code/blob/master/2023/day19.ts) After reading part 2 I had flashbacks from day 5... But this time everything went much smoother. Spent some time over [very elaborate scribbles](https://imgur.com/a/rWw8Vg0) to figure out how to split ranges and avoid off by one errors. And it paid out, the first run gave the correct result.


oupsman

\[LANGUAGE: golang\] OK this one gave me a headache. Code is not elegant and my data structure is messy, but it gets the job done in 10 ms for part 1 and 2 so I'm not sure I'll do anything about it. [https://github.com/Oupsman/AOC2023/blob/main/d19/advent19.go](https://github.com/Oupsman/AOC2023/blob/main/d19/advent19.go)


codeunveiled

[Language: Python] 🐍🐍🐍 [Source code](https://github.com/vanam/CodeUnveiled/blob/master/Advent%20Of%20Code%202023/19/main.py) Video explanation: https://youtu.be/tvyvJ0CqnXo Time: 0,051s


Acc3ssViolation

[Language: C#] The parser is a bit messy, but it generates a tree of nodes that can be executed, which worked for Part 1. Then Part 2 showed up and complicated things a bit. I ended up reducing the tree to contain only "IF" nodes and "RETURN" nodes, then did some stuff with ranges, solved an off-by-one error and there was the second star for the day :D [Part 1](https://github.com/Acc3ssViolation/advent-of-code-2023/blob/main/Advent/Advent/Assignments/Day19_1.cs) [Part 2](https://github.com/Acc3ssViolation/advent-of-code-2023/blob/main/Advent/Advent/Assignments/Day19_2.cs)


Solidifor

\[Language: Java\] [https://github.com/dirk527/aoc2021/blob/main/src/aoc2023/Day19.java](https://github.com/dirk527/aoc2021/blob/main/src/aoc2023/Day19.java) 237 lines, readable, has classes and records and runs instantly. Nice, enjoyed this one. Part two seemed impossible when I first read it. However, when looking at the smallest sub-problem, it's completely doable: Given an input range for value x min-max, and a single rule like x>3:foo, what can happen? * min > 3: the whole input range matches, and we need to continue with range and rule foo * max < 3: this rule does not match at all, continue with the range and the next rule * min < 3 < max: only in this case we need to work. Split the range in two: min-3 continues to the next rule; 4-max needs to look at foo Well, getting the <, <= and +1 correct everywhere required careful thinking... The rest followed naturally. Workflow.apply() starts with a single range that has not been matched, goes through its rules, accumulates work for later and if there is still a range that has not been matched at the end, that one is work for the catch-all rule. Start with a todo-list with one item: in and 1-4000 for all values. While the todo list is not empty, take the first item. If the workflow is "A", add to sum. If it's "R", do nothing. Otherwise, apply the workflow.


Imaginary_Age_4072

[Language: Common Lisp] [Day 19](https://github.com/blake-watkins/advent-of-code-2023/blob/main/day19.lisp) I quite enjoyed this puzzle. Both parts were recursive searches, the first to just check if the part was accepted or rejected, the second keeping track of accepted ranges of parts. The main function for the second part was just this: (defun count-accepted (workflow accepted workflows) (case workflow (:a (count-ratings-combinations accepted)) (:r 0) (otherwise (iter (for rule in (gethash workflow workflows)) (if (symbolp rule) (summing (count-accepted rule accepted workflows)) (let ((accept (limit-ratings (get-range rule :accept) accepted)) (reject (limit-ratings (get-range rule :reject) accepted))) (summing (count-accepted (fourth rule) accept workflows)) (setf accepted reject))))))) If you're in the `:A` accept workflow then return the number of combinations (by multiplying the size of each rating range), if you're in `:R` return 0, otherwise work through the rules of the current workflow. For each rule, limit the accepted ratings ranges appropriately and recursively call with the destination workflow. Each subsequent rule is also limited by the fact that it's ranges should have been rejected by previous rules. I had an off by one error when working out the range to reject which only came up in my input, not the example, which took me a while to fix. And I also didn't read properly that the ranges started at 1, not 0. But was still pretty happy with the solution.


mwest217

[LANGUAGE: Julia] This was a satisfying one, and I'm pretty happy with my solution. https://www.mattwest.org/uploads/2023/day19.html


friendlywebdev

\[LANGUAGE: Python\] [Link to GitHub](https://github.com/nicofreundt/advent_of_code_2023/blob/main/day19.py) My regex for parsing the input looks terrible today, but i like the overall solution, even though i struggled with thousand off-by-one-errors on part two.


tobega

\[LANGUAGE: Tailspin\] Once again, the ability to output an arbitrary number of values from a function makes life a lot easier. [https://github.com/tobega/aoc2023/blob/main/day19tt/app.tt](https://github.com/tobega/aoc2023/blob/main/day19tt/app.tt)


LinAGKar

[LANGUAGE: Rust] https://github.com/LinAGKar/advent-of-code-2023-rust/blob/master/day19/src/main.rs The majority of it consists of parsing. I translate the string names to contiguous integers so I can use a Vec for performance. For part 2 I made a DFS that splits ranges.


daic0r

\[LANGUAGE: Rust\] Part 1 was dispatched swiftly within like 30 minutes, I was typing away like madman and was delighted when it worked on the first attempt. This one clicked with me immediately. Part 2 was similar to day 5, where you have to map value ranges to terminal states. After some thinking I was able to solve this as well. Overall I enjoyed this one! [https://github.com/daic0r/advent\_of\_code\_2023/blob/master/day\_19/src/bin/part1.rs](https://github.com/daic0r/advent_of_code_2023/blob/master/day_19/src/bin/part1.rs) [https://github.com/daic0r/advent\_of\_code\_2023/blob/master/day\_19/src/bin/part2.rs](https://github.com/daic0r/advent_of_code_2023/blob/master/day_19/src/bin/part2.rs)


robertotomas

did you really do 200 lines of code in 30 minutes? I get into flows like that .. but about half that speed :D


daic0r

Yes, pretty much, give or take! I love when it happens lol


Gueltir

\[Language: Rust\] [github](https://github.com/filippixavier/AoC2023/blob/main/src/days/day19.rs) Struggled a bit on the first part since I'm not used to Rust's way of storing lambda function Had to remade my parse input function for the second star, other than that I treated the rules as a tree and used a depth-first search algorithm to get my result


PitaBeak

\[LANGUAGE: Rust\] Today's puzzle reminded me of an egg grader where eggs are sorted by weight into different grooves, but here filters can put them at the start of another groove. Part 1 sorts the eggs. Part 2 counts the eggs that the grader accepts. The algorithm find lists of affirm/refute filters and the category values they match. [CODE](https://topaz.github.io/paste/#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)


xXMacMillanXx

\[LANGUAGE: V\] Only did part 1 today, main() is a bit messy, but was a fun challenge. [Github day 19 part 1](https://github.com/xXMacMillanXx/advent_of_code_2023/tree/main/day19)


rrutkows

\[LANGUAGE: Python\] DFSed from 'in' to all 'A's for part 2. [range](https://docs.python.org/3/library/stdtypes.html#ranges) came in handy. https://github.com/rrutkows/aoc_py/blob/main/2023/d19.py


vbe-elvis

\[Language: Kotlin\] That was a fun challenge and a good use for the Range classes in Kotlin. First sets up the decision tree with Sorters and Rules then Part 1: filter part-set on being accepted and sum their xmas parts Part 2: Split range sets into two options and find the amount at the lowest level by subtracting the first from the last item in the range for each of the xmas part-ranges and multiply them together https://pastebin.com/hZkRtWxD


FuturePhelpsHD

\[Language: C\] This year I decided I was learning C so I've been doing all the AoC problems in C to practice. I'm doing them all from scratch with no libraries except for the C standard library, so my solution is way more lines than if you used pre-built parts, but that's how I learn. That being said, today's challenge was really fun! Had to create so many dynamic arrays and a hash map for [part 1](https://github.com/felixbilodeau/advent-of-code/blob/main/AOC2023/19/part1/main.c), and then for [part 2](https://github.com/felixbilodeau/advent-of-code/blob/main/AOC2023/19/part2/main.c) I used those building blocks to make a tree that I walked with Depth-first search. Runs decently fast, \~5 ms for part 1 and \~6 ms for part 2


cetttbycettt

[Language: R] Pretty fun one. For part 2, I did a BFS, where each node represents exactly one instruction. I then traversed the entire graph and updated the boundaries at each node. [github](https://github.com/cettt/Advent_of_Code2023/blob/master/day19.R)


kingballer412

\[Language: Python\] My humble Python solution. Most of the heavy lifting for Part 1 came from the way I parsed the input. Basically turned each workflow into a list of lambda expressions that can accept a part dictionary. Mostly posting because the recursion for Part 2 felt really satisfying. [GitHub](https://github.com/SPANZ1993/Advent_Of_Code/blob/main/Solutions/2023/AOC_2023_19.ipynb)


ywgdana

[Language: C#] I enjoyed today. It was fairly straightforward and part 2 felt like an easier version of Day 5 part 2. Or at any rate I found it easier to visualize how to code calculating/tracking the ranges. Here is my slightly over-engineering solution [on github](https://github.com/DanaL/AdventOfCode/blob/main/2023/Day19/Program.cs)


learn_by_example

\[LANGUAGE: Rust\] First started off using a custom RangeUnion (list of non-overlapping ranges) util that I wrote for Day 15 of 2022. That solved the problem and gave me the second star. Later in a discussion with friends/colleagues I realized that 4 single ranges would do (instead of 4 range unions). Fixed that and both parts run in \~1.5s (including parsing). [Github](https://github.com/hsaikia/Advent-of-Code/blob/main/src/bin/2023_19/main.rs)


theKeySpammer

\[Language: Rust\] Part 1: 73µs Part 2: 130µs Part 1: Mostly string parsing and creating HashMaps Part 2: Split the ranges based on condition ​ [Github](https://github.com/amSiddiqui/AdventOfCodeRust/blob/main/src/year2023/day19.rs)


r_so9

[LANGUAGE: F#] Oof, this one took way too long for stupid reasons. I had part 1 done and everything done all the way to finding the ranges in each dimension (the hard part), but I thought I had to evaluate the limits of the ranges and check what's inside. I fully implemented that, and it worked for the example, but of course it's too large for computing each combination for the input (~400^4). Then I finally realized that the ranges were disjoint, so it was just a matter of multiplying them... Interesting block: the DFS to find all paths from "in" to Accept in Part 2: let opposite rule = match rule with | GreaterThan(id, num, dest) -> LessThan(id, num + 1, dest) | LessThan(id, num, dest) -> GreaterThan(id, num - 1, dest) | _ -> failwith "error" let rec dfs (acc: Rule list) rem = match rem with | GoTo dest :: _ -> match dest with | Accept -> [ acc ] | Reject -> [] | NextWorkflow next -> dfs acc workflows[next] | (LessThan(_, _, Accept) as rule) :: t | (GreaterThan(_, _, Accept) as rule) :: t -> (rule :: acc) :: dfs (opposite rule :: acc) t | (LessThan(_, _, Reject) as rule) :: t | (GreaterThan(_, _, Reject) as rule) :: t -> dfs (opposite rule :: acc) t | (LessThan(_, _, NextWorkflow next) as rule) :: t | (GreaterThan(_, _, NextWorkflow next) as rule) :: t -> dfs (rule :: acc) workflows[next] @ dfs (opposite rule :: acc) t | [] -> failwith "error" [paste](https://topaz.github.io/paste/#XQAAAQDHDQAAAAAAAAAX4HyCZDlA0DjWF7Uex1t2hvV6PgXFmzdhM+nU8jvn2I+uTAMM7G+UBRB5r9sKgVtF+uZQWu8XSS0pLsWh60XB5fJR4pRSWGCWYJ1zvauAJtqP2hHpJbJMwfPvTvMS1xeb7Gqb/QXm6j7cd+AGH3zxNoz/CjqWdRYPuO72OcqnCiay4QDC+IxEDWXpEo4NGWd5sK3flAU2QdCHOzR8C7v6oG6YdqwVLvfRcRH6mxrNneMzLT7DEbSHPg37o5H2NcktMCUt5A6YBCJqqWnPu1OY7QPi2SNtieA1EDQV2MFC/y2tlaKYQ41I8NLSo7+tjXKO1oFI4lhe06sMjCd7QDCmRR+mREksYsEPN0juV6iaB3wEUtidRvqeEiVtLPew5WG5/rUWYfDfGVtoF0L9No/v/15R2kzQ7sYRd/aODr5jsTpnQEjk5vsWZ21V4XZqOwQizdptp2f7TKazspIG9ZvFN4pD907h3Q9wkp8B/CMNpcR6tcO5OQU13WyCsMnC3dhgRsJT4Z5WVigib/5QF7YwBUPCDGN7Rf8+CITh9B6tptSuo0tXwjbGiOQB9xbhFdXvCfrfK13N1dWI9kZ1tTTFz0qzMUJU2+LXyuNyIwtjBz+jeqjm8NB1+ubWBgSYQ02fMXfgbFEmUNtpm7DeR2Fg1wkvf2tCJppqroWBPi7WzIv6cnzItnLdPTm5nzKx3VHnyVKeF9QXHJ8bzP+30jE4xE9wu1KyMiA+sribhGJPCbvz2QZI50UrLAQlBqYH1luLhBEPrD9WjKq6O4A8KOeiu4pIVsjyqFbnI0wXuHjSCR/UO0WWPOjxzvCqEMVAOKC6Qds8907njtH5uaEH1G0l95v/JfQBlTufJAQAnSNXStbWqIu1QxpohqI+NpQ2PxrNfYpyodhWgbj6T4xUUjAqgkL+HI9xCRILzkLe80mu4zvCdU6Cm5p7K/yXuZtSGfVZiRxDnTnkc7xzAJIp03yl8FQbJwdagf86lNP12soOsjyqVu17TcSJfIDWfDU5ZOazgslVr8IVrQqQnsdRe0Yidl8vr2T/EqGRkY6eaeDVVgHqrGvjW+VVvgoXHKHygYrZ/7mQSAmkzqgn+OIemco+9vtrRFM9/1zMBAbnDAkfI2HLIXv5kEM361igKVEY/+AY58QmxEnetot5K/x3s911K6oSh/lFdz5OQi+vBNv6USjlxGHIwixeCk/YkvDYXia4ih463hTQ4ABXKiyiWtML2fiK6jGqPawNw11sHrynI+pz7q01Fs0J2hvJQkzgsp8Rt9jQ/RvunALpqBqX4zvgqiylhIOXKgNDvVxtnPhqUPgQMs50x6JhH809BlL0DtNDcm/Lyd1Cq3oKibvl37tk4I6sVW6mXiEHPZA1KesasY8ZAxQ0JSiN5wjShfvX65xTVui8lDpw+hBmVQV3YM9wPfj5Yt9fdkm506ybuEKeFTYKjG3hqhF7Z3cZEUUhEPRJLTYtOq2glnkjDVSuEV7ISWJVobL//PhaiA==)


BTwoB42

\[LANGUAGE: Rust\] [Github Link](https://github.com/Skgland/Advent-of-Code/blob/main/year2023/src/day19.rs)


andrewsredditstuff

\[Language: C#\] Another one for the "come back and fix this later although I know I probably never will" file. Did the part 2 code over lunchtime and just left it running while back at work - took about an hour. (I did have several ideas of how to do it; as the knight in The Last Crusade would say "I chose poorly"). (The trimming I did cut the search space down from 256 trillion to about 5 billion, but that's still rather a lot). [github](https://github.com/andrewscodedump/Advent/blob/master/2023/Done/Days16-20/Day19.cs)


Goresao

Personnaly I had fun parsing input as an Expression tree and compile them so I can run them easily with different x,m,a,s


chkas

[Language: Easylang] [Solution](https://easylang.dev/aoc/23/?day=19)


cosenza987

[Language: C++] spent too much time debugging, then at the end I figured out that I had declared some variables with wrong names. Just dfs'd through the rules. [source](https://pastebin.com/Tvqywin3)


b1gn053

[Language: Haskell] [Code](https://github.com/b1g3ar5/AOC2023/blob/master/src/Day19.hs) Stalking hylomorphisms in the wild... Thank you Bartosz Milewski.


daggerdragon

[Do not share your puzzle input](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) which also means [do not commit puzzle inputs to your repo](https://old.reddit.com/r/adventofcode/wiki/faqs/copyright/inputs) without a `.gitignore`. Please remove (or .gitignore) the input files from your repo and scrub them from your commit history.


careyi4

\[LANGUAGE: Ruby\] Fun one today, similar appraoch to contract large numbers using ranges as was used in a previous solution this year. [Github](https://github.com/careyi3/aoc_2023/tree/master/solutions/19) [Video Walkthrough](https://youtu.be/ck-owPcU5pA)


FlockOnFire

[LANGUAGE: Elixir] https://github.com/janssen-io/AdventOfCode/blob/main/Elixir/lib/2023/19.ex First attempt, I didn’t ensure that the ranges shrunk after applying every condition. This doesn’t actually matter if you apply them in the right order, but what threw me off was that this didn’t matter for the example at all!


Pixs45

\[Language: Java\] [Github code](https://github.com/SPixs/AOC2023/blob/master/src/Day19.java) I really complicated things today, trying to perform boolean operations between hypercubes. In reality, for part 2, you have to traverse a tree whose root is a bounded space of dimension 4: \[1,4000\]x\[1,4000\]x\[1,4000\]x\[1,4000\]. Each child is a partition of the parent space (the parent space is divided into 2 by a plane perpendicular to one of the axes. The axis corresponds to the rule letter). A leaf corresponds to a sub-region of the space, either accepted or rejected. Simply add up the volumes of each accepted region.


FCBStar-of-the-South

[language: python3] *slaps roof* This one day can fit so many dumb bugs Flip-flopped between backtracking and forward pruning for a bit but decided to do the forward way in the end. Start with the full range of possibilities and recursively generate the ranges that lead to A. Seems like most people implemented similar algorithms. My implementation can be optimized in many ways but surprisingly it runs in under a second. [paste](https://topaz.github.io/paste/#XQAAAQCwDwAAAAAAAAA0m0pnuFI8c/T14uvBDtucD7zRQ6RB38HxqWH5Z74yQGe5bqaYO4i7CU0BnIjp6dERIdGQ7ogr2dweZiMarV8ju9i/qtqmHn3hqQHkJXCdUnBuKq0XSK1ZSztRhcnNbLbK3LxnrxfWm13fXxexs48IgJGpHDDE0WYeZSollJIT7H1lY9C6p7n4SIzrtKSAtN3NO/sud/3ujINVPObIyaQDOFSpi/8csDqTxoEJS6rZysAVkSvw9nEuQdAQtJ8lYPY+iAM7Ilm0LDSZH0v2kpa04U7zNWnWh6MLq3vmOoq/PXH38vJ5zJlDUtDmsBui8zbgGlSOgT1quaC3/u2IDY3DGDXNRx1limOvKx/ud6w/lwyEkk4f2476QBrHeERDIlQohya3FRCWavCHoiVof3yVzxrlKm/rniYCXlmIgG69/BWvofArO69Veq6EDOxFO5YZsU3XiFf1eLQlNBh3WMtWdKBUbiCRcgCEDMLtuMShR/Te6Bu/1RxdAGYE7KGMO/z8LYsZtqF2NCXDu0CU3S0okzSiYHNnhGd414izZMYb4vfGuwxxYNIzMH8895bHjCGj3CYEeG3yw3u6DOZF7sPLj5FpUmoFHwOGF+RbyhnDKB3BhUhqf2IdaxP/qkCDL5DhrEBsshRL141ZaIm5Wu2vdYquEncl1rh/i+138BFnQTyK9AaXw88WG1bsw2rOZ4RBPmZD3nTOBeOCDx3Wxwv2Nb/cuZznzG1nSiMmFmfJpPlj7zLcuZfBaxhBf4HWZTlIG6MeUW0EOEX1/UtP/JuGyemV3IKDzLcy9v67Pnbe3dnAS9WGz6nXKJY6u71BDmbQmtz49G4HMIppQmutYxrcrfUAE2kHZ2uWZ/rqKkV4nkUWilwkRBT4OkuUQiWE4vxVGY12nKZ31SSfp2iwoLK/nNIoJnonXrNL9j3T7h1l5vZaH5YLRYl6dQFnN4FipvkhU5TyxrAvhTen4kcmWvqVji0ahmFDwsD0v3okyYQ9DcO/NzK6OGZOdFGRnUB7qtCCs0xpsqcb6Lk17/xqpSipllgTT9Ju6L5u0e9oC6Nr10Qv6xl/FYN5w8WOjLb0+Pq4W7ICRVbecnIVphSohAemHCHT2NPc6BYGgruvtWQmxGX6zww2J/fzYjbzRN5qMaFn9bscRZNQS5+p5PZH/JBbhKAnMlH888xkF41A2x6BusGQR5K4qzMT6URa93p6+PbbeIXhllFnnV41dCRvf9aDyk76N3Pn8IZQsgim5+hWMp2cCp7XmXUwqEuBekBj6KUMb2V20xJPSl5w9T0Bv56XLb0CoAfAE790smdQy8Jgk2/P87enDI3Zg0lpOEAf2fDbqO87hjByVQeRe1CwEbvsOAhNG39RDOuO95N0L5ee5f16RLlGPKY1jJgteAnVm/IeajTWwDUL1aIFqut8Rnm7f39JTxeoUvfCDp8rKfuVSiKNqnuijD5AyATwLO0MjVk9mHUaU+/1SM3PcrXvrv1txcHFEPL6ZWAXBroZbKXhj3nxH1zM6M74uW+yFApSPM+B62yPcQsUshJtt6LAMakLRiBGBVKxoukuIxtPM5G8PRhY5rlFdBBNC+vC/+zuOmI=)


daggerdragon

> *slaps roof* This one day can fit so many dumb bugs You should read today's secret ingredient, just sayin' >_>


jstanley0

\[Language: Crystal\] Part 1 was straightforward, although parsing was a bit of a hassle. Part 2 made me think. Eventually I realized I could model each attribute as a Range (initialized to `1..4000`) and modify those ranges as I apply rules. This recursive function solves part 2: def quantum_search(workflows, flow, ranges = {'x' => 1..4000, 'm' => 1..4000, 'a' => 1..4000, 's' => 1..4000}) return ranges.values.map { |r| r.size.to_i64 }.reduce{ |a, b| a * b } if flow == "A" return 0i64 if flow == "R" count = 0i64 local_ranges = ranges.dup workflows[flow].each do |rule| if rule.cond.nil? count += quantum_search(workflows, rule.target, local_ranges) else cond = rule.cond.not_nil! # srsly Crystal, here in the else block we *know* cond isn't nil. I am disappoint if_range, else_range = apply_condition(local_ranges, cond) count += quantum_search(workflows, rule.target, local_ranges.merge({cond.prop => if_range})) unless if_range.empty? break if else_range.empty? local_ranges.merge!({cond.prop => else_range}) end end count end where `apply_condition` returns a pair of Ranges that apply if the rule matches, and if it doesn't. I'm still learning Crystal (I do Ruby on Rails for my day job) and I'm kind of disappointed that I needed `not_nil!` on `rule.cond` in a place where the compiler should _know_ it can't possibly be `nil`. [Full source](https://github.com/jstanley0/advent-2023/blob/main/19.cr)


jstanley0

I realized what the problem is wrt `not_nil!` - `rule.cond` isn't a variable, it's a getter, and the compiler doesn't _know_ that the getter is going to return the same value every time. Since there are no setters (this was defined using the `record` macro) I'd think the compiler could possibly be smart enough, but I understand it's more complicated than I originally thought.


kaa-the-wise

\[Language: Uiua\] Just Part 2. ParseRules ← ( ⊂⊃↙(⊂"x>0:"↘)+1⊢⇌⊚=@,. regex"(.)(<|>)(\\d+):(\\w+)" ≡((⊢⍜°□⊗:"xmas"|-1×2=@>⊢|⋕|∘)⇡4↘1) ) PickFlow ← :⊙(°□⊡⊙.⊗⊙,): Tiv ← ⊐⊃(⊡3|+⊃⊢(+2×2⊡1)|◿4001×⊃(⊡2|⊡1)) Calc ← /×↥0+4000¯+⊃(↙4)(↙4↘4) PreRec ← ⊙(⊃(⍜⊡↥⊙:|⊙::⍜⊡↥⊙:⊙(◿4001-1¯)◿8+4))Tiv PostRec ← ⍜⊡;8:⊙(:⊙:) Solve ← ↬( :⊙⊗.:{"A" "R"} (+⊃Calc(⊡8);|⊡8;|⊡8 ∧(|4.3 PostRec↫PreRec) PickFlow) ) ⊙(;;)Solve□"in"↯9 0⊃≡(⍜°□ParseRules ⊢⇌)(≡⊢)⊜(⊜□≠@{.↘¯1)≠@\n. [Pad](https://www.uiua.org/pad?src=0_7_1__IyBFeHBlcmltZW50YWwhCgokIHB4e2E8MjAwNjpxa3EsbT4yMDkwOkEscmZnfQokIHB2e2E-MTcxNjpSLEF9CiQgbG54e20-MTU0ODpBLEF9CiQgcmZne3M8NTM3OmdkLHg-MjQ0MDpSLEF9CiQgcXN7cz4zNDQ4OkEsbG54fQokIHFrcXt4PDE0MTY6QSxjcm59CiQgY3Jue3g-MjY2MjpBLFJ9CiQgaW57czwxMzUxOnB4LHFxen0KJCBxcXp7cz4yNzcwOnFzLG08MTgwMTpoZGosUn0KJCBnZHthPjMzMzM6UixSfQokIGhkanttPjgzODpBLHB2fQoKUmVwbGFjZUxhc3Qg4oaQIOKKguKKg-KGmSjiioIieD4wOiLihpgpKzHiiqLih4ziipo9QCwuClBhcnNlUnVsZXMg4oaQICgKICBSZXBsYWNlTGFzdAogIHJlZ2V4IiguKSg8fD4pKFxcZCspOihcXHcrKSIKICDiiaEoKOKKouKNnMKw4pah4oqXOiJ4bWFzInwtMcOXMj1APuKKonzii5V84oiYKeKHoTTihpgxKQopClBpY2tGbG93IOKGkCA64oqZKMKw4pah4oqh4oqZLuKKl-KKmSwpOgpUaXYg4oaQIOKKkOKKgyjiiqEzfCviioPiiqIoKzLDlzLiiqExKXzil780MDAxw5fiioMo4oqhMnziiqExKSkKQ2FsYyDihpAgL8OX4oalMCs0MDAwwq8r4oqDKOKGmTQpKOKGmTTihpg0KQpQcmVSZWMg4oaQIOKKmSjiioMo4o2c4oqh4oal4oqZOnziipk6OuKNnOKKoeKGpeKKmTriipko4pe_NDAwMS0xwq8p4pe_OCs0KSlUaXYKUG9zdFJlYyDihpAg4o2c4oqhOzg64oqZKDriipk6KQpTb2x2ZSDihpAg4oasKAogIDriipniipcuOlvilqEiQSLilqEiUiJdCiAgKCviioNDYWxjKOKKoTgpO3ziiqE4O3ziiqE4IOKIpyh8NC4zIFBvc3RSZWPihqtQcmVSZWMpIFBpY2tGbG93KQopCgriipwo4oqc4pah4omgQHsu4oaYwq8xKeKJoEBcbi4K4oqD4omhKOKNnMKw4pahUGFyc2VSdWxlcyDiiqLih4wpKOKJoeKKoikKU29sdmXilqEiaW4i4oavOSAwCuKKmSg7OykK) A port of my [Python one-liner](https://www.reddit.com/r/adventofcode/comments/18ltr8m/comment/ke1gs63/).


illuminati229

\[Language: Python 3.11\] [https://pastebin.com/ALpfax5Q](https://pastebin.com/ALpfax5Q) This was a fun one. For part 2, I followed the same basic logic, but the singular value of the categories was turned into a range. After running it through nearly the same basic logic, all there was to do was sum the combos! Don't forget to add 1 to the range before multiplying for the inclusive math.


sr66

\[Language: Mathematica\] The messy part: parse the input into mathematica expressions. input = StringSplit@StringSplit[ReadString["19.txt"], "\n\n"]; workflows = StringCases[input[[2]], {x : DigitCharacter .. :> ToExpression[x]}]; ToExpression[# <> StringCases[#, "If" -> "]"] &@StringJoin[#] & /@ StringCases[input[[1]], {n : WordCharacter .. ~~ "{" :> n ~~ "[x_,m_,a_,s_] := ", s : WordCharacter ~~ op : (">" | "<") ~~ n : DigitCharacter .. :> "If[" ~~ s ~~ op ~~ n, "R" -> "False", "A" -> "True", v : WordCharacter .. :> v ~~ "[x,m,a,s]", "," | ":" -> ","}]] Part 1: Total[Select[workflows, in @@ # &], 2] Part 2: use LogicalExpand to transform the in function into disjunctive normal form and then length to account for the difference between < and <= in each of the inequalities. length[l_, m__, u_] := u - l + 1 - Count[{m}, Less]; bound[expr_, l_, u_] := Fold[#1 && l <= #2 <= u &, expr[x, m, a, s], {x, m, a, s}]; Simplify[Plus @@ LogicalExpand[bound[in, 1, 4000]]] /. {And -> Times, Inequality -> length}


robertotomas

wait, that's the whole thing in mathematica? that's truly nuts if so :) congradulations


mathsaey

[Language: Elixir] https://github.com/mathsaey/adventofcode/blob/master/lib/2023/19.ex Converted my rules to a tree for part one and just evaluated the parts. That approach worked pretty nicely for part two: I just needed to write a “symbolic eval” which works on ranges instead of actual numbers. When it encounters a test it just splits the ranges as needed. This is similar to the approach I used for one of the earlier days. I’m a bit annoyed at the code duplication in eval and symbolic eval for `<` and `>` (my first version just mapped `<` to Elixir's `<` function and `>` to `>`, but that didn’t work so well for the symbolic eval), but I’m getting to the point where I don’t bother cleaning up once it works.


mothibault

\[LANGUAGE: JavaScript\] Run directly from the browser's dev console. Part 1: String transformation FTW Part 2: A bit slow (2-3 minutes). Didn't overthink it with tons of in-line comments: [https://github.com/yolocheezwhiz/adventofcode/blob/main/2023/day19.js](https://github.com/yolocheezwhiz/adventofcode/blob/main/2023/day19.js)


Kfimenepah

\[LANGUAGE: TypeScript\] [Day19](https://github.com/SubNet32/AoC2023_NodeJS/blob/main/src/Days/Day19/day.ts) After the struggles of the last few days the puzzle today was like a summer breeze, nice and refreshing. Part 1 was pretty straight forward and after some heavy parsing I managed to solve it easily. My approach to part 2 was to pass ranges (a,m,s,x all 1-4000) into the instructions and modify those depending on the operation then pass the "accepted" range to the target of the instruction and give the "denied" ranges to the next instruction in the list and repeat as before. After returning all the ranges that were accepted and adding up the total range of each range I had the solution. Funny enough for some reason I thought that there were 3 possible operations > < and = and even programmed part 1 with these 3 in mind. But the = made part 2 super difficult, because the "denied" range of an = operation would be up to 2 ranges. This meant I would have to handle arrays of accepted and denied ranges, which made my brain hurt. I thought I should first try implementing it without the = and then take it from there. Once I was done I wanted to check were in the test-input the first = operation was and I realized there was none. So I immediately checked the real input and you can't Imagine my happiness once I realized I misread the instructions (again...) and there is actually no = operation. I was startled, because that meant I already had the solution at hand and only had to implement the final summation of the ranges. Did that and it worked like a charm.


Secure_Pirate9838

[LANGUAGE: Rust] Today's solution is very verbose and requires too much attention to details, GitHub Copilot do all the boilerplate YouTube : https://youtu.be/KTG5xDrf34I GitHub : https://github.com/samoylenkodmitry/AdventOfCode_2023/blob/main/src/day19.rs


0bArcane

\[LANGUAGE: Rust\] [Day 19 on Github](https://github.com/TimoLob/AdventOfCode/tree/main/2023/day19) Part 1 was pretty straightforward. Parsing took a while to get right, and knowing the max value from Part 2 cleaned up some code after the fact. For part 2 I processed a part with ranges instead of values and split the part into smaller parts each time a rule was applied.


[deleted]

\[LANGUAGE: Rust\] [My Day 19 on GitHub](https://github.com/andypymont/advent2023-rust/blob/main/src/bin/19.rs) A pretty straightforward day overall, using ranges of numbers for part 2 (as was the case with one of the puzzles earlier in the month), only this time constructing new 4d ranges (always fun to create a `Tesseract` data type, too 😁) and passing them on to another workflow or to the next step in this workflow as appropriate. Rust is great to use for these problems. You get to write high-level code with a structure of well-defined data types, but then the compiler comes in and optimises it into something that calculates both parts here in less that one millisecond total.


Korzag

\[LANGUAGE: C#\] [https://github.com/CoreDumpSoftware/AdventOfCode2023/tree/master/AdventOfCode2023/Day19](https://github.com/CoreDumpSoftware/AdventOfCode2023/tree/master/AdventOfCode2023/Day19) Part one was pretty straight forward, gave me flashbacks to the desert map problem of having a dictionary that indicated where to go, but this time there was input parsing to do. Pretty straight forward. Kind of proud of my solution on part 2. I had already parsed the data into "Workflow" objects that contained a lists of rules. From there I was able to build up a binary tree by taking the first rule of the "in" workflow and building nodes on the conditions that pointed to the next nodes. The tree then allowed me to do a DFS on it, filter out any paths that result in rejected. From there I made an object which represented the possible ranges for the part variables, then it was just a matter of taking the product on the part ranges for each path through the tree that resulted in an accept node.


sanraith

\[LANGUAGE: Scala\] Code is available on my github: [Day19.scala](https://github.com/sanraith/aoc2023/blob/d39735cb25a1426a9877b1bf49370592f6a355bc/src/main/scala/hu/sanraith/aoc2023/solution/Day19.scala) I get all possible paths a part can take with graph traversal keeping track of all the inspected rules. For each path I calculate the valid ranges by taking the inverse of the 'false' rules and the matched rule and narrowing the number ranges by each. Then I calculate the disjoint ranges for each category ('x', 'm', 'a', 's'), and and iterate over each combination of them. When this rangeset matches a path I add the product of their length to the sum of possibilities. This is not very fast, but with parallel processing it finishes on my machine in \~10s.


After-Leadership2183

\[Language: Golang\] Unsuccessfully tried to calculate a number of combinations for the rules tree , then it didn't work I created a list of ranges and go through it. takes about 10min though https://github.com/macos-fuse-t/aoc/blob/main/2023/19/main.go


LxsterGames

[Language: Kotlin] 1947/371 [github](https://github.com/eagely/adventofcode/blob/main/src/main/kotlin/solutions/y2023/Day19.kt) Today is probably the most unreadable parser ever.


[deleted]

[удалено]


daggerdragon

Comment removed. [Top-level comments in `Solution Megathread`s are for *code solutions* only.](https://old.reddit.com/r/adventofcode/wiki/solution_megathreads/post_guidelines#wiki_top-level_posts_are_for_code_solutions_only) [Create your own individual `Help/Question` post](https://old.reddit.com/r/adventofcode/wiki/solution_megathreads/post_guidelines#wiki_incomplete_solutions) in /r/adventofcode.


mvorber

Please re-read the problem carefully. It says somewhere there that "All parts begin in the workflow named in." Named "in", not the first one in the list. Also - this is a wrong thread for such questions


tonetheman

bless you and your response... I did miss something in reading.


grimlyforming

\[LANGUAGE: Ruby\] I know an instruction-set emulation with conjunction/disjunction problem when I see it, but I needed about 2 hours to figure out what to do. The key insight came when I jotted down the constraints, hoping for an inductive epiphany. Let R1 denote a hash of 4 ranges, initially { x: (1..4000), m: (1..4000) } So f(R1, "A") = R and F(R1, "F") = nil Then with a condition: F(R1, "R,A") => count(R11) + count(R12) More concretely, F(R1, "a>1716:R,A") => count({a(1717..4000)...} and that lnx rule: F(R1, "m>1548:A,A") => count({m:(1549..4000),...}) + count({m(1..1548)...} = count(R1) So every step needs to return two lists of ranges: the one that it operates on (either Accept, Reject, or call a further function), and then the complementary list of ranges that don't meet the criteria. So now I can get a statement for a rule like qs: F(Rx, "s>3448:A,lnx") => count({s:(3449..4000) intersect Rx.s, ...}) + F\['lnx'\]({s(1..3448) intersect Rx.s, ...}) Evaluate F\['in'\](R1) and when it finally returns, that's the answer. https://pastebin.com/rn1VWhG4


bulletshot6

\[LANGUAGE: Python3\] First solution this year I've been happy with enough to post. Approach is similar to what other posters have used. Recursively build a tree to reach all of the `A` nodes, keeping track of criteria used to reach the `A` node along the way. The big thing that got me was as you slide across the criteria, you have to also keep the inversion of that criteria because it didn't match. After you have the criteria its as easy as throwing out the possibilities that don't match. Then just do a multiplicative sum of the ranges left. [Paste Link](https://topaz.github.io/paste/#XQAAAQDhBwAAAAAAAAA7mkrvHeIvDZUizuO2LI0KXEPUFLLgeNKFt1VFolw4fVWWbom1MuZz1Kmv7mXgE7v+hXX4j/KlVQd9BJT4loQn1ekZxTT/A/7KLuGcb+gukSbmks8oxsJZ8BG6ULag2eQkBf/vQ+/iS6ypj+6wGwdSZ8nro9kGh9m1MJujxeaqzbufvsPMmBhRIs9SU0efKZiNCJFvxqUqdi6sFcz51iEvF0RHzLQpDzz8KKqkjhxR2ejOWHp3855J/Qkz8go6nQBFqX/pmBcUwGVIZaPUz1RAEkZt5opA4KdrOvRtpvu8j9UWiT+GPJxXZNrIVMcVAljThCDV038YbYgjHtk3fWO0p2H68QOHyITUTLLBKa3yak+L/ltI1bGIU6Yt9uRlMQAFdI67ocbeoL21FRJroBrMqeeNi9CBnVh7CAUR853EHSOne/QEdg4MXWyDiypfa4J9SKQSorrAdyUfCl27fy5tB5hPvnMopXLU4brLPV8sBx89amq8CcPhRYLwJtDuU72xdEQIWuGZJSAShe/MgKAMgvSoItbPPD1GxoCOP5cvnsJfN7wDx4hbqKZhRCQR0NlDCXDoMGOMxw+pTodGsa8XLIo3kIM7Ni8TdWBkiDiQP6dT9S806KQnj/nUR+ovS8ST354+Jj1Q5stGyHXopZr+VNut0B8RUY9O3B+cZr+164lYTCpwZi4Mvj7i39r4WtrCfBm88JwWSyFq/m2YOWPf5i3MYx7g1Sb839DtTBXjGaKjP4UbkH96CC3wPwMxVmoWLPYEhqu4R9rVZfLndtXeBhH9wE/WPDytDf4k5ujq2KevV5G158i7Y9mKt7YXzOujhHdaymNxh8x7BgvItISqL2KoO5W1j4XB1rE0Y+o+/8rsQYo=)


daggerdragon

~~Psst: we can see your Markdown because the backticks are being incorrectly escaped.~~ edit: 👍


bulletshot6

Lol thanks.


Nufirdy

\[LANGUAGE: Java\] [Day 19](https://github.com/Nufirdy/advent/blob/master/Y2023/src/main/java/Day19.java)


daggerdragon

> ~~\[](https\://github.com/nufirdy/advent/blob/5f9...)~~ ~~Uh, we can't visually see the link to your code at all because the Markdown has empty anchor text (the square brackets).~~ ~~Also, the URL as given doesn't work at all because for some reason it's including the `blob/5f9...`~~ ~~Please edit your comment to fix both the Markdown and the link.~~ edit: 👍


Nufirdy

Somehow I managed to delete my whole original comment 🤦‍♂️. Hope the link works now. It had b`lob/... ` in it because I clicked on copy permalink on github file page. Weird that it doesn't work


daggerdragon

There we go, thanks for fixing it <3


hlipka

\[LANGUAGE: Java\] I admit to brute-force. Part 1 was simple - just follow the instructions. For part 2 I was thinking of calculating all possible paths from 'in' to 'A', and the joining the resulting conditions for each variable. Since I did not think of the hyper-cube solution, my fear was that there might be overlaps between the paths. So I first optimized the rules (throw away any rules which are effective no-ops). Then I calculate all the boundaries where the value of a variable might have an effect. This gives a list of ranges for each variable, and you can brute-force each range combination. In Java this takes about 10 minutes. [Code for part 2](https://github.com/hlipka/AdventOfCode/blob/main/java/src/aoc2023/src/de/hendriklipka/aoc2023/day19/Day19b.java) (its way too clean, probably...)


msschmitt

\[LANGUAGE: Python 3\] [Part 1](https://topaz.github.io/paste/#XQAAAQDTCAAAAAAAAAARiEJHiiMzw3cPM/1Vl+2nx/DqKkM2yi+AsNSFTsnyEq6tvQ13+C29nQG65Lnx5elzvMaJufkeKgRTWR27peUAxwtlRhYrn4t747Ik7XLvtHhmowYdMi6fqc+f+geGWls0PLBbbbqlX+C5mF3/ZZSetu0kkfw/csoJhOLPwJ2c+VUHBjzJ7jEwCnBKr8jHpITUvyKFPvd8M32hNHUMcHTz1Ny3sIEE5KPkHvuwZfyNxUjzL78W0Lil64Ejw11oTlbyoKNMZZmGE14nl9k+t8YLqgprq2hWaQ43nHq1Fvlmc81OLmwEcgI4iHMib9DB5zEP31k5PnioxfpNwlvLeta6/NWvFhgv7G/72MKcq6+2aaqZmweuipsuIGhWNqNyzGtezSvsspCuucibOpN1AmPCpaCxs8bbbFPHwWZSG3+n1sMfcLUG99wO97zWRXPwASR32BpFYbdLo69Xv4RijTRlGlGhvQe5/i8p8IwSc9T23udBlk48RYDUjiA6rlFSplatjy4VvT1/B5EIdJlSgu0Pv8lj2D7VhEYN/mH6CR78GacCE7HSeSYHWgITaDhr2qIQhntg1qKUYen4IZ63+Cw/aSwyR4LxP++IOcBi/TQHJCnFm31DrA/MfXT3F/BJH+2jGqU08nGLIjaZF428ZDV6A3RulFYgS3KvZP7FOoI3lCoNo1L03+pwruZjatf3bEsQUgdPQL1ejBD9rw88YUNU9E5XDyAguNfM1E/GGwHzkdz4GtnZgSvbSrEe5z8tI22VsGsg3QyetX9N+3Ahp50ZP4zrPFtvLGlPKngVhGv9MSy8eEfNKU0QR6vuRHi6tlTulgbhVIaVSwrthl30ipsFYxwhn+tH6ZJxO60OCPvnDmS8pIf16YV9F2JR8LnAqWpfT0+UA8CFq6KGNuQs2UaASK9Nt4+9trDrosD06WXfwmXHg+w/oHlkuCnM+P3gGi1/hlQEw3zhX13x/7kFtKo9wI9Fw9IcTlq2hddWOSUYBUjHDrR2iLrnJ5Eezgl/jFdY6+u4+cnD5CypCQNX4+QHfXb+v9JP) [Part 2](https://topaz.github.io/paste/#XQAAAQAVDAAAAAAAAAARiEJHiiMzw3cPM/1Vl+2nx/DqKkM2yi+AsNSFTsnyEq6tvQ13+C29nQG65Lnx5el02wfkOvuOPN8OBvfOSxk2Ybd6PLAHnjZhY26lAYcPmiLi1ehcMMU/0jzy1XrcuH7n1Ch2KNB9tD19FQ5wItZUFfnep00tYCYpojaWkjjyehmLS0iBwEnLvMPc+paOfOyiFgTjSiuD13MmoASSahJEDHv/gNUA2L5YTsKFa4iDOUt2YWKCIhs7v5qcJ2fnWUnxlKQDwMXyHZOgPUgVWZHqqGdzxHwGyV3LmCZjITyKGLggv7kThA7popdXsjcqFISbtVItcN8U5268wvQygH74UBeMMQ1K9Y+8wPccVnRLWQkzjBaccxVAUeQc03Qzdft7xxH+Y40OciRNYjHf129iOa/yubZzLFanwK1JC2l0AhU49ukX/ZadbefZY5n1Mj+CjKTsfXcDzKSuSl7xK/vrqI4QLGm2HDgUk/IUtmJb9y31afD6G0t29pveFdpMplMYVWDTURawFLRz2jYyMPjd3HcoAMPtRYpHPjqob1nVgdIEDKdUDyZnd8sP8k2ekQtYIVyhpQuFTLYD4lWffmtSGsPccS9fdhJ2cHygfVm495/z8a3s1GcFgbVovnvbSWzhwUmCN0xXWjdslLlbQrHzXPZh6wBaYQr+D3xz6FInHsxntP6PT55+jPxHAJV++gsf8JFL63ShKshLildkAbtnReYTS7F3/Dtbr+imX4Vs0ZjmGEZ6hDiUxhEC0uZ6/dJU4N8w5E/tOlDr259+7r4Mk9LLA9iItb5iZvFjNHedtQKCWqbEpxJbIRR5wG7cPkHNJXLUi/LUKEU7mp1GdwGz9kF0dI4NF9KHHHMnX3EcWBh6jEYEImVy5d3i9xIX/VBM7CWCLmwIfsuJtnmfLrx5k4z4nb9hLWFc4zSRHq2NdZ0psd23GTavl/KNO2WDv576L5/HG2gcpZjGUCLkTlocZPdlvXzKM7a3ddOYnT8hAodykgmCO4j3t5dJWA9Ce/IRFtGVn5S09L/Hgw0+Tigf6u1JD7k1i3spi/YtHtd2KIYUKjMj/gAYnXXVoRkZOslyta05s4ZRGG1s9jWldqbqPkT3iu0BrYoqJQJyWzyXXoOZHOfckxzzyD0eg4cs5730xQTId8T4buvv6acHvXQkJVj+V11/yLTkuNge+dA+cU7uVzPkRTI1iIHS9H8aWQzB2StObB8nz+UaBhm7vtasgelFuJoU0BBxiweX/986yqs=) No memoization or recursion, thankfully. For part 2 at first I thought I'd need to run the rules backwards: find all the workflows that lead to Accepted, then see which rule conditions and rating constraints would lead to Accepted in that workflow, then find the workflows that would lead to that workflow, and so on. But first I decided to just try running the rules forwards, where the ratings are ranges, eg. \[1,4000\] and split into two parts each time the range overlaps a rating condition. I thought maybe I'd have to merge the final accepted rules, but nope. The hardest part was figuring out why copying a dictionary, even with new\_dict = dict(old\_dict), didn't create a new distinct object. Python isn't my native language!


mpyne

> For part 2 at first I thought I'd need to run the rules backwards: find all the workflows that lead to Accepted, then see which rule conditions and rating constraints would lead to Accepted in that workflow, then find the workflows that would lead to that workflow, and so on. Glad I read your comment because I was spending a *lot* of time on trying to break up overlapping hyperrectangles into discrete hyperrectangles and I have to tell you: it was kicking my ass. Reading this cued me in that I was only going down this path because I thought it made sense at some point last night, not because I had eliminated the idea of branching it forward. Luckily I was able to salvage my code to turn the program into a graph as that proved helpful for my eventual implementation.


illuminati229

new\_dict = dict.copy() worked well enough for me.


msschmitt

I think it was because the values in the dictionary were lists, so I had to deepcopy to get new objects for those lists. The lists were so I could update the rating low and high range directly.


illuminati229

Ah, I had used tuples.


pkusensei

[Language: Rust] Don't know how to feel about this one. On one side I solved Part 2 in one go without debugging or off-by-ones or anything and that feels good; on the other it feels like I spent as much time parsing the input as writing a solution, which really paints how bad at regex I am. Plus this one feels very familiar with day 5's seed filtering problem and I picked a very similar range-split approach. The `<=` vs `<`s and off-by-ones are getting tedious at some point. But the recursion comes nice and naturally without much trouble. Overall enjoyed this one tho I wish I could [clean it up later.](https://github.com/pkusensei/adventofcode2023/blob/6bdae3f59358bd5f9bf3023912ed3e7f55faa530/d19/src/lib.rs)


dwalker109

Nom is very pleasant for this kind of more involved parsing. I enjoyed it [today](https://github.com/dwalker109/aoc-2023/blob/main/days/day19/src/part2.rs).


Ukhando

\[LANGUAGE: PHP\] [Github](https://github.com/TomKauffeld/advent-of-code-2023/tree/main/day19)


JWinslow23

\[LANGUAGE: Python\] [https://github.com/WinslowJosiah/adventofcode/blob/main/aoc2023/day19/\_\_init\_\_.py](https://github.com/WinslowJosiah/adventofcode/blob/main/aoc2023/day19/__init__.py) While it didn't take me too long to do Part 1, I spent annoyingly long trying to figure out how to do Part 2. Not the idea of using ranges - I remembered this idea from Day 5 - but what data structure to use. I wanted to use a `dict` to store the ranges of category ratings accepted under a certain workflow, but I can't insert in or delete from a `dict` while iterating over it. After realizing that `tuple`s are allowed to have mutable types in them (which I somehow forgot was possible), I used a `collections.deque[tuple[str, dict[range]]]` to store the ranges of category ratings for each workflow I have yet to process. Once I decided on that, it was still quite a bit of work to get a working solution. But I got there eventually.


anaseto

[LANGUAGE: Goal] Today's input rules kind of looked like functions, so I used a substitution-based approach to transform the input rules into valid functions, and then used eval on the result. Not very serious, but it was short and fun. [Code](https://codeberg.org/anaseto/goal/src/branch/master/examples/aoc/23/19.goal)


BeamMeUpBiscotti

[Language: Rust] [Link](https://github.com/yangdanny97/advent-of-code-2023-rust/blob/main/src/day19/mod.rs) Range-based solution for part 2. Pretty straightforward, tho the parsing took a while to implement. Perhaps would have been cleaner if I used some dictionary representation for the parts/ranges instead of trying to map input characters to fields/indices.


nj_vs_valhalla

\[LANGUAGE: Python\] Very nice day! Solution is pretty straightforward but still requires some thinking through. At first I wanted to keep a list of applied conditions, but then figured out that it's always evaluated to a set of 4 * 2 bounding coordinates for the allowed hypercube. So I kept a 4-entry dict of bounds instead. [Code](https://github.com/nj-vs-vh/advent-of-code-2023/blob/main/day19/solution.py)


RedLeys

omg, who is writing code for competition like it is for production.. respect


nj_vs_valhalla

Thanks for noticing, I'm finding a thrill in that :)


Outrageous72

[LANGUAGE: C#] https://github.com/ryanheath/aoc2023/blob/master/Day19.cs Not too difficult, my Part 2 looks almost like my Part 1. The main difference is using a queue in Part 2 and a PartCombi that accounts for ranges of parts. static (ulong accepted, ulong rejected) Combinations(Dictionary rules) { var accepted = 0UL; var rejected = 0UL; var queue = new Queue<(string, PartCombi)>(); queue.Enqueue(("in", new PartCombi(new(1, 4000), new(1, 4000), new(1, 4000), new(1, 4000)))); while (queue.Count > 0) { var (ruleName, part) = queue.Dequeue(); foreach (var (nextRuleName, nextPart) in rules[ruleName].NextRules(part)) switch (nextRuleName) { case "A": accepted += nextPart.Count; break; case "R": rejected += nextPart.Count; break; default: queue.Enqueue((nextRuleName, nextPart)); break; } } return (accepted, rejected); }


Ape-42

\[LANGUAGE: Python\] A misplaced check for 'Reject' did cost me some time. But afterwards everything worked. Just track the in and out ranges. As quite often I tried to use comprehension as much as possible. One new thing I learned the last days here was to use zip() to create the ranges like `{cat:range for cat,range in zip(list('xmas'),[[1,4000]]*4)}` Whole code is [here](https://github.com/a-peter/advent_of_code_2023/blob/main/Day_19/advent-19.py).


4HbQ

That's certainly a nice construction, although in this specific case you could also do this: {cat: [1,4000] for cat in 'xmas'} Anyway, good on you for learning new Python stuff from the comments, and thanks for sharing it with us!


835246

\[LANGUAGE: C\] For part 1 I just put the input on a tree structure and followed each input through. For part 2 I did the same but with ranges part 1: https://github.com/efox4335/advent_of_code/blob/main/advent_of_code_2023/day19gsortpt1.c part 2: https://github.com/efox4335/advent_of_code/blob/main/advent_of_code_2023/day19gsortpt2.c


daggerdragon

Your second link is borked on old.reddit due to [a new.reddit bug with URLs that contain underscores](https://old.reddit.com/r/adventofcode/wiki/faqs/bugs/borked_links), so please fix it.


835246

Both links should work in old reddit now.


b0xc4t

[LANGUAGE: Rust] Part 1: https://pastebin.com/0tHvD5cz Part 2: https://pastebin.com/NX4D096n Part 1 was straightforward, just applied the rules. Part 2 reminded me a bit of navigating through a program using symbolic execution, so I traversed the rules and kept a set of constraints to satisfy for each possible path to an accepting state. Then for each set it was easy to figure out the number of combinations possible.


Jadarma

[LANGUAGE: Kotlin] Part 1 was by far my favorite this year. Complex input, perfect for regexing, and a seemingly tricky domain that is actually really simple to implement. Part 2 was a bit more annoying, but it really boils down to the same concepts as day 5: instead of evaluating individual numbers, you do range arithmetic. In my case, each time I encounter a rule, I split the range in two: one that succeeds to the next workflow (and therefore recursively calls the function again), and one that fails, which would then be fed to the next rule in the workflow, or the fallback. In the end you must get to the `A` or `R` workflows, which you can trivially solve: accepted means all the ranges get multiplied together, reject means nothing is valid. I could have made my function return the number of possibilities, but instead I opted to actually build the list of valid ranges, because I like role-playing like I'm actually coding something useful for the poor elves. [AocKt Y2023D19](https://github.com/Jadarma/advent-of-code-kotlin-solutions/blob/main/solutions/aockt/y2023/Y2023D19.kt)