

Thanks - appreciate the feedback!
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.
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()
}
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 })
}
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)
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.
Thanks. I didn’t know about these advanced libraries, and had not heard of C++ modules either. Appreciate the explanation.
I don’t code in C++ (although I’m somewhat familiar with the syntax). My understanding is the header files should only contain prototypes / signatures, not actual implementations. But that doesn’t seem to be the case here. Have I misunderstood, or is that part of the joke?
I like Konsole.
It comes with KDE, supports tabs, themes, and loads very fast.
I don’t really need more from a terminal than that. When I, rarely, need more advanced features like window splitting and session management I also use Zellij (previously I used tmux).
Yes, I don’t know how I forgot to mention that Iceshrimp and Sharkey both have Mastodon compatible APIs - so all the same apps work (mostly).
Based on your requirements, I would suggest looking at one of the Firefish / CalcKey forks. They are ideal for single user or small instances and they support s3 compatible object storage out of the box.
I would recommend looking at Sharkey or Iceshrimp. Both are under very active development and have very responsive developers if you need support.
If you would like to check out an example, Ruud (of mastodon.world and lemmy.world) set up an instance of Sharkey at (you guessed it) sharkey.world.
Another vote here for Fastmail. I also like Posteo, Mailbox and mxroute, but these are not as fully featured - which may be perfect for you if you’re after email only. What I really like about Fastmail is that on top of being a customer-focused business (rather than a customer is the product business), they offer a really snappy web interface with excellent search - and they are extremely compliant with email standards, building everything on JMAP.
I do not like Proton or Tutanota. I have used both, including using Proton as my main email account for the past two years. I do believe they are probably the best when it comes to encryption and privacy standards, but for me it’s at far too much cost. Encrypted email is almost pointless - the moment you email someone who isn’t using a Proton (or PGP encryption), then the encryption is lost. Or even if they just forward an email to someone outside your chain. I would argue that if you need to send a message to someone with enough sensitivity to require this level of encryption, email is the wrong choice of protocol.
For all that Proton offer, it results in broken email standard compliance, awful search capability and reliance on bridge software or being limited to their WebUI and apps. And it’s a shame, because I really like the company and their mission.
A seemingly unpopular opinion, but Christian Bale’s Batman is my favourite live action version of the character.
Celebrities, politicians and businesses will be more likely to show up on the platform, if that’s your jam.
When corporations inevitably arrive to the platform, we can use it to shame them into offering a decent service after they ignore our calls and emails.
As in, I have Nginx running on my server and use it as a reverse proxy to access a variety of apps and services. But can’t get it playing nicely with AIO Nextcloud.
Yes I’ve not managed to solve this yet. For me, it’s hosting AIO behind my existing Nginx.
Care to give a summary on why you think they should be blocked ahead of any bad acting? Yes, there is some concern about Meta attempting EEE, but ultimately they’re a large platform that can bring a lot of users and attention to the Fediverse. There’s nothing preventing large instances from blocking them down the line, and with user level instance blocking coming in 0.19 to Lemmy (not sure if Mastodon et al have something similar), you can block them personally yourself if you wish, rather than having that thrust upon you by your instance admins.
They’re not really blaming capitalism for anything though? They’re just explaining how it works, and they’re right. In a market driven economy, you are paid for having a skill or some knowledge based on the demand of that skill or knowledge and nothing else. In the same way as the quality of your house has little bearing on it’s value when compared to it’s location. Not a criticism of capitalism.
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.