cabhan

joined 2 years ago
[–] cabhan@discuss.tchncs.de 3 points 4 weeks ago* (last edited 3 weeks ago) (1 children)

I'm playing Wylde Flowers. It's a farm sim game with witchcraft, but I mostly like it because it is extremely low-stress. No inventory management, no time pressure to do things, just building a farm and talking to / romancing people.

I picked it up after I got to the point in Subnautica where you have too much contact with leviathans, and I need something calm and relaxing. Maybe I'll make more Subnautica progress soon, though :).

Edit: Spelling

 

Hallo Leute! Ich suche ein paar Dinge für den Saunagang, in diesem Fall einen Saunakilt. Ich habe früher Handtücher und Bademäntel von Amazon gekauft, und ich habe mich damals schlecht gefühlt, und ich würde voll gern eher von einem Laden hier in München kaufen. Kann irgendjemand mir was empfehlen?

Ich habe schon in dem kleinen Laden im Phönix Bad geschaut, aber sie haben viel mehr für das Pool als für die Sauna.

Vielen Dank!

[–] cabhan@discuss.tchncs.de 27 points 3 months ago* (last edited 3 months ago)

When I toured the concentration camp at Dachau some years ago, the tour guide was very clear on this point: people did elect the Nazis.

In 1932, the Nazi party became the largest party in the German parliament, with 37.3% of the vote. It is true that it was not mandatory to make Hitler chancellor, but as the head of the largest party, it would have been expected.

The Nazi party received massive support in democratic elections, where the expectation of the voters would have been that if the Nazi party gained enough seats, Hitler would become chancellor.

This is an important point to me, as it shows that it is possible for democratic elections to result in a fascist government that dismantles democracy. Ignoring this historical example prevents us from applying the lesson to new situations.

[–] cabhan@discuss.tchncs.de 1 points 3 months ago

Hah. I tried doing some research about what this kind of drain is called, but I have no idea. I've never had a drain like this before, but I guess it must not be too rare?

In my case, the issue is that it starts to stink a lot. We had a plumber out a few years ago, and he opened that thing up and used a plunger to remove a ton of hair. He then suggested we wash it out every now and again, but I haven't been able to do it for a while now, since I can't get that thing open.

[–] cabhan@discuss.tchncs.de 1 points 3 months ago (1 children)

Not at all a silly question! I have tried, yes. Also, I've been able to remove it before, but the last time I put it in, I really jammed it in, I guess. There are no threads, so the turning is really just about generating force.

[–] cabhan@discuss.tchncs.de 1 points 3 months ago

This looks very promising! Have you used something like this before? Most references I see online use this to remove the entire drain, not simply to turn the little thing inside. Is that accurate?

[–] cabhan@discuss.tchncs.de 8 points 3 months ago (1 children)

It's not the most complex game, but Dixit has really beautiful cards, in my opinion.

[–] cabhan@discuss.tchncs.de 4 points 3 months ago

I agree that the cards are great! Have you heard of the Fan Art Pack? It has variants of a bunch of the cards in a different style, which I also quite like.

 

A specific question, but maybe someone here knows! My shower has a drain. When I remove the cover and the "thing" inside of it, there's a stopper with an O-Ring.

We used to be able to pull the stopper out and clean inside the pipe (suggested by a plumber), but I now can't remove the stopper anymore. It appears to be quite stuck, and the angle is also terrible to get a better grip on it. I don't want to use pliers, because I'm afraid I might snap the thing that you hold, and then I'm really in trouble.

Can anyone give me suggestions what I can do to get the stopper out? Is there a technique I don't know? A device I could buy?

Thank you!

 

Hello all! I've been a Software Developer for almost 15 years now, and after staying at my last few companies for only 2 years each, I'm starting to think about the possibility of becoming a freelancer/contractor. I'm looking for more flexibility in my work and getting out of parts of the corporate culture that I have grown to dislike.

I'm in a good place financially, and so I'm looking to see if it's a possibility. I speak English and German fluently, and have primarily a background in webservice and FE development, though I can also do quite a bit of Rust and have dabbled in Android apps a bit. I also have some experience with medical software. I think my biggest issues right now are business model development / pricing and finding customers.

Does anyone know of any good resources? I find quite a bit online, but a lot seems geared towards being self-employed generally, and not to the software industry itself. I'd be looking for either good websites or books, or general starting points for research.

Thanks in advance for any suggestions or advice!

[–] cabhan@discuss.tchncs.de 2 points 4 months ago

I bought Ghost of Tsushima in one of the recent sales, and I've been enjoying it a great deal, so I'll likely be joining you there.

[–] cabhan@discuss.tchncs.de 3 points 5 months ago* (last edited 5 months ago)

Rust

I was stuck for a while, even after getting a few hints, until I read the problem more closely and realized: there is only one non-cheating path, and every free space is on it. This means that the target of any shortcut is guaranteed to be on the shortest path to the end.

This made things relatively simple. I used Dijkstra to calculate the distance from the start to each space. I then looked at every pair of points: if they are a valid distance away from each other, check how much time I would save jumping from one to the next. If that amount of time is in the range we want, then this is a valid cheat.

https://gitlab.com/bricka/advent-of-code-2024-rust/-/blob/main/src/days/day20.rs?ref_type=heads

The Code

// Critical point to note: EVERY free space is on the shortest path.

use itertools::Itertools;

use crate::search::dijkstra;
use crate::solver::DaySolver;
use crate::grid::{Coordinate, Grid};

type MyGrid = Grid<MazeElement>;

enum MazeElement {
    Wall,
    Free,
    Start,
    End,
}

impl MazeElement {
    fn is_free(&self) -> bool {
        !matches!(self, MazeElement::Wall)
    }
}

fn parse_input(input: String) -> (MyGrid, Coordinate) {
    let grid: MyGrid = input.lines()
        .map(|line| line.chars().map(|c| match c {
            '#' => MazeElement::Wall,
            '.' => MazeElement::Free,
            'S' => MazeElement::Start,
            'E' => MazeElement::End,
            _ => panic!("Invalid maze element: {}", c)
        })
             .collect())
        .collect::<Vec<Vec<MazeElement>>>()
        .into();

    let start_pos = grid.iter().find(|(_, me)| matches!(me, MazeElement::Start)).unwrap().0;

    (grid, start_pos)
}

fn solve<R>(grid: &MyGrid, start_pos: Coordinate, min_save_time: usize, in_range: R) -> usize
where R: Fn(Coordinate, Coordinate) -> bool {
    let (cost_to, _) = dijkstra(
        start_pos,
        |&c| grid.orthogonal_neighbors_iter(c)
            .filter(|&n| grid[n].is_free())
            .map(|n| (n, 1))
            .collect()
    );

    cost_to.keys()
        .cartesian_product(cost_to.keys())
        .map(|(&c1, &c2)| (c1, c2))
        // We don't compare with ourself
        .filter(|&(c1, c2)| c1 != c2)
        // The two points need to be within range
        .filter(|&(c1, c2)| in_range(c1, c2))
        // We need to save at least `min_save_time`
        .filter(|(c1, c2)| {
            // Because we are working with `usize`, the subtraction
            // could underflow. So we need to use `checked_sub`
            // instead, and check that a) no underflow happened, and
            // b) that the time saved is at least the minimum.
            cost_to.get(c2).copied()
                .and_then(|n| n.checked_sub(*cost_to.get(c1).unwrap()))
                .and_then(|n| n.checked_sub(c1.distance_to(c2)))
                .map(|n| n >= min_save_time)
                .unwrap_or(false)
        })
        .count()
}

pub struct Day20Solver;

impl DaySolver for Day20Solver {
    fn part1(&self, input: String) -> String {
        let (grid, start_pos) = parse_input(input);
        solve(
            &grid,
            start_pos,
            100,
            |c1, c2| c1.distance_to(&c2) == 2,
        ).to_string()
    }

    fn part2(&self, input: String) -> String {
        let (grid, start_pos) = parse_input(input);
        solve(
            &grid,
            start_pos,
            100,
            |c1, c2| c1.distance_to(&c2) <= 20,
        ).to_string()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_part1() {
        let input = include_str!("../../inputs/test/20");
        let (grid, start_pos) = parse_input(input.to_string());
        let actual = solve(&grid, start_pos, 1, |c1, c2| c1.distance_to(&c2) == 2);
        assert_eq!(44, actual);
    }

    #[test]
    fn test_part2() {
        let input = include_str!("../../inputs/test/20");
        let (grid, start_pos) = parse_input(input.to_string());
        let actual = solve(&grid, start_pos, 50, |c1, c2| c1.distance_to(&c2) <= 20);
        assert_eq!(285, actual);
    }
}

[–] cabhan@discuss.tchncs.de 3 points 5 months ago

Rust

I figured that Part 2 would want something to do with unique paths, so I tried to generate all paths in Part 1, which took too long. So I then decided to go with dynamic programming. In Part 1, I stored a cache of whether a given state can lead to the solution. In Part 2, I updated it to store how many options are possible from a given state.

https://gitlab.com/bricka/advent-of-code-2024-rust/-/blob/main/src/days/day19.rs?ref_type=heads

The Code

use std::collections::HashMap;

use crate::solver::DaySolver;

fn parse_input(input: String) -> (Vec<String>, Vec<String>) {
    let towels = input.lines().take(1).collect::<String>().split(", ").map(|s| s.to_string()).collect();

    let designs = input.lines().skip(2).map(|s| s.to_string()).collect();

    (towels, designs)
}

fn how_many_ways(cache: &mut HashMap<String, usize>, towels: &[String], current: String, target: &str) -> usize {
    if let Some(ways) = cache.get(&current) {
        *ways
    } else if current == target {
        cache.insert(current.clone(), 1);
        1
    } else if !target.starts_with(&current) {
        cache.insert(current.clone(), 0);
        0
    } else {
        let ways = towels.iter()
            .map(|t| format!("{}{}", current, t))
            .map(|next| how_many_ways(cache, towels, next, target))
            .sum();
        cache.insert(current, ways);
        ways
    }
}

pub struct Day19Solver;

impl DaySolver for Day19Solver {
    fn part1(&self, input: String) -> String {
        let (towels, designs) = parse_input(input);

        designs.into_iter()
            .filter(|d| how_many_ways(&mut HashMap::new(), &towels, "".to_string(), d) > 0)
            .count()
            .to_string()
    }

    fn part2(&self, input: String) -> String {
        let (towels, designs) = parse_input(input);

        designs.into_iter()
            .map(|d| how_many_ways(&mut HashMap::new(), &towels, "".to_string(), &d))
            .sum::<usize>()
            .to_string()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_part1() {
        let input = include_str!("../../inputs/test/19");
        let solver = Day19Solver {};
        assert_eq!("6", solver.part1(input.to_string()));
    }

    #[test]
    fn test_part2() {
        let input = include_str!("../../inputs/test/19");
        let solver = Day19Solver {};
        assert_eq!("16", solver.part2(input.to_string()));
    }
}

[–] cabhan@discuss.tchncs.de 3 points 5 months ago (1 children)

Rust

I essentially used flood fill to collect each region. Part 1 was then relatively easy: for each point, check how many neighbors are outside of the region.

Part 2 took me forever, and I ended up looking for hints online, where I discovered that an easy way to count the number of sides is to instead count the number of corners. Doing this for "normal" corners (e.g. in a square) was relatively easy, but "reverse corners" took me a long time. Corners like here what we see in the NE corner of the first C in the third row here:

....
..C.
..CC
...C

I'm more or less happy with my solution, but my brain is now totally fried.

https://gitlab.com/bricka/advent-of-code-2024-rust/-/blob/main/src/days/day12.rs?ref_type=heads

use std::collections::HashSet;

use crate::grid::{Coordinate, Direction, Grid};
use crate::solver::DaySolver;

fn perimeter_score(c: Coordinate, grid: &MyGrid) -> usize {
    let plant_type = grid[c];

    Direction::orthogonal_iter()
        .map(|d| grid.neighbor_in_direction(c, d))
        .map(|c_opt| match c_opt {
            None => 1,
            Some(c) => if grid[c] == plant_type {
                0
            } else {
                1
            }
        })
        .sum()
}

type MyGrid = Grid<char>;

struct Region {
    #[allow(dead_code)]
    plant_type: char,
    coordinates: HashSet<Coordinate>,
}

impl Region {
    fn new(plant_type: char, coordinates: HashSet<Coordinate>) -> Region {
        Region { plant_type, coordinates }
    }

    fn iter(&self) -> impl Iterator<Item = &Coordinate> {
        self.coordinates.iter()
    }

    fn part1_score(&self, grid: &MyGrid) -> usize {
        self.coordinates.len() * self.coordinates.iter().map(|c| perimeter_score(*c, grid)).sum::<usize>()
    }

    fn part2_score(&self, grid: &MyGrid) -> usize {
        let area = self.coordinates.len();
        let sides = self.number_of_corners(grid);

        area * sides
    }

    fn number_of_corners(&self, grid: &MyGrid) -> usize {
        self.coordinates.iter().cloned()
            .map(|coordinate| {
                // How many corners do we have from here?
                // println!("Checking {}", border_coordinate);

                let corner_count = Direction::diagonal_iter()
                    .filter(|corner_direction| {
                        // Either:
                        // 1) Both neighbor directions are not 100% in the region
                        // 2) Both neighbors are in the region, but the corner itself isn't

                        let corner_in_region = match grid.neighbor_in_direction(coordinate, *corner_direction) {
                            None => false,
                            Some(c) => self.coordinates.contains(&c),
                        };

                        let both_neighbors_not_in_region = corner_direction.neighbor_directions().iter()
                            .all(|direction| match grid.neighbor_in_direction(coordinate, *direction) {
                                None => true,
                                Some(c) => !self.coordinates.contains(&c),
                            });

                        let both_neighbors_in_region = corner_direction.neighbor_directions().iter()
                            .all(|direction| match grid.neighbor_in_direction(coordinate, *direction) {
                                None => false,
                                Some(c) => self.coordinates.contains(&c),
                            });

                        both_neighbors_not_in_region || (both_neighbors_in_region && !corner_in_region)
                    })
                    .count();
                // println!("Corner count = {}", corner_count);
                corner_count
            })
            .sum()
    }
}

fn parse_input(input: String) -> MyGrid {
    input.lines()
        .map(|line| line.chars().collect())
        .collect::<Vec<Vec<char>>>()
        .into()
}

fn find_region_at(grid: &MyGrid, start: Coordinate) -> Region {
    let plant_type = grid[start];
    let mut coordinates = HashSet::new();
    let mut frontier = vec![start];

    while let Some(coordinate) = frontier.pop() {
        if grid[coordinate] == plant_type  && !coordinates.contains(&coordinate) {
            coordinates.insert(coordinate);
            frontier.extend(grid.orthogonal_neighbors_iter(coordinate));
        }
    }

    Region::new(plant_type, coordinates)
}

fn find_regions(grid: &MyGrid) -> Vec<Region> {
    let mut visited_coordinates: HashSet<Coordinate> = HashSet::new();
    let mut regions = vec![];

    for coordinate in grid.coordinates_iter() {
        if !visited_coordinates.contains(&coordinate) {
            let region = find_region_at(grid, coordinate);
            visited_coordinates.extend(region.iter().cloned());
            regions.push(region);
        }
    }

    regions
}

pub struct Day12Solver;

impl DaySolver for Day12Solver {
    fn part1(&self, input: String) -> usize {
        let grid = parse_input(input);
        let regions = find_regions(&grid);

        regions.into_iter()
            .map(|region| region.part1_score(&grid))
            .sum()
    }

    fn part2(&self, input: String) -> usize {
        let grid = parse_input(input);
        let regions = find_regions(&grid);

        regions.into_iter()
            .map(|region| region.part2_score(&grid))
            .sum()
    }
}
 

I have the feeling that over the past years, we've started seeing more TV shows that are either sympathetic towards Hell and Satan, or somewhat negative towards Heaven. I just watched "Hazbin Hotel" today, which isn't too theological, but clearly is fairly negative towards Heaven.

In "The Good Place",

Spoilers for The Good Placethe people in The Bad Place end up pushing to improve the whole system, whereas The Good Place is happy to spend hundreds of year not letting people in.

"Little Demon" has Satan as a main character, and he's more or less sympathetic.

"Ugly Americans" shows demons and Satan as relatively normal, and Hell doesn't seem too bad.

I only watched the first episode of "Lucifer", but it's also more or less sympathetic towards Lucifer.

I have a few more examples (Billy Joel: "I'd rather laugh with the sinners than cry with the saints", or the very funny German "Ein Münchner im Himmel", where Heaven is portrayed as fantastically boring), but I won't list them all here.

My question is: how modern is this? I've heard of "Paradise Lost", and I've heard that it portrays Satan somewhat sympathetically, though I found it very difficult to read. And the idea of the snake in the Garden of Eden as having given free will and wisdom to humanity can't be that modern of a thought, even if it would have been heretical.

Is this something that's happened in the last 10 years? Are there older examples? Does anyone have a good source I could read?

Note that I don't claim Satan is always portrayed positively, or Heaven always negatively :).

 

I already have a Venu Sq, and I'm looking to upgrade. My wife has a Fenix 7S and loves it, and it has some features I would like.

The Fenix 8 is now obviously out, but it's a) very expensive, b) bigger than a 7S (I have very small wrists), and c) has a microphone. I try to avoid devices with microphones, since I don't completely trust that they can't be somehow used for evil. And although I do scuba dive, I already have a Mares dive computer, so the dive functionality on the Garmin isn't quite as appealing.

I get a good deal on Garmin devices through work, and people are selling lots of used Fenix 7 watches, so I'm interested in using this as a chance to get one. But I'm a bit afraid that they'll stop getting any updates or anything soon.

How long do we think the 7 will keep getting updates? Or what's my best path forward here?

 

I just played a round of Machi Koro with a friend, and at a certain point, he was far behind. He didn't have many buildings that grant money on other people's turns, and the rest of us had also purchased a lot more red buildings than him.

I'm looking for ideas of house rules that make help provide some sort of catch-up mechanism if you're far behind. Do any of you have any tips?

If it matters, we usually play with the Harbor expansion, but are willing to play without it as well. We're already considering it because of how extreme the Tuna Boat can be.

 

Hi all! I have a Venue Sq, and I've been thinking of purchasing a new watch for quite some time. I've been mostly leaning towards a Fenix 7, since it has some more sport features, and has no microphone (the Venue 3 has a microphone, which I wouldn't use and don't really trust).

However, the Fenix 7 was announced in January 2022, and I'm wondering if there will be either Fenix 8 or at least a discount on the Fenix 7 sometime soon, so I'm hesitant to buy one now.

When are new watches usually announced? Any thoughts on whether it makes sense to wait?

 

I do not know if it's true for all countries, but at least the USA and the UK require your passport to be signed to be valid. And I know that when I fly, I sometimes get checked if it is signed.

Is there a practical reason for this? Does the signature get checked against anything? Or is it simply that the law says a passport must be signed to be valid, so there you go?

I googled around a bit, but only found resources on how to sign, but not why it needs to be signed.

Thank you Internet hive mind!

 

Ich habe vor einem Monat Miso wegen einer Idee gekauft, aber habe es nicht benutzt. Jetzt habe viel Miso, aber ich weiß nicht, was ich kochen soll.

Ich habe schon zweimal Miso Auberginen gemacht, aber der Misoschicht ist viel zu stark...ich liebe salzig und umami, aber es ist einfach zu viel.

Habt ihr irgendwelche tolle vegane oder vegetarische Ideen, wo der Miso ein bisschen weniger stark ist?

Danke!

 

As far as I am aware, grazing animals like cows or sheep poop in the same meadows where they eat grass, but presumably don't have any problems eating the grass and pooping in the same space. But if humans would eat vegetables that they had pooped on, my understanding is that we would get sick.

Why? Am I incorrect that grazing animals poop where they eat? Are their stomachs more resistant to whatever makes it dangerous?

Thank you!

 

Hallo Leute!

Ich versuche anzufangen, als Tanzlehrer als Nebenjob zu arbeiten. Ich plane ziemlich wenig zu verdienen (weniger als 1000€ im Jahr), und ich suche einem:r Steuerberater:in, von wem ich Beratung bekommen kann, was ich machen muss. Ich habe Lohi kontaktiert, aber sie bieten nur Lohnsteuererklärungen an.

Kann jemand mir einen:r Steuerberater:in empehlen?

Vielen Dank!

view more: next ›