3 votes

Day 25: Code Chronicle

Today's problem description: https://adventofcode.com/2024/day/25

Please post your solutions in your own top-level comment. Here's a template you can copy-paste into your comment to format it nicely, with the code collapsed by default inside an expandable section with syntax highlighting (you can replace python with any of the "short names" listed in this page of supported languages):

<details>
<summary>Part 1</summary>

```python
Your code here.
```

</details>

4 comments

  1. [3]
    lily
    Link
    Glad for the easier one today. I wasn't able to solve yesterday's part 2 as I'm not familiar with adders and learning about them didn't feel like a fun way to spend my Christmas Eve. If anyone has...

    Glad for the easier one today. I wasn't able to solve yesterday's part 2 as I'm not familiar with adders and learning about them didn't feel like a fun way to spend my Christmas Eve. If anyone has any hints for that that don't entirely give the solution away, I would appreciate it. Until then, I'll have to leave this year's Advent of Code unfinished.

    As for today's puzzle, it was one of the easiest this year. I wasn't especially fast at solving it, unfortunately, but there really wasn't anything to solve about it - it was immediately clear what I was supposed to do. Most of my time was spent writing input parsing code.

    Solution (Jai)
    /* Advent of Code 2024
     * Day 25: Code Chronicle
     */
    
    #import "Basic";
    #import "File";
    #import "String";
    
    main :: () {
        input, success := read_entire_file("inputs/day_25.txt");
        assert(success);
    
        groups := split(input, "\n\n");
        defer array_free(groups);
    
        keys: [..][5] int;
        locks: [..][5] int;
        defer array_free(keys);
        defer array_free(locks);
    
        for groups {
            lines := split(it, "\n");
            defer array_free(lines);
    
            if lines[0] == "....." {
                key: [5] int;
                for x: 0..4 {
                    height := 0;
                    for #v2 < y: 1..5 {
                        if lines[y][x] == #char "#" {
                            height += 1;
                        } else {
                            break;
                        }
                    }
    
                    key[x] = height;
                }
    
                array_add(*keys, key);
            } else {
                lock: [5] int;
                for x: 0..4 {
                    height := 0;
                    for y: 1..5 {
                        if lines[y][x] == #char "#" {
                            height += 1;
                        } else {
                            break;
                        }
                    }
    
                    lock[x] = height;
                }
    
                array_add(*locks, lock);
            }
        }
    
        fitting_pairs := 0;
        for key: keys {
            for lock: locks {
                fits := true;
                for 0..4 {
                    if key[it] + lock[it] > 5 {
                        fits = false;
                        break;
                    }
                }
    
                if fits {
                    fitting_pairs += 1;
                }
            }
        }
    
        print("Part 1: %\n", fitting_pairs);
    }
    
    1 vote
    1. [2]
      scarecrw
      Link Parent
      Part 2 was definitely this year's "don't generalize, just inspect your input" problem. I can say that while I at some point knew how adders were set up, the only information that was necessary is...

      Part 2 was definitely this year's "don't generalize, just inspect your input" problem. I can say that while I at some point knew how adders were set up, the only information that was necessary is that each bit in the output is calculated in roughly the same way.

      minor spoiler

      For example, after sorting all the connections that led to a z output, I could see:

      ...
      gmw XOR cqn -> z08
      jgj XOR gff -> z09
      x10 AND y10 -> z10 // that's weird
      fgb XOR bmd -> z11
      qbw XOR gvj -> z12
      bgh XOR ctc -> z13
      pvs XOR wgc -> z14
      ...
      

      Just the obvious stand-outs accounted for 3/4 of the swaps for my input. Finding what to replace them with was a bit more challenging, but the same premise of "follow the pattern" still holds.

      Btw, thanks for sharing your Jai work! I'd never heard of the language, and while I'm not sure if I'm interested in trying it, I watched one of the creator's videos and the ideas seemed super interesting!

      1 vote
      1. lily
        Link Parent
        It's very procedural / C-like and quite opinionated, so it probably is only appealing to specific types of programmers. I've found some things about it I like, and some I don't - though, maybe...

        It's very procedural / C-like and quite opinionated, so it probably is only appealing to specific types of programmers. I've found some things about it I like, and some I don't - though, maybe some of the latter will be improved by the time the language enters open beta. The compile-time features are probably the language's "big idea", though I didn't find much use for them in Advent of Code.

        1 vote
  2. scarecrw
    Link
    Short and sweet to finish! I just hardcoded all the dimensions, but it's the last day, so I'm happy enough with it. Smalltalk Solution Class { #name : 'Day25Solver', #superclass : 'AoCSolver',...

    Short and sweet to finish! I just hardcoded all the dimensions, but it's the last day, so I'm happy enough with it.

    Smalltalk Solution
    Class {
    	#name : 'Day25Solver',
    	#superclass : 'AoCSolver',
    	#instVars : [ 'locks', 'keys' ],
    	#category : 'AoCDay25',
    	#package : 'AoCDay25'
    }
    
    Day25Solver >> getHeights: aString [
       | heights |
       heights := OrderedCollection new: 5 withAll: 0.
       aString lines do: [ :row |
          row withIndexDo: [ :c :i |
             c = $# ifTrue: [ heights at: i put: (heights at: i) + 1 ] ] ].
       ^ heights
    ]
    
    Day25Solver >> parseRawData [
       locks := OrderedCollection new.
       keys := OrderedCollection new.
       (rawData splitOn: String cr , String cr) do: [ :schematic |
          (schematic startsWith: '#')
             ifTrue: [ locks add: (self getHeights: schematic) ]
             ifFalse: [ keys add: (self getHeights: schematic) ] ]
    ]
    
    Day25Solver >> solvePart1 [
    	^ locks collectAndSum: [ :lock | keys count: [ :key | (lock + key) max <= 7 ] ]
    ]
    

    I've certainly come a long with Pharo since the beginning of the month! I can't say I expect to use it much going forward, but I'm pleased to have gotten through AoC with it and definitely feel like I've gotten the "experience" of working in a language like this. I caught myself the other day writting in another language and thinking "oh man, I wish I could do it like Pharo..." which is always a great indicator that something's started to rub off.

    Always more puzzles to be had, but this year's AoC was a wonderful time!

    1 vote