RagingHungryPanda

joined 2 years ago
[–] RagingHungryPanda@lemm.ee 3 points 1 month ago

Start with "absolute beginner" courses. Here's one from Bob Taylor. He puts out a lot of good stuff.

Sit your self down and study it for a good bit, then build some things. https://youtu.be/0QUgvfuKvWU

[–] RagingHungryPanda@lemm.ee 2 points 1 month ago

Oh they got the room alright

[–] RagingHungryPanda@lemm.ee 5 points 1 month ago* (last edited 3 weeks ago)

When we went through a family tragedy the big lasagna was amazing. We didn't have to find or worry about anything and we could just do it on autopilot.

Edit:typo

[–] RagingHungryPanda@lemm.ee 2 points 1 month ago

I use one for travel abroad and wireguard/open vpn connections. I just set up another at home as a server and I'm thinking of setting up tail scale and maybe getting some services running. They're good devices.

[–] RagingHungryPanda@lemm.ee 29 points 1 month ago (7 children)

I've enjoyed lemm.ee

[–] RagingHungryPanda@lemm.ee 58 points 1 month ago

Damn the chuds are really trying. I can smell the copium.

[–] RagingHungryPanda@lemm.ee 2 points 1 month ago

I saw that. I think it sort of made sense haha. There's a reason I'm not in statistics or analytics lol

[–] RagingHungryPanda@lemm.ee 2 points 1 month ago (2 children)

Yeah I don't know how long I would have tried to solve that on my own. I was starting to wonder if I did something wrong because I read seeing patterns every 80 iterations or so

[–] RagingHungryPanda@lemm.ee 2 points 1 month ago (4 children)

This one was wild. At first I started visualling it but wasn't seeing anything. I went up to almost 80 iterations before giving up. I then went with the "no overlapping points thing" but didn't think that was working for me either.

It was iteration 7,753. f's sake man.

I used the a modulo operation and an if check to skip ahead to the final state. It was also tricky b/c the grid is larger than I could get my console to work with.

F#

(just the important bits)

type Velocity = Point2I
[<Struct>]type Robot = {Position:Point2I; Velocity:Velocity}
type Boundary = {MaxX:int; MaxY: int}
let move ticks boundary robot =
    let newX = ((robot.Position.X + (robot.Velocity.X * ticks)) % boundary.MaxX) |> fun x -> if x < 0 then boundary.MaxX + x else x
    let newY = ((robot.Position.Y + (robot.Velocity.Y * ticks)) % boundary.MaxY) |> fun x -> if x < 0 then boundary.MaxY + x else x
    { robot with Position = {X = newX; Y = newY} }
    
let toQuadrantScore boundary robots =
    let removeX = ((boundary.MaxX |> float) / 2.0) |> int
    let removeY = ((boundary.MaxY |> float) / 2.0) |> int
    ((0,0,0,0), robots)
    ||> Seq.fold(fun (a,b,c,d) robot ->
        if robot.Position.X < removeX && robot.Position.Y < removeY then (a+1,b,c,d)
        else if robot.Position.X > removeX && robot.Position.Y < removeY then (a,b+1,c,d)
        else if robot.Position.X < removeX && robot.Position.Y > removeY then (a,b,c+1,d)
        else if (robot.Position.X > removeX && robot.Position.Y > removeY) then (a,b,c,d+1)
        else (a,b,c,d)
        )
    |> fun (a,b,c,d) -> a*b*c*d


let part1impl boundary ticks robots =
    robots
    |> Seq.map(move ticks boundary)
    |> toQuadrantScore boundary
    
let part1 input =
    (read input parse)
    |> part1impl {MaxX = 101; MaxY = 103 } 100


let part2 input =
    let robots = (read input parse) |> Array.ofSeq
    let boundary = {MaxX = 101; MaxY = 103 }
    
    // I'll steal the no overlapping robots approach
    // since I'll just be iterating through, I'll do batches of 100 numbers each in parallel and then draw it
    // up to 100 batches
    [0..100]
    |> List.find (fun batch ->
        try
            seq {0..100}
            |> Seq.pick (fun t ->
                // I could use PSeq here, but I'd have to remove the console stuff as the locking and fighting for the console in parallel really slows it
                let ticks = batch * 100 + t
                Console.Clear()
                Console.SetCursorPosition(0,0)
                Console.Write(ticks)
                
                let count =
                    robots
                    |> PSeq.map (move ticks boundary)
                    |> PSeq.distinctBy _.Position
                    |> PSeq.length
                    
                
                    
                if count = 500 then
                    ... write to file, console

[–] RagingHungryPanda@lemm.ee 1 points 1 month 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

[–] RagingHungryPanda@lemm.ee 2 points 1 month ago

hey thanks!

I didn't check any other solutions before finishing (currently wondering way day 13 is too low), but I thought that trying to traverse fences would be a pain and since I have everything separated by regions and not traversing the array, counting corners never came to mind.

But the thought that I had was that for each region, all points will be a straight line in the V or H orientations, so if I can go up and down and count when last != next - 1, then that'll tell me that that is a contiguous piece of fence.

The idea isn't too hard, for tracking the XAxis it's

region.GroupBy(YAxis) // row
.Select(group => 
    group.Sort(g => g.XAxis) // column
        .Window(a,b => a != b - 1 ? 1 : 0).Sum()
.Sum()

Except that I used a different splitting method and that came to me later.

[–] RagingHungryPanda@lemm.ee 2 points 1 month ago* (last edited 1 month ago) (2 children)

I know I'm late, but it's still fun and I'm sure no-one will see this.

Part 2 took me way too long to get right. I was initially only returning the relative point to which a plot needed a fence. I ran into issues of knowing if it was a valid fence or not by my method of counting (later). I eventually went with returning a tuple of the plot and an enum flag of the sides that it has fences on.

For counting I grouped the points by one axis then sorted on the other and counted the number of times the transition between two wasn't contiguous.

It could by done in parallel, but the original traversal would need de-duping, which I didn't feel like doing. After that things are done on a region basis, which could be parallel.

I also can't help but notice mine is by far the longest ( > . < )

F#

Tap for spoiler

type Plant = char
type Plot = Plant * Point2I
type Region = Plot list

let area region = List.length region

let perimeter (region:Region) (farm:Grid<Plant>) =
    (0, region)
    ||> List.fold (fun sum plot ->
        movements4 (snd plot) farm
        |> List.fold (fun acc po ->
            acc + match po with
                  | ValueNone -> 1
                  | ValueSome pother ->
                      get pother farm
                      |> fun x ->
                          match x with
                          | ValueSome v when v <> fst plot -> 1
                          | _ -> 0
            ) 0
        |> (fun x -> x + sum)
        )

let movements (plot:Plot) g (visited:HashSet<Point2I>) =
    let plant, point = plot
    movements4 point g
    |> List.choosev (fun px ->
        let vx = get px g |> ifNoneFail "couldn't get point"
        struct(px,vx))
    |> List.filter (fun plotx ->
        let struct(px, vx) = plotx
        vx = plant && not (visited.Contains px))

// visited is needed because I'm using similar logic to the trails, but no stopping point, so I
// need to make sure that it doesn't retrace itself
let rec traverse grid plot (visited:HashSet<Point2I>) =
    let plant, point = plot
    if visited.Contains(point) then []
    else
        visited.Add(point) |> ignore
        let path =
            movements plot grid visited
            |> List.filter (fun struct(newPoint, newPlant) -> newPlant = plant && visited.Contains(newPoint) |> not )
            |> List.map(fun struct(newPoint, newPlant) -> traverse grid (newPlant, newPoint) visited)
            |> List.concat
            |> List.distinct
        plot :: path

/// Returns the list of plots walked and a new grid with the traversed plots set to '.'
let walk (plot:Plot) (farm:Grid<Plant>) : Region * Grid<Plant> =
    let foundMovements = HashSet()
    let region:Region = traverse farm plot foundMovements
    let updatedGrid =
        let arr = Array2D.copy farm
        for _, p in region do
            set p arr '.' |> ignore
        arr
    (region, updatedGrid)
    
let rec findRegions (farm:Grid<Plant>) : Region list=
    farm
    |> List.unfold (fun arr ->
        match (findFirst (fun struct(_,_,v) -> v <> '.' )) arr with
        | Some value ->
            let struct(x,y,v) = value
            let point = {X = x; Y = y}
            let plot : Plot = (v, point)
            let region, newFarm = walk plot arr
            Some (region, newFarm)
        | None -> None
    )
    
let part1 input =
    (readGrid2D input (fun _ c -> c))
    |> fun grid ->
        findRegions grid
        |> List.sumBy (fun region ->
            let a = area region
            let p = perimeter region grid
            a * p)

// Part 2 ---------------------------------------------
[<Flags>]
type Side = None = 0 | Top = 1 | Right = 2| Left = 4 | Bottom = 8
type PlotWithFence = Plot * Side 

type SideAndNextPoint = Side * Point2I

// I couldn't use my original movement function because it filters out off-grid positions, so I modified it here
let getSides plot grid =
    let toPlot (side:Side) (voption:Point2I voption) =
        match voption with | ValueNone -> None, side | ValueSome point -> (Some point, side)
    [
        l (snd plot) |> toPlot Side.Left
        r (snd plot) grid |> toPlot Side.Right
        u (snd plot) |> toPlot Side.Top
        d (snd plot) grid |> toPlot Side.Bottom
    ]


let rec findEdges grid (plot:Plot) (visited:HashSet<Point2I>) =
    
    // this attempt that works is to attach the side information to each point
    // I didn't see a great way to use the existing movements function, so I copied it and added a mapping
    // so that I know in what direction the movement options are
    let sidesWithFence = getSides plot grid

    let plant, point = plot
    if visited.Add(point) |> not then Side.None
    else
        // use the movements to find edges
        let edges = 
            sidesWithFence
            |> List.fold (fun sides next ->
                match next with
                | None, side ->  sides ||| side
                | Some point, side when (get point grid >>= fun v -> v <> plant) |> ifNone false -> sides ||| side
                | _ -> sides
            ) Side.None
            
        edges

let getSideCount2 (plotFences:(Point2I * Side) list) =
    // ok, now I have information on each SIDE that a fence is one... omg I suck at this.
    // I'll try to do the whole compare horizontally and vertically thing again, but this time
    // within each I'll have to check the top and bottom, or I'll iterate it twice
    
    let getX (pf:Point2I * Side) : int = (fst pf) |> _.X
    let getY (pf:Point2I * Side) : int = (fst pf) |> _.Y
    
    let countContiguous side group sort =
        plotFences
        |> Seq.filter (fun pf -> (snd pf) &&& side = side)
        |> Seq.groupBy group 
        |> Seq.map(fun (key, g) -> g |> Seq.sortBy sort)
        // |> Array.ofSeq // debugging code
        |> Seq.sumBy(fun grouping ->
            let total =
                grouping
                |> Seq.splitByComparison (fun last current -> 
// splitByComparison is an implementation I took from ChatGPT for a function that I commonly use in C# as part of the MoreLinq library that does the same thing. Here, I'm splitting whenever there is a difference. 
// in hindsight, it probably could have been a window
                    let l = sort last 
                    let r = sort current
                    l <> (r - 1)
                )
                |> Seq.length
            total)
    
    let topCounts = countContiguous Side.Top getY getX
    let bottomCounts = countContiguous Side.Bottom getY getX
    let leftCounts = countContiguous Side.Left getX getY
    let rightCounts = countContiguous Side.Right getX getY
    
    topCounts + bottomCounts + leftCounts + rightCounts


let part2 input =
    (readGrid2D input (fun _ c -> c))
    |> fun grid ->
        findRegions grid
        // |> List.take 1
        |> List.sumBy(fun region ->
            let (plotCount, edgecount) =
                let visited = HashSet()
                let regionCounts =
                    region
                    |> List.map(fun p -> (snd p), findEdges grid p visited)
                    |> getSideCount2
                (visited.Count, regionCounts)
            
            let area = plotCount
            area * edgecount
            )

 
19
Hostels baby (lemm.ee)
submitted 5 months ago* (last edited 5 months ago) by RagingHungryPanda@lemm.ee to c/travel@lemmy.world
 

If this is not the right place for memes about travel, feel free to remove

 

One of the fun parts about traveling and speaking another language: sometimes my Spanish is really good, but the past few days people haven't been able to understand me and asked me to switch to English. Maybe I got lazy, maybe my mouth is moving weird, but it happens. It comes back eventually. I hope

edit: the other part about it is that it does feel embarrassing, because I'm just ordering a coffee and failed to do that. Eh, whatever.

 

I think I've out-aged the medium 😅

Wow! You're so ancient! You're like 30!

Could you not? sad pepe

 

I think I've out-aged the medium 😅

Wow! You're so ancient! You're like 30!

Could you not? sad pepe

 

I hope this helps some people that are traveling. These are links to Google Maps lists I made of places in different cities I've been to that I thought were interesting. You can subscribe/follow the list to add it to yours. These lists aren't complete travel guides, just places I wanted to save or was told about, sorted by name. Some of them have a lot of places, others not so much. I left off lists that only had a few places. I hope someone may find them helpful one day!

Antigua, Guatemala

Buenos Aires, Argentina

Cali, Colombia

Chicago, USA

Medellin, Colombia

Merida, Mexico

Mexico City, Mexico

New Orleans, USA

New York City, USA

Oaxaca, Mexico

Quito, Ecuador

Rosario, Argentina

Edits
Cordoba, Argentina

 

Wanna feel rich with little money?

 

cross-posted from: https://lemm.ee/post/39289735

NEW YORK TIMES BESTSELLER • WALL STREET JOURNAL BESTSELLER • USA TODAY! BESTSELLER

In this beautifully written, vividly detailed memoir, a young woman chronicles her adventures traveling across the deserts of the American West in an orange van named Bertha and reflects on an unconventional approach to life.

 

Bianca Graulau

While reporting on the inequality and unequal treatment between tourists and locals in Oaxaca, Mexico, Bianca was told to not mention the hotel chain because they were affiliated with the company.

In Oaxaca, there is a water shortage that has a great impact on the people there and in the surrounding area. But if you're a tourist, you may not even know.

This story was censored by a big and well-known media company. So I decided to tell it on my own. I look into the following question: does the current tourism model in Oaxaca lead to deeper inequality?

view more: ‹ prev next ›