This should have been posted in [email protected] . I’m leaving it up here as the question has been answered.
bugsmith
- 53 Posts
- 183 Comments
Thanks - appreciate the feedback!
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.
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() }
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.
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
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
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.
Totally agree. Like most “rules”, it just needs treating with nuance and context.
bugsmithAto Ask Lemmy@lemmy.world•What's an activity that you could foresee yourself doing every weekend for the rest of your life?2·11 months agoI can totally see how it could be read like that!
bugsmithAto Ask Lemmy@lemmy.world•What's an activity that you could foresee yourself doing every weekend for the rest of your life?3·11 months agoFive-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.
bugsmithAto Ask Lemmy@lemmy.world•What's an activity that you could foresee yourself doing every weekend for the rest of your life?19·11 months agoFive-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.
Is it perhaps time to unsticky this thread, as it’s been six months?
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.
bugsmithOPAto United Kingdom@feddit.uk•Self-proclaimed working class Clacton woman speaks out against FarageEnglish17·1 year agoI 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.
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.
bugsmithOPAto Programming.dev Meta•Piracy-Related Content on P.D: An Open Dialogue with Our Community2·1 year agoFor 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.
bugsmithOPAto Programming.dev Meta•Piracy-Related Content on P.D: An Open Dialogue with Our Community10·1 year agoI 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.
Personally, I think it’s great. It’s a smaller community than HN and the registration requirements, whilst not a perfect solution, do create a litmus test and ultimately creates an envrionment of mostly high quality posting.
To get in, you need to be invited in by an existing user. If you don’t know anybody, you can hang around on their IRC channel and once you’re familiar, somebody may be willing to invite you.