Skip Navigation
Posts
24
Comments
109
Joined
2 yr. ago
  • I'm a bit less extreme about it than many here. But, in short, back when Reddit made sweeping API changes it immediately gave me 'the ick' and so I sought less centralised platforms. Lemmy is the closest thing I've found to people just hosting their own message boards like back in the early internet.

    I'm a big fan of decentralized platforms and I love the concept of ActivityPub.

    That said, I still use Reddit and have recently started to really enjoy BlueSky, so I'm not militantly against the corporate platforms or anything.

    Finally, I just like the natural selection things like Lemmy and Mastodon have for those who are naturally more techy and nerdy.

  • Gleam

    Late as usual. This one challenged me. Functional programming is a lot of fun, but it's kicking my ass.

     gleam
        
    import gleam/dict
    import gleam/io
    import gleam/list
    import gleam/option.{None, Some}
    import gleam/result
    import gleam/set.{type Set}
    import gleam/string
    import simplifile
    
    pub type Point =
      #(Int, Int)
    
    pub type Grid(a) =
      dict.Dict(Point, a)
    
    pub type Direction {
      North
      East
      South
      West
    }
    
    pub type Loops {
      DoesLoop
      DoesNotLoop
    }
    
    pub type Guard {
      Guard(position: Point, direction: Direction)
    }
    
    fn get_guard(grid: Grid(String)) -> Guard {
      let pos = dict.filter(grid, fn(_pos, char) { char == "^" })
      let assert Ok(pos) = case dict.size(pos) {
        1 -> list.first(dict.keys(pos))
        0 -> panic as "No guard found in input!"
        _ -> panic as "More than one guard found in input!"
      }
      Guard(pos, North)
    }
    
    fn move_guard(guard: Guard) -> Guard {
      let new_pos = case guard.direction {
        North -> #(-1, 0)
        East -> #(0, 1)
        South -> #(1, 0)
        West -> #(0, -1)
      }
      Guard(
        #(guard.position.0 + new_pos.0, guard.position.1 + new_pos.1),
        guard.direction,
      )
    }
    
    fn turn_guard(guard: Guard) -> Guard {
      let new_dir = case guard.direction {
        North -> East
        East -> South
        South -> West
        West -> North
      }
      Guard(guard.position, new_dir)
    }
    
    fn get_obstacles(grid: Grid(String)) -> List(Point) {
      dict.filter(grid, fn(_pos, char) { char == "#" })
      |> dict.keys()
    }
    
    fn recurse_grid(
      grid: Grid(String),
      guard: Guard,
      obstacles: List(#(Int, Int)),
      visited: Set(#(#(Int, Int), Direction)),
    ) -> #(Set(#(#(Int, Int), Direction)), Loops) {
      let new_guard = move_guard(guard)
      let position = new_guard.position
      let dir = new_guard.direction
      case dict.has_key(grid, position) {
        False -> #(visited, DoesNotLoop)
        True -> {
          case set.contains(visited, #(position, dir)) {
            True -> {
              #(visited, DoesLoop)
            }
            False -> {
              case list.contains(obstacles, position) {
                True -> recurse_grid(grid, turn_guard(guard), obstacles, visited)
                False ->
                  recurse_grid(
                    grid,
                    new_guard,
                    obstacles,
                    set.insert(visited, #(position, dir)),
                  )
              }
            }
          }
        }
      }
    }
    
    fn get_grid_input(filename: String) -> Grid(String) {
      let lines =
        filename
        |> simplifile.read()
        |> result.unwrap("")
        |> string.trim()
        |> string.split("\n")
      use grid, row, row_idx <- list.index_fold(lines, dict.new())
      use grid, col, col_idx <- list.index_fold(string.to_graphemes(row), grid)
      dict.insert(grid, #(row_idx, col_idx), col)
    }
    
    fn part_one(
      grid: Grid(String),
    ) -> #(#(Set(#(#(Int, Int), Direction)), Loops), Int) {
      let guard = get_guard(grid)
      let obstacles = get_obstacles(grid)
      let visited = set.new() |> set.insert(#(guard.position, guard.direction))
      let visited = recurse_grid(grid, guard, obstacles, visited)
      let visited_without_dir =
        set.fold(visited.0, set.new(), fn(acc, x) { set.insert(acc, x.0) })
      #(visited, visited_without_dir |> set.size())
    }
    
    fn check_loop(grid: Grid(String), blocker: Point) -> Loops {
      let blocked_grid =
        dict.upsert(grid, blocker, fn(x) {
          case x {
            Some("^") -> "^"
            Some(_) -> "#"
            None -> "#"
          }
        })
      let visited = part_one(blocked_grid).0
      visited.1
    }
    
    fn part_two(grid: Grid(String), visited: Set(#(#(Int, Int), Direction))) {
      let visited =
        set.fold(visited, set.new(), fn(acc, x) { set.insert(acc, x.0) })
      use counter, position <- set.fold(visited, 0)
      case check_loop(grid, position) {
        DoesLoop -> counter + 1
        DoesNotLoop -> counter
      }
    }
    
    pub fn main() {
      let input = "input.in"
      let p1 = input |> get_grid_input() |> part_one
      let visited = p1.0.0
      io.debug(p1.1)
      input |> get_grid_input |> part_two(visited) |> io.debug()
    }
    
      
  • Advent Of Code @programming.dev
    bugsmith @programming.dev

    Any Gleamings in the house?

    I'm running behind as usual. I'm still rather new to Gleam and would love some feedback on how I handled the Day 06 puzzle:

     gleam
        
    import gleam/dict
    import gleam/io
    import gleam/list
    import gleam/option.{None, Some}
    import gleam/result
    import gleam/set.{type Set}
    import gleam/string
    import simplifile
    
    pub type Point =
      #(Int, Int)
    
    pub type Grid(a) =
      dict.Dict(Point, a)
    
    pub type Direction {
      North
      East
      South
      West
    }
    
    pub type Loops {
      DoesLoop
      DoesNotLoop
    }
    
    pub type Guard {
      Guard(position: Point, direction: Direction)
    }
    
    fn get_guard(grid: Grid(String)) -> Guard {
      let pos = dict.filter(grid, fn(_pos, char) { char == "^" })
      let assert Ok(pos) = case dict.size(pos) {
        1 -> list.first(dict.keys(pos))
        0 -> panic as "No guard found in input!"
        _ -> panic as "More than one guard found in input!"
      }
      Guard(pos, North)
    }
    
    fn move_guard(guard: Guard) -> Guard {
      let new_pos = case guard.direction {
        North -> #(-1, 0)
        East -> #(0, 1)
        South -> #(1, 0
      
  • Gleam

    Struggled with the second part as I am still very new to this very cool language, but got there after scrolling for some inspiration.

     gleam
        
    import gleam/int
    import gleam/io
    import gleam/list
    import gleam/regex
    import gleam/result
    import gleam/string
    import simplifile
    
    pub fn main() {
      let assert Ok(data) = simplifile.read("input.in")
      part_one(data) |> io.debug
      part_two(data) |> io.debug
    }
    
    fn part_one(data) {
      let assert Ok(multiplication_pattern) =
        regex.from_string("mul\\(\\d{1,3},\\d{1,3}\\)")
      let assert Ok(digit_pattern) = regex.from_string("\\d{1,3},\\d{1,3}")
      let multiplications =
        regex.scan(multiplication_pattern, data)
        |> list.flat_map(fn(reg) {
          regex.scan(digit_pattern, reg.content)
          |> list.map(fn(digits) {
            digits.content
            |> string.split(",")
            |> list.map(fn(x) { x |> int.parse |> result.unwrap(0) })
            |> list.reduce(fn(a, b) { a * b })
            |> result.unwrap(0)
          })
        })
        |> list.reduce(fn(a, b) { a + b })
        |> result.unwrap(0)
    }
    
    fn part_two(data) {
      let data = "do()" <> string.replace(data, "\n", "") <> "don't()"
      let assert Ok(pattern) = regex.from_string("do\\(\\).*?don't\\(\\)")
      regex.scan(pattern, data)
      |> list.map(fn(input) { input.content |> part_one })
      |> list.reduce(fn(a, b) { a + b })
    }
    
      
  • Elixir

     elixir
        
    defmodule Day02 do
      defp part1(reports) do
        reports
        |> Enum.map(fn report ->
          levels =
            report
            |> String.split()
            |> Enum.map(&String.to_integer/1)
    
          cond do
            sequence_is_safe?(levels) ->
              :safe
    
            true ->
              :unsafe
          end
        end)
        |> Enum.count(fn x -> x == :safe end)
      end
    
      defp part2(reports) do
        reports
        |> Enum.map(fn report ->
          levels =
            report
            |> String.split()
            |> Enum.map(&String.to_integer/1)
    
          sequences =
            0..(length(levels) - 1)
            |> Enum.map(fn i ->
              List.delete_at(levels, i)
            end)
    
          cond do
            sequence_is_safe?(levels) ->
              :safe
    
            Enum.any?(sequences, &sequence_is_safe?/1) ->
              :safe
    
            true ->
              :unsafe
          end
        end)
        |> Enum.count(fn x -> x == :safe end)
      end
    
      defp all_gaps_within_max_diff?(numbers) do
        numbers
        |> Enum.chunk_every(2, 1, :discard)
        |> Enum.all?(fn [a, b] -> abs(b - a) <= 3 end)
      end
    
      defp is_strictly_increasing?(numbers) do
        numbers
        |> Enum.chunk_every(2, 1, :discard)
        |> Enum.all?(fn [a, b] -> a < b end)
      end
    
      defp is_strictly_decreasing?(numbers) do
        numbers
        |> Enum.chunk_every(2, 1, :discard)
        |> Enum.all?(fn [a, b] -> a > b end)
      end
    
      defp sequence_is_safe?(numbers) do
        (is_strictly_increasing?(numbers) or
           is_strictly_decreasing?(numbers)) and all_gaps_within_max_diff?(numbers)
      end
    
      def run(data) do
        reports = data |> String.split("\n", trim: true)
        p1 = part1(reports)
        p2 = part2(reports)
        IO.puts(p1)
        IO.puts(p2)
      end
    end
    
    data = File.read!("input.in")
    Day02.run(data)
    
      
  • I'm late to the party, as usual. Damned timezones. This year I'm going to tackle with a small handful of languages, but primarily Elixir and Gleam. This is my first time trying this languages in earnest, so expect some terrible, inefficient and totally unidiomatic code!
    Here's day one:

    Elixir

     elixir
        
    part_one =
      File.read!("input.in")
      |> String.split("\n", trim: true)
      |> Enum.map(fn line ->
        line
        |> String.split()
        |> Enum.map(&String.to_integer/1)
      end)
      |> Enum.reduce({[], []}, fn [first, second], {list1, list2} ->
        {[first | list1], [second | list2]}
      end)
      |> then(fn {list1, list2} ->
        {Enum.sort(list1), Enum.sort(list2)}
      end)
      |> then(fn {list1, list2} ->
        Enum.zip(list1, list2)
        |> Enum.map(fn {x, y} -> abs(x - y) end)
      end)
      |> Enum.sum()
    
    part_two =
      File.read!("input.in")
      |> String.split("\n", trim: true)
      |> Enum.map(fn line ->
        line
        |> String.split()
        |> Enum.map(&String.to_integer/1)
      end)
      |> Enum.reduce({[], []}, fn [first, second], {list1, list2} ->
        {[first | list1], [second | list2]}
      end)
      |> then(fn {list1, list2} ->
        Enum.map(list1, fn line ->
          line * Enum.count(list2, fn x -> x === line end)
        end)
        |> Enum.sum()
      end)
    
    IO.inspect(part_one)
    IO.inspect(part_two)
    
      
  • She was 89 and no doubt lead a truly fulfilling life, and so I think objectively it's not a sad passing - she had a truly remarkable life and long life.

    That said, she was a significant part of my childhood, and always on the television in the various households I've lived in for one show or another. It feels like losing a beloved grandmother, and I'm devastated. RIP Maggie.

  • Programming @programming.dev
    bugsmith @programming.dev
    Programming @programming.dev
    bugsmith @programming.dev
  • Five-a-side is a specific format of football (soccer), aimed at more casual play with a much lower bar to skill level. Outside of five-a-side leagues (which do exist), it's rarely played with fixed teams and often ran in a more "pick up group" fashion.

  • Five-a-side football (soccer). I'm not a sporty person, but started going with a local group a few years ago and have reaped the benefits of doing some intensive team exercise once per week. I go with a bunch of guys way older than I am, and it's amazing how fit and healthy they are compared to the average person I meet of their age. I certainly plan to keep this up so long an injury doesn't prevent me.

  • Python @programming.dev
    bugsmith @programming.dev

    Polars — Announcing Polars 1.0

  • Nice. I've not seen any of your other videos yet, but I can say that for this one, I really loved that you just jumped straight in to the action and kept the video tight, without missing important details.

  • I really admire her after seeing this. She is so dialled in to what's going on in her working area, and she doesn't get flustered when probed with follow-up questions. Regardless of party, we could do with more people like her running and being elected as MPs - but I imagine she wouldn't even consider it.

  • United Kingdom @feddit.uk
    bugsmith @programming.dev

    Self-proclaimed working class Clacton woman speaks out against Farage

  • You know, I wish I could enjoy IRC - or chatrooms in general. But I just struggle with them. Forums and their ilk, I get. I check in on them and see what's been posted since I last visited, and reply to anything that motivates me to do so. Perhaps I'll even throw a post up myself once in a while.

    But with IRC, Matrix, Discord, etc, I just feel like I only ever enter in the middle of an existing conversation. It's fine on very small rooms where it's almost analagous to a forum because there's little enough conversation going on that it remains mostly asynchronous. But larger chatrooms are just a wall of flowing conversation that I struggle to keep up with, or find an entry point.

    Anyway - to answer the actual question, I use something called "The Lounge" which I host on my VPS. I like it because it remains online even when I am not, so I can atleast view some of the history of any conversation I do stumble across when I go on IRC. I typically just use the web client that comes with it.

  • For Lemmy, it is the latter. Federated content is stored locally on each instance.

  • I really like Nushell. I would not run it as a daily driver currently, as it mostly doesn't win me over from Fish, feature-wise, but I love having it available for anything CLI date pipeline work I need to do.

  • I think that is really in the spirit of Lemmy and the Fediverse. Pick an instance that aligns with your interests / identity / geography / etc, and use that as an entry point to the rest. It doesn't work so well if that entry point has overzealous gatekeeping.

  • We have not blocked anything proactively.

    For us, it was a priority to get some open communication out on this issue, due to any uncertainty caused my Lemmy.world's actions.

  • Unfortunately, there are some cases of direct linking occurring. Fortunately, it's mostly caught by moderators and admins and removed. Defederating is certainly an extreme case, and it's absolutely not something we're intending to do. It would be an absolutely extreme scenario for that to occur in this case.

    Shouldn’t we defederate .world?

    There is no appetite to defederate from lemmy.world. I know their some of their decisions have been unpopular with some users, but they are by far the largest Lemmy instance, and that puts a target on them. Like us, they are a bunch of volunteers trying their best to run a large community and that will sometimes mean making decisions they probably aren't keen of themselves.

  • Yes, my personal stance would also be against blocking. The general preference is to avoid blocking wherever possible.

  • Love this. Always interesting to see novel ways of querying data in the terminal, and I agree that jq's syntax is difficult to remember.

    I actually prefer nu(shell) for this though. On the lobste.rs thread for this blog, a user shared this:

     http get https://api.github.com/orgs/golang/repos
        
    | get license.key -i
    | uniq --count
    | rename license
    
    This outputs the following:
    
    ╭───┬──────────────┬───────╮
    │ # │    license   │ count │
    ├───┼──────────────┼───────┤
    │ 0 │ bsd-3-clause │    23 │
    │ 1 │ apache-2.0   │     5 │
    │ 2 │              │     2 │
    ╰───┴──────────────┴───────╯
    
    
      
  • the piracy community isn’t on this instance, so it’d be a surprise if there’s any legal basis to charge PD with anything related to it.

    This is not so clear-cut. The nature of federation means that any posts you see through via instance are hosted here too. How liable we are for that content is certainly an important question.

    Thanks for your feedback.

  • Programming.dev Meta @programming.dev
    bugsmith @programming.dev

    Piracy-Related Content on P.D: An Open Dialogue with Our Community

    Hello P.D users.

    I'm sure the recent news of lemmy.world's removal of piracy communities has not escaped the attention of many of you. For those who have not heard, here is their announcement on the matter.

    Now, being as transparent as possible, this is not a subject that the admin team of P.D have discussed in great detail up until this point. We have yet to create an explicit rule stating that piracy related content is forbidden on this instance, and doing so is not something any of us wish to do.

    With that being said, this topic requires more deliberation and consideration. There is more complexity to this issue than taking a stance for, against, or tolerant of piracy. There are legal considerations. And the truth is that we are not 100% sure on what the legal implications are for allowing piracy related content to exist on this instance, either directly on our communities or indirectly via federation.

    One thing that must be considered wh

    Programming @programming.dev
    bugsmith @programming.dev
    Programming @programming.dev
    bugsmith @programming.dev

    What even is “Dependency Injection”? (a practical example using Go)

    Programming @programming.dev
    bugsmith @programming.dev
    Programming @programming.dev
    bugsmith @programming.dev
    Programming @programming.dev
    bugsmith @programming.dev
    Programming @programming.dev
    bugsmith @programming.dev
    hnreads.com The Hacker News Top 40 books of 2023

    Hi, welcome to the brand new website, HN Reads. I enjoy reading Hacker News and I love buying books (and reading), and I also love data, so what better than doing some processing of data about books to find some interesting results?! It also gives me the opportunity to write about books that I find ...

    The Hacker News Top 40 books of 2023

    I came across this list and thought it might be interesting to the programming community here.

    Which of these books have you read, or are on your list? Did any have a profound impact on your life? Were any a struggle to get through?

    Selfhosted @lemmy.world
    bugsmith @programming.dev

    The "Everything" Fanless Home Server for under $300 USD

    Programming @programming.dev
    bugsmith @programming.dev

    How Standard Ebooks serves millions of requests per month with a 2GB VPS

    Advent Of Code @programming.dev
    bugsmith @programming.dev

    How will you be tackling the challenges this year?

    What language(s) will you be using? Will you be trying anything different this year to usual?

    Programming @programming.dev
    bugsmith @programming.dev

    Introducing Numbat: A programming language with physical units as types

    Programming @programming.dev
    bugsmith @programming.dev

    Teaching programming to raise money for my local cardiology ward

    I have set up an Open Collective to do some fundraising for my local Cardiology Department. Long term I wish to raise money for equipment, amenities and things like patient taxis, but in the short term I am looking to help fund the staff Christmas party.

    Like many parts of the NHS, the budgets are super tight. I found out recently that the Christmas meal for the cardiology ward this year is going to be cancelled as there is no budget for it. This breaks my heart (pun only slightly intended), and I would like to help fund it.

    I am offering to teach people how to code, or help out junior programmers still early on in their journey. If you are interested, or know someone who is, please consider checking out the Open Collective.

    I have added some tiered "contribution rewards" to give an idea of what might be a good contribution in return for a desired service. Having said this, this is supposed to be a cha

    Programmer Humor @programming.dev
    bugsmith @programming.dev

    I'm just at home heating up my no-code offering in the microwave...

    Sync for Lemmy @lemmy.world
    bugsmith @programming.dev

    I am not receiving ads on the free version

    Obviously it's not something that upsets me, but I was expecting there to be ads and haven't seen any in several weeks of usage.

    I've used it on several networks and do not run an adblocker on my phone, nor do I currently use Pihole or any similar DNS based adblocking.

    Am I just fortunate, or is this beta related?

    Device information

     undefined
            Sync version: v23.09.13-18:19    
        Sync flavor: googlePlay    
        
        View type: Small cards    
        
        Device: panther    
        Model: Google Pixel 7    
        Android: 13
    
    
      

    Edit: I'd be interested to know why this post has been so heavily downvoted.

    United Kingdom @feddit.uk
    bugsmith @programming.dev

    Parliament will debate petition: Make lying in the House of Commons a criminal offence - 23rd October 2023