this post was submitted on 01 Dec 2023
17 points (100.0% liked)

NotAwfulTech

385 readers
2 users here now

a community for posting cool tech news you don’t want to sneer at

non-awfulness of tech is not required or else we wouldn’t have any posts

founded 1 year ago
MODERATORS
 

Rules: no spoilers.

The other rules are made up as we go along.

Share code by link to a forge, home page, pastebin (Eric Wastl has one here) or code section in a comment.

(page 2) 50 comments
sorted by: hot top controversial new old
[–] [email protected] 3 points 1 year ago
[–] [email protected] 3 points 1 year ago* (last edited 1 year ago) (6 children)

Day 5: If You Give A Seed A Fertilizer

https://adventofcode.com/2023/day/5

Leaderboard completion time: 26m37s, so it's the toughest problem this year so far.

load more comments (6 replies)
[–] [email protected] 3 points 1 year ago* (last edited 1 year ago) (1 children)

Day 6: Wait For It

https://adventofcode.com/2023/day/6

Alternate spoiler name - for part 2~~Do you remember highschool algebra?~~ Can you (or your compiler) remember highschool algebra fast enough to beat out a naïve implementation?

[–] [email protected] 3 points 1 year ago

nice cleanser after yesterday

spoilerit would have taken me longer to figure out the algebra than to just mush the inputs together and get the solution that way (16s runtime)

[–] [email protected] 3 points 1 year ago* (last edited 1 year ago) (1 children)

I have come up with a more horrifying way to solve Day 1 Part 1 involving C++ implementation defined behavior, but it requires launching two subprocesses for every test case so I'm not sure I have the motivation right now.

Proof of concept: https://www.animeprincess.net/blog/?p=60

load more comments (1 replies)
[–] [email protected] 3 points 1 year ago (1 children)

Day 7: Camel Cards

https://adventofcode.com/2023/day/7

So far, my favorite puzzle. Challenging but fair. Also plays to Perl's strengths.

Leaderboard completion time: 16 minutes flat, so not a pushover.

[–] [email protected] 3 points 1 year ago* (last edited 1 year ago) (7 children)

Day 8: Haunted Wasteland

https://adventofcode.com/2023/day/8

Not so easy at least for part two.

spoilerDo you remember high school math, like lowest common multiple, part 2 electric boogaloo.

load more comments (7 replies)
[–] [email protected] 3 points 1 year ago (1 children)

Day 9: Mirage Maintenance

My solution: https://github.com/gustafe/aoc2023/blob/main/d09-Mirage-Maintenance.pl

discussionWhat can I say. Shockingly simple.

I just literally followed the instructions, and got a solution in 20ms. This despite literally creating each intermediate array yet only using the ends. I'm sure I used way to much memory but you know? I'm using a $5/mo VPS for everything and unless I'm barking totally up the wrong tree I've never exceeded its memory limits.

On the subreddit I see people discussing recursion and "dynamic programming" (which is an empty signifier imho) but I really don't see the need, unless you wanna be "elegant"

[–] [email protected] 3 points 1 year ago (1 children)

spoilerDP to me is when you use memoisation and sometimes recursion and you want to feel smarter about what you did.

I also struggle to think of the need for DP, even in a more “elegant” approach. Maybe if you wanted to do an O(n) memory solution instead of n^2, or something. Not saying this out of derision. I do like looking at elegant code, sometimes you learn something.

I feel like there’s an unreadable Perl one line solution to this problem, wanna give that a go, @gerikson?

[–] [email protected] 3 points 1 year ago (2 children)

spoilerPart 2 only, but Part 1 is very similar.

#!/usr/bin/env jq -n -R -f
[
  # For each line, get numbers eg: [ [1,2,3] ]
  inputs / " " | map(tonumber) | [ . ] |

  # Until latest row is all zeroes
  until (.[-1] | [ .[] == 0] | all;
   . += [
     # Add next row, where for element(i) = prev(i+1) - prev(i)
     [ .[-1][1:] , .[-1][0:-1] ] | transpose | map(.[0] - .[1])
    ]
  )
  # Get extrapolated previous element for first row
  |  [ .[][0] ] | reverse | reduce .[] as $i (0; $i - . )
]

# Output sum of extapolations for all lines
| add

I'm pretty sure you could make this one line and unreadable ^^.

[–] [email protected] 3 points 1 year ago

Now this is content

[–] [email protected] 3 points 1 year ago

Here's where I landed in dart

no comments

d9(bool s) {
  print(getLines().fold(0, (p, e) {
    int pre(List h, bool s) {
      return h.every((e) => e == 0)
          ? 0
          : (pre(List.generate(h.length - 1, (i) => h[i + 1] - h[i]), s)) *
                  (s ? -1 : 1) +
              (s ? h.first : h.last);
    }

    return p + pre(stois(e), s);
  }));
}

[–] [email protected] 3 points 1 year ago* (last edited 1 year ago) (18 children)

Starting a new comment thread for my solutions to 10-19. Double digits, baby! Code here: https://github.com/Fluxward/aoc2023/

[–] [email protected] 3 points 1 year ago (3 children)

a,b, not much to sayThe hardest part has finding the right dart ascii library to use (by default dart treats everything as UTF-16, which is horrible for this sort of thing) and the right data structure (linked hash map, which is a map that remembers insertion order.)

load more comments (3 replies)
[–] [email protected] 3 points 1 year ago (1 children)

11

a,ba: So, I've been in the habit of skipping the flavour text and glossing over the prompt. This time, it hurt me badly.

I read the problem as follows: for N galaxies, find N/2 pairings such that the sum of distances is minimal.

At this point, I was like, wow, the difficulty has ramped up. A DP? That will probably run out of memory with most approaches, requiring a BitSet. I dove in, eager to implement a janky data structure to solve this humdinger.

I wrote the whole damn thing. The bitset, the DP, everything. I ran the code, and WOAH, that number was much smaller than the sample answer. I reread the prompt and realised I had it all wrong.

It wasn't all for naught, though. A lot of the convenience stuff I'd written was fine. Also, I implemented a sparse parser, which helped for b.

b: I was hoping they were asking for what I had accidentally implemented for a. My hopes were squandered.

Anyway, this was pretty trivial with a sparse representation of the galaxies.

[–] [email protected] 3 points 1 year ago (1 children)

Love ur premature optimization

[–] [email protected] 2 points 1 year ago

Watch me as I solve P=NP and then find out I was only supposed to solve fizzbuzz

[–] [email protected] 3 points 1 year ago (2 children)
  1. After this problem, I will create a new reply in the OP if it is not there already, and will discuss under that thread.

a,bSo, like many other problems from this year, this is one of those direct solution problems where there isn't much of a neat trick to getting the answer. You just have to implement the algorithm they specify and hope you can do it correctly.

a) I used a regex to do some parsing because I haven't looked at dart regex much and wanted to dip my toes a little.

I considered doing this "properly" with OO classes and subclasses for the different rules. I felt that it would be too difficult and just wrote something janky instead. In hindsight, this was probably the wrong choice, especially since grappling with all the nullable types I had in my single rule class became a little too complex for my melting brain (it is HOT in Australia right now; also my conjunctivae are infected from my sinus infection. So my current IQ is like down 40 IQ points from its normal value of probably -12)

b) There may have been a trick here to simplify the programming (not the processing). Again, I felt that directly implementing the specified algorithm was the only real way forward. In brief:

  1. Start with an "open" set containing a part with 4 ranges from [1, 4001) and an "accepted" set that is empty.
  2. Start at the workflow "in"
  3. For each rule in the current workflow:
  • If the rule accepts part of the ranges in the open set, remember those ranges in a closed set and remove them from the open set.
  • Remove anything the rule rejects from the open set.
  • If the rule redirects to a different workflow W, split off the applicable ranges and recurse at 3 with the current workflow as W.
  • Keep in the open set anything the rule doesn't consider.

Because this is AOC, I assumed that the input would be nice and wouldn't have anything problematic like overlapping ranges, and I was right. I had a very stupid off by one error that took me a while to find as well.

The code I have up as of this comment is pretty long and boring, I might try clean it up later.

[–] [email protected] 3 points 1 year ago

update: have cleaned up the code.

[–] [email protected] 3 points 1 year ago (1 children)

Replying in OP: Yeah, Lemmy punishes old threads/posts a bit too much for my taste ^^.

load more comments (1 replies)
[–] [email protected] 2 points 1 year ago

12

a,bFinally! a Dee Pee!!!

This problem was mainly testing:

  • Are you a bad enough dude to formulate this DP correctly?
  • Are you a bad enough dude to choose a good DP state storage schema?
  • Is your computer a bad enough dude to store all the DP states if you choose a bad storage schema?

...which is true of all DP problems, honestly. So given you know and understand how to approach DP problems, this would be more an engineering issue than anything.

load more comments (14 replies)
[–] [email protected] 3 points 1 year ago* (last edited 1 year ago) (3 children)

Day 20: Pulse Propagation

It feels weird to kick one of these threads off, but hey, here we go.

Code as always: https://github.com/Fluxward/aoc2023/blob/main/20.dart

a,bA

So following from yesterday where I was punished by not going full OO, I decided, hey, this is a problem in which I can do some OOP, so I did. This took very long to do but I regret nothing. If you look at my code, feel free to click your tongue and shake your head at every opportunity I missed to use a design pattern.

Anyway, after a slight snafu with misunderstanding the FF logic and not spotting that some modules can be dummy modules, it all just worked, and I got my answer.

B

This was a bit of a headscratcher, but the answer was surprisingly simple.

First, the answer. Here's how to do it:

  • Look for the "rx" module in your input.
  • If the module that outputs to rx is a conjunction, keep track of how many button presses it takes for each input of the conjunction to change. The answer is the LCM of all those numbers.
  • If the module is a FF, you can also work backwards to get it, but this was not my input so I didn't need to try this.

Getting here was a bit weird. I hoped that I could just run the code from A and spit out the answer when rx went low, but as of time of writing I've been running it now on a separate machine for about an hour and still no result.

My next instinct was to simply work it out from pen and paper. I thought it might be possible (it probably is) but decided to at least experimentally see if the states of the modules connected to rx were cyclic first. I did, and that was enough for me to get to the answer.

My answer was about 230 trillion BPs, which, extrapolating on how long execution is taking on my other machine, might take just under 137 years to calculate naively. Fun!

[–] [email protected] 3 points 1 year ago

[Language: jq]https://github.com/zogwarg/advent-of-code/blob/main/2023/jq/20-b.jq

Completed when waiting for the second leg of my Christmas holidays flight. (It was a long wait, can I blame jet-lag?).

Have a more compact implementation of LCM/GCD, something tells me it will come in handy In future editions. (I’ve also progressively been doing past years)

load more comments (2 replies)
[–] [email protected] 3 points 1 year ago* (last edited 1 year ago) (5 children)

21 Step Counter

Starting this thread having only solved a.

APretty straightforward. Could probably be done in a few lines with the right syntactic sugar.

BThis is some game of life thing that I've never implemented or seen an implementation of, so I am altogether lost.

My current code (https://github.com/Fluxward/aoc2023/blob/main/21.dart) has a memoisation based approach but my current ailments are preventing me from really thinking about this properly so I am bowing out until I have the wherewithal.

[–] [email protected] 3 points 1 year ago

Only solved by receving heavy hints from other's solution, and it still took me forever. By far the hardest this year.

load more comments (4 replies)
[–] [email protected] 3 points 11 months ago (1 children)

Sorry for the necropost: I have completed all the problems! One of them completely stumped me and I had to cheat. Not going to do a writeup unless requested :)

[–] [email protected] 3 points 11 months ago (1 children)

congrats! I have officially checked out of the competition for the time being. Maybe if I get some spare energy later.

What problem had you stumped?

load more comments (1 replies)
[–] [email protected] 2 points 1 year ago* (last edited 1 year ago) (2 children)

Day 12: Hot springs

https://adventofcode.com/2023/day/12

  • Leaderboard completion time: 22:57
  • Personal completion time: ahahahahahahaha (at least i had fun)

Where a curse the fact I decided to use JQ and not a "real" programming language.

spoilerHad to resort to memoization, but sadly JQ isn't mega well suited to that. I had to refactor my part 1 function, to make including the "state" at every function call possible. I wish it were as easy as a @cache decorator, but i guess this way i had fun (for an arbitrary definition of "fun")

Further cleaned up version: https://github.com/zogwarg/advent-of-code/blob/main/2023/jq/12-b.jq

Also lost a fair amount of time not not noticing that the sequence should be joined with "?" not with "". (that'll teach me to always run on the example before the full input, when execution time is super long).

Execution time: 17m10s (without memoization a single row was taking multiple minutes, and there's 1000 rows ^^...)

EDIT: see massive improvement by running in parallel in reply.

[–] [email protected] 3 points 1 year ago

A nice workaround to jq single threadedness, since this is maq reduce and safe to parallelize. 17m10s -> 20s !!!

Spoiler link to commit.https://github.com/zogwarg/advent-of-code/commit/fef153411fe0bfe0e7d5f2d07da80bcaa18c952c

Not really spoilery details: Revolves around spawing mutiple jq instances and filtering the inputs bassed on a modulo of number of instances:

  # Option to run in parallel using xargs
  # Eg: ( seq 0 9 | \
  #        xargs -P 10 -n 1 ./2023/jq/12-b.jq input.txt --argjson s 10 --argjson i \
  #      ) | jq -s add
  # Execution time 17m10s -> 20s
  if $ARGS.named.s and $ARGS.named.i then #
    [inputs] | to_entries[] | select(.key % $ARGS.named.s == $ARGS.named.i) | .value / " "
  else
    inputs / " "
  end

I use JQ at work, and never really needed this, i guess this trick is nice to have under the belt just in case.

load more comments (1 replies)
load more comments
view more: ‹ prev next ›