this post was submitted on 13 Dec 2024
18 points (90.9% liked)

Advent Of Code

995 readers
6 users here now

An unofficial home for the advent of code community on programming.dev!

Advent of Code is an annual Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

AoC 2024

Solution Threads

M T W T F S S
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25

Rules/Guidelines

Relevant Communities

Relevant Links

Credits

Icon base by Lorc under CC BY 3.0 with modifications to add a gradient

console.log('Hello World')

founded 1 year ago
MODERATORS
 

Day 13: Claw Contraption

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

you are viewing a single comment's thread
view the rest of the comments
[โ€“] [email protected] 1 points 3 days ago

I had to borrow some of y'alls code to finish part 2. My approach and all the attempts I did at trying to get the slopes of lines and such couldn't get it high enough.

I thought to move from the prize along it's furthest away axis until I got to the intersection of the slope of the two buttons.

I thought that maybe that wasn't the cheapest way, so I fiddled around with the order of button A and B, but still couldn't get it high enough.

It looks like this group was mostly doing the cross product of the prize to the two buttons. I'm too dumb to realize how that would work. I thought you'd want to move along the furthest away axis first, but maybe it doesn't matter.

If anyone can see if I did anything obviously wrong, I'd appreciate it. I normally don't like to take code without fixing whatever it is I was doing since it always bites me in the butt later, but here I am.

F#

expand for source

let getButtonCounts (buttonA: Button) (buttonB: Button) buttonACost buttonBCost (prize:Prize) =
    // my way of trying to solve by moving the greatest axis first doesn't work for part 2.
    // everyone else seems to be using the slope between the two buttons and applying the cost
    // to a part. I don't see how it works but fuck it.
    // I had to add the `abs` calls to a and b to the borrow code, so who knows wtf. I'm done.
    let cpAB = crossProduct buttonA buttonB
    if cpAB = 0 then None
    else
        let detA = crossProduct prize buttonB
        let detB = crossProduct prize buttonA
        let struct(a, rem_a) = Int64.DivRem(detA, cpAB)
        let struct(b, rem_b) = Int64.DivRem(detB, cpAB)
        if (rem_a <> 0 || rem_b <> 0) then None
        else (abs(a) * (int64 buttonACost) + abs(b)) |> Some
    
    
    // here's where my code was. It came up short on part 2
    let (majorAxis:Point2<int64> -> int64), (minorAxis:Point2<int64> -> int64) = if prize.X > prize.Y then _.X, _.Y else _.Y,_.X
    let firstButton,firstCost, secondButton,secondCost =
        if majorAxis buttonA = majorAxis buttonB then (buttonB, buttonBCost, buttonA, buttonACost)
        else if majorAxis buttonA > majorAxis buttonB then (buttonA,buttonACost, buttonB,buttonBCost)
        else (buttonB, buttonBCost, buttonA, buttonACost)
    
    let origin:Point2<int64> = {X = 0; Y = 0}
    let toSlope button  = Segment.Slope.findL {Start = origin; End = button}
    
    let majorLine = (toSlope firstButton) |> fun s -> {Point = prize; Slope = s }
    let minorLine = (toSlope secondButton) |> fun s -> {Point = origin; Slope = s}
    
    let minorOffset = {Point = secondButton; Slope = minorLine.Slope }
    let intersection = Line.intersection majorLine minorOffset
                       |> Option.filter intersectsOnWholeNumber
                       // |> Option.filter (fun i -> i.X <= (float prize.X) && i.Y <= (float prize.Y)) // is in bounds
                       |> Option.map(fun p ->
                           let pp:Point2<int64> = {X = p.X |> round |> int64; Y = p.Y |> round |> int64}
                           pp)
                       // comparing by slopes can intersect outside of the bounds
                       // of the prize, which is not compatible
    
    match intersection with
    | None -> None
    | Some i -> 
        // steps to move to intersection
        let firstMovement =  (majorAxis prize - majorAxis i) / (majorAxis firstButton)
        // steps to move to 0
        let secondMovement = (minorAxis i) / (minorAxis secondButton)
        
        let cost = firstMovement * (int64 firstCost) + secondMovement * (int64 secondCost)
        Some cost