LogoWCF

janka102's Solution

2025

I used a recursive approach filling in smaller and smaller sleigh sizes as presents are added. This gets very slow very quickly with a naive implementation. One trick is of course classic memoization! The trick to that trick is that you need to have a separate entry for each sleigh size and previous present size. Since present sizes can’t repeat, then for example a remaining sleigh size of 5 can hold different amounts depending on what the previous present was (including no previous present).

1: 1
...
10: 123
...
100: 638760883391635670992582
...
1000: 9.849739E+240
...
10000: 7.486669E+2412
________________________________________________________
Executed in    1.01 secs
require 'optparse'

class Dayd08
  def initialize
    @memo = {}
  end

  def solve(challenge)
    if challenge
      (1..).each do |size|
        arrangements = fill_sleigh(size, nil)
        # the numbers get very large, so format in 3.141592E+65 format
        if size > 100
          digits = Math.log10(arrangements)
          sig_figs = 10**(digits % 1)
          exponent = digits.floor
          puts "#{size}: #{format('%.6fE+%d', sig_figs, exponent)}"
        else
          puts "#{size}: #{arrangements}"
        end
      end
    else
      size = 30
      puts "#{size}: #{fill_sleigh(size, nil)}"
    end
  end

  # Given a sleigh size, try to fit one of each size present
  # then add up how many presents can fit in the new smaller sleigh
  def fill_sleigh(size, prev)
    return @memo[[size, prev]] if @memo.include?([size, prev])

    total = 0

    # order is important, check small to big
    (1..9).each do |present|
      # don't allow two presents of the same size next to each other
      next if present == prev

      remaining = size - present

      # if there is the exact space required for this present then we found a solution
      total += 1 if remaining.zero?

      # if no more space then we can break early and skip checking even bigger presents
      break if remaining <= 0

      sub = fill_sleigh(remaining, present)
      total += sub if sub.positive?
    end

    @memo[[size, prev]] = total

    total
  end
end

if __FILE__ == $PROGRAM_NAME
  options = {}
  OptionParser.new do |parser|
    parser.banner = "Usage: #{$PROGRAM_NAME} [options]"

    parser.on('-c', '--challenge', 'Solve for ever increasing sleigh sizes')
  end.parse!(into: options)

  challenge = Dayd08.new
  challenge.solve(options[:challenge])
end

Day 8: Santa's Tube Sleigh

Santa has limited space in his sleigh, so he needs to know the different ways it can be packed. Santa is magic, so his sleigh is a tube that can store only one long line of presents (check out Jesse’s lore for the reason why! It’s very interesting). Presents can be of any size from 1 - 9, but max out at the size of the sleigh (for when the sleigh is smaller than 9). Because of magic reasons (again, check the lore!), presents of the same size can’t be next to one another. Also, you’re only searching for present arrangements that fill the sleigh. An empty sleigh is not allowed! Neither is one with any gaps!

Here’s an example of all the possible combos for a sleigh of length 3:

Note, 1, 1, 1 is not allowed because it has 2 presents of the same size next to each other!

Some more examples for different sleigh sizes:

4:

5:

For 10 (which has 123 total valid combinations)
  • 1, 2, 1, 2, 1, 2, 1
  • 1, 2, 1, 2, 1, 3
  • 1, 2, 1, 2, 3, 1
  • 1, 2, 1, 2, 4
  • 1, 2, 1, 3, 1, 2
  • 1, 2, 1, 3, 2, 1
  • 1, 2, 1, 4, 2
  • 1, 2, 1, 5, 1
  • 1, 2, 1, 6
  • 1, 2, 3, 1, 2, 1
  • 1, 2, 3, 1, 3
  • 1, 2, 3, 4
  • 1, 2, 4, 1, 2
  • 1, 2, 4, 2, 1
  • 1, 2, 4, 3
  • 1, 2, 5, 2
  • 1, 2, 6, 1
  • 1, 2, 7
  • 1, 3, 1, 2, 1, 2
  • 1, 3, 1, 2, 3
  • 1, 3, 1, 3, 2
  • 1, 3, 1, 4, 1
  • 1, 3, 1, 5
  • 1, 3, 2, 1, 2, 1
  • 1, 3, 2, 1, 3
  • 1, 3, 2, 3, 1
  • 1, 3, 2, 4
  • 1, 3, 4, 2
  • 1, 3, 5, 1
  • 1, 3, 6
  • 1, 4, 1, 3, 1
  • 1, 4, 1, 4
  • 1, 4, 2, 1, 2
  • 1, 4, 2, 3
  • 1, 4, 3, 2
  • 1, 4, 5
  • 1, 5, 1, 2, 1
  • 1, 5, 1, 3
  • 1, 5, 3, 1
  • 1, 5, 4
  • 1, 6, 1, 2
  • 1, 6, 2, 1
  • 1, 6, 3
  • 1, 7, 2
  • 1, 8, 1
  • 1, 9
  • 2, 1, 2, 1, 3, 1
  • 2, 1, 2, 1, 4
  • 2, 1, 2, 3, 2
  • 2, 1, 2, 4, 1
  • 2, 1, 2, 5
  • 2, 1, 3, 1, 2, 1
  • 2, 1, 3, 1, 3
  • 2, 1, 3, 4
  • 2, 1, 4, 1, 2
  • 2, 1, 4, 2, 1
  • 2, 1, 4, 3
  • 2, 1, 5, 2
  • 2, 1, 6, 1
  • 2, 1, 7
  • 2, 3, 1, 3, 1
  • 2, 3, 1, 4
  • 2, 3, 2, 1, 2
  • 2, 3, 2, 3
  • 2, 3, 4, 1
  • 2, 3, 5
  • 2, 4, 1, 2, 1
  • 2, 4, 1, 3
  • 2, 4, 3, 1
  • 2, 5, 1, 2
  • 2, 5, 2, 1
  • 2, 5, 3
  • 2, 6, 2
  • 2, 7, 1
  • 2, 8
  • 3, 1, 2, 1, 2, 1
  • 3, 1, 2, 1, 3
  • 3, 1, 2, 3, 1
  • 3, 1, 2, 4
  • 3, 1, 3, 1, 2
  • 3, 1, 3, 2, 1
  • 3, 1, 4, 2
  • 3, 1, 5, 1
  • 3, 1, 6
  • 3, 2, 1, 3, 1
  • 3, 2, 1, 4
  • 3, 2, 3, 2
  • 3, 2, 4, 1
  • 3, 2, 5
  • 3, 4, 1, 2
  • 3, 4, 2, 1
  • 3, 4, 3
  • 3, 5, 2
  • 3, 6, 1
  • 3, 7
  • 4, 1, 2, 1, 2
  • 4, 1, 2, 3
  • 4, 1, 3, 2
  • 4, 1, 4, 1
  • 4, 1, 5
  • 4, 2, 1, 2, 1
  • 4, 2, 1, 3
  • 4, 2, 3, 1
  • 4, 2, 4
  • 4, 3, 1, 2
  • 4, 3, 2, 1
  • 4, 5, 1
  • 4, 6
  • 5, 1, 3, 1
  • 5, 1, 4
  • 5, 2, 1, 2
  • 5, 2, 3
  • 5, 3, 2
  • 5, 4, 1
  • 6, 1, 2, 1
  • 6, 1, 3
  • 6, 3, 1
  • 6, 4
  • 7, 1, 2
  • 7, 2, 1
  • 7, 3
  • 8, 2
  • 9, 1

Problem: Find the number of possible arrangements of presents for a sleigh of length 30. For an extra challenge, see how large a sleigh you can compute the number of combinations for!


Jesse's Lore Jesse will fill this out