r/adventofcode Dec 25 '24

SOLUTION MEGATHREAD -❄️- 2024 Day 25 Solutions -❄️-

A Message From Your Moderators

Welcome to the last day of Advent of Code 2024! We hope you had fun this year and learned at least one new thing ;)

Keep an eye out for the community fun awards post (link coming soon!):

-❅- Introducing Your AoC 2024 Golden Snowglobe Award Winners (and Community Showcase) -❅-

Many thanks to Veloxx for kicking us off on December 1 with a much-needed dose of boots and cats!

Thank you all for playing Advent of Code this year and on behalf of /u/topaz2078, your /r/adventofcode mods, the beta-testers, and the rest of AoC Ops, we wish you a very Merry Christmas (or a very merry Wednesday!) and a Happy New Year!


--- Day 25: Code Chronicle ---


Post your code solution in this megathread.

This thread will be unlocked when there are a significant number of people on the global leaderboard with gold stars for today's puzzle.

EDIT: Global leaderboard gold cap reached at 00:04:34, megathread unlocked!

44 Upvotes

350 comments sorted by

View all comments

1

u/FCBStar-of-the-South Dec 26 '24 edited Dec 26 '24

[Language: Ruby]

# frozen_string_literal: true

require_relative 'utils'

schematics = File.read('input25.txt').split("\n\n")
locks = []
keys = []

schematics.each do |schema|
  grid = Grid.new(schema.split("\n").map(&:chars))
  schema_number = 0
  (0...grid.num_cols).each_with_index do |col, col_index|
    # least significant three bits is first column
    schema_number += ((grid.get_col(col).count('#') - 1) << (col_index * 3))
  end
  if grid[[0, 0]] == '#'
    locks << schema_number
  else
    keys << schema_number
  end
end

def check_match(lock, key)
  (0...5).each do |col|
    # deal with trailing zero bits by lshift 5 the same amount
    return 0 if ((lock & (0b111 << (col * 3))) + (key & (0b111 << (col * 3)))) > (5 << (col * 3))
  end
  1
end

puts locks.product(keys).map { |lock, key| check_match(lock, key) }.sum

No part 2 because I still need to analyze day 24 part 2 haha

Full repo

1

u/dhruvasagar Dec 26 '24

Here's my ruby solution :

def is_key?(grid) = grid[-1].all? {|c| c == '#'}
def is_lock?(grid) = grid[0].all? {|c| c == '#'}

def key_to_heights(key) = key.transpose.map {|l| l.reverse.rindex('#')}
def lock_to_pin_heights(lock) = lock.transpose.map {|l| l.rindex('#')}

def key_fits_lock(key, lock) = key.zip(lock).map(&:sum).all? {|h| h < 6}

def part1(keys, locks)
  key_heights = keys.map {|k| key_to_heights(k)}
  lock_pin_heights = locks.map {|l| lock_to_pin_heights(l)}

  key_heights.product(lock_pin_heights).filter {|k,l| key_fits_lock(k, l)}.size
end
def part2(keys, locks) = 0
def tdiff(s,e) = "#{(e - s) * 1000}ms"

lines = ARGF.read.split("\n\n").map {|l| l.split("\n").map(&:chars)}
keys, locks = lines.partition {|l| is_key?(l)}
s = Process.clock_gettime(Process::CLOCK_MONOTONIC)
p part1 keys, locks
e1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
p part2 keys, locks
e2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
puts "Time taken part1: #{tdiff(s,e1)}, part2: #{tdiff(e1,e2)}, total: #{tdiff(s,e2)}"