JRaccoon

joined 2 years ago
[–] [email protected] 5 points 5 months ago (1 children)

I had one of the earlier Lumia models, maybe the 900. The software was missing many standard features (even for the time), and there were like no apps available. Edge wasn't a thing yet and instead it rocked Internet Explorer... And I don’t think there were any other browsers available, at least not in the beginning.

That said, I do remember kinda liking the UI. On PC (Windows 8) it was terrible, but it worked quite well on a device it was actually designed for. Another thing, it had a really good camera. The hardware I mean, sadly the software for it was seriously lacking, and there just weren’t any third-party camera apps available yet

[–] [email protected] 3 points 6 months ago

Kun kaikki ekstra oppituntien pitämisen päälle menee käytännössä työajan ulkopuolelle

Kuulostaa siltä, että aivan ensimmäiseksi pitäisi korjata tämä.

[–] [email protected] 1 points 6 months ago (2 children)

Kiitos, mielenkiintoista juttua. Omassa tuttavapiirissä ei perusasteen opettajia ole, joten kosketuspinta asiaan on lähinnä uutisoinnin kautta.

Itselle ehkä suurin ihmetyksen aihe on se, että jos nyt olisin opettaja ja takavarikoisin Pirkko-Petterin huuliharpun oppitunnin ajaksi ja lopulta antaisin vielä jälki-istuntoa päälle jatkuvasta opetuksen häiriköinnistä, niin mikä on pahinta mitä tästä voisi minulle seurata? Pirkon vanhemmat itkevät paikallisessa puskaradiossa että miten paska opettaja omalla kullannupulla on? Entä sitten?
Tekevät jonkinlaisen valituksen minusta? Olisiko sellaisella todellisia mahdollisuuksia menestyä?
Soittavat koulun rehtorille tai kunnan sivistystoimenjohtajalle ja haukkuvat minut? Luulisi (tai toivoisi) että kuka tahansa järkevä jättäisi tällaisen puhelun huomiotta.

Pointti ehkä lähinnä se, että ymmärrän kyllä, että opettajien auktoriteetti luokassa on rappeutunut ja keinovalikoima ylläpitää sitä supistunut, mutta jos tietyt kurinpidolliset toimet edelleen ovat mahdollisia, niin miksi opettajat eivät sitten koe voivansa tarpeen vaatiessa niitä käyttää?

[–] [email protected] 24 points 6 months ago

Pretty sure any decent model could easily solve that anyways.

True, but often these things also track the mouse movements or touch inputs and analyse those to see if they match natural human input or not. Of course advanced AI would be able to simulate proper inputs but most bots today would fail this check.

[–] [email protected] 5 points 6 months ago (5 children)

Hyvä että edistyy, mutta en vieläkään ymmärrä, että miksi tällaista asiaa pitää vatvoa eduskunnan tasolla. Voisiko joku selittää rautalangasta, että miksi ilman lakimuutosta opettaja ei yksinkertaisesti voi oppitunnin aluksi käskeä kaikkia laittamaan puhelinta taskuun/pois näkyvistä ja pitämään ne siellä oppitunnin ajan? Ja jos joku ei useasta kehotuksesta huolimatta tottele, niin käsittääkseni jälki-istuntoa saa edelleen antaa.

[–] [email protected] 31 points 6 months ago

Also, if applicable, have a different person perform the restore every time and have them do it just by following the documentation. This way multiple persons have actual experience with the process if the shit ever hits the fan and this also makes sure the documentation is accurate and up-to-date.

[–] [email protected] 20 points 6 months ago

I remember reading from somewhere that according to family he was very eager to get to vote one more time and to cast his vote for Harris. So glad he got the chance to do that before going, even though the result wasn't what he probably was hoping for.

[–] [email protected] 38 points 6 months ago* (last edited 6 months ago) (7 children)

Is it just me or does it feel that 2024 has not been a very good year in aviation safety? It seems that almost every month there's news about some major crash or incident and then of course there was the whole fiasco with Boeing

[–] [email protected] 1 points 6 months ago

You're absolutely right. Good for me then that the inputs weren't any larger

[–] [email protected] 2 points 6 months ago

TypeScript

Not very optimized code today. Basically just a recursive function

Code

import fs from "fs";

type Point = {x: number, y: number};

enum Direction {
    UP = '^',
    DOWN = 'v',
    LEFT = '<',
    RIGHT = '>'
}

const input = fs.readFileSync("./15/input.txt", "utf-8").split(/[\r\n]{4,}/);
const warehouse: string[][] = input[0]
    .split(/[\r\n]+/)
    .map(row => row.split(""));
const movements: Direction[] = input[1]
    .split("")
    .map(char => char.trim())
    .filter(Boolean)
    .map(char => char as Direction);

// Part 1
console.info("Part 1: " + solve(warehouse, movements));

// Part 2
const secondWarehouse = warehouse.map(row => {
    const newRow: string[] = [];
    for (const char of row) {
        if (char === '#') { newRow.push('#', '#'); }
        else if (char === 'O') { newRow.push('[', ']'); }
        else if (char === '.') { newRow.push('.', '.'); }
        else { newRow.push('@', '.'); }
    }
    return newRow;
});
console.info("Part 2: " + solve(secondWarehouse, movements));

function solve(warehouse: string[][], movements: Direction[]): number {
    let _warehouse = warehouse.map(row => [...row]); // Take a copy to avoid modifying the original
    const robotLocation: Point = findStartLocation(_warehouse);

    for (const move of movements) {
        // Under some very specific circumstances in part 2, tryMove returns false, but the grid has already been modified
        // "Fix" the issue ba taking a copy so we can easily revert all changes made
        // Slow AF of course but rest of this code isn't optimized either, so...
        const copy = _warehouse.map(row => [...row]);
    
        if (tryMove(robotLocation, move, _warehouse)) {
            if (move === Direction.UP) { robotLocation.y--; }
            else if (move === Direction.DOWN) { robotLocation.y++; }
            else if (move === Direction.LEFT) { robotLocation.x--; }
            else { robotLocation.x++; }
        } else {
            _warehouse = copy; // Revert changes
        }
    }

    // GPS
    let result = 0;
    for (let y = 0; y < _warehouse.length; y++) {
        for (let x = 0; x < _warehouse[y].length; x++) {
            if (_warehouse[y][x] === "O" || _warehouse[y][x] === "[") {
                result += 100 * y + x;
            }
        }
    }
    return result;
}

function tryMove(from: Point, direction: Direction, warehouse: string[][], movingPair = false): boolean {
    const moveWhat = warehouse[from.y][from.x];
    if (moveWhat === "#") {
        return false;
    }

    let to: Point;
    switch (direction) {
        case Direction.UP: to = {x: from.x, y: from.y - 1}; break;
        case Direction.DOWN: to = {x: from.x, y: from.y + 1}; break;
        case Direction.LEFT: to = {x: from.x - 1, y: from.y}; break;
        case Direction.RIGHT: to = {x: from.x + 1, y: from.y}; break;
    }

    const allowMove = warehouse[to.y][to.x] === "."
        || (direction === Direction.UP && tryMove({x: from.x, y: from.y - 1}, direction, warehouse))
        || (direction === Direction.DOWN && tryMove({x: from.x, y: from.y + 1}, direction, warehouse))
        || (direction === Direction.LEFT && tryMove({x: from.x - 1, y: from.y}, direction, warehouse))
        || (direction === Direction.RIGHT && tryMove({x: from.x + 1, y: from.y}, direction, warehouse));

    if (allowMove) {
        // Part 1 logic handles horizontal movement of larger boxes just fine. Needs special handling for vertical movement
        if (!movingPair && (direction === Direction.UP || direction === Direction.DOWN)) {
            if (moveWhat === "[" && !tryMove({x: from.x + 1, y: from.y}, direction, warehouse, true)) {
                return false;
            }
            if (moveWhat === "]" && !tryMove({x: from.x - 1, y: from.y}, direction, warehouse, true)) {
                return false;
            }
        }

        // Make the move
        warehouse[to.y][to.x] = moveWhat;
        warehouse[from.y][from.x] = ".";
        return true;
    }
    return false;
}

function findStartLocation(warehouse: string[][]): Point {
    for (let y = 0; y < warehouse.length; y++) {
        for (let x = 0; x < warehouse[y].length; x++) {
            if (warehouse[y][x] === "@") {
                return {x,y};
            }
        }
    }

    throw new Error("Could not find start location!");
}

[–] [email protected] 4 points 6 months ago (1 children)

TypeScript

Part 2 was a major curveball for sure. I was expecting something like the grid size and number of seconds multiplying by a large amount to make iterative solutions unfeasible.

First I was baffled how we're supposed to know what shape we're looking for exactly. I just started printing out cases where many robots were next to each other and checked them by hand and eventually found it. For my input the correct picture looked like this:

The Christmas treePicture

Later it turned out that a much simpler way is to just check for the first time none of the robots are overlapping each other. I cannot say for sure if this works for every input, but I suspect the inputs are generated in such a way that this approach always works.

The code

import fs from "fs";

type Coord = {x: number, y: number};
type Robot = {start: Coord, velocity: Coord};

const SIZE: Coord = {x: 101, y: 103};

const input: Robot[] = fs.readFileSync("./14/input.txt", "utf-8")
    .split(/[\r\n]+/)
    .map(row => /p=(-?\d+),(-?\d+)\sv=(-?\d+),(-?\d+)/.exec(row))
    .filter(matcher => matcher != null)
    .map(matcher => {
        return {
            start: {x: parseInt(matcher[1]), y: parseInt(matcher[2])},
            velocity: {x: parseInt(matcher[3]), y: parseInt(matcher[4])}
        };
    });

console.info("Part 1: " + safetyFactor(input.map(robot => calculatePosition(robot, SIZE, 100)), SIZE));

// Part 2
// Turns out the Christmas tree is arranged the first time none of the robots are overlapping
for (let i = 101; true; i++) {
    const positions = input.map(robot => calculatePosition(robot, SIZE, i));
    if (positions.every((position, index, arr) => arr.findIndex(pos => pos.x === position.x && pos.y === position.y) === index)) {
        console.info("Part 2: " + i);
        break;
    }
}

function calculatePosition(robot: Robot, size: Coord, seconds: number): Coord {
    return {
        x: ((robot.start.x + robot.velocity.x * seconds) % size.x + size.x) % size.x,
        y: ((robot.start.y + robot.velocity.y * seconds) % size.y + size.y) % size.y
    };
}

function safetyFactor(positions: Coord[], size: Coord): number {
    const midX = Math.floor(size.x / 2);
    const midY = Math.floor(size.y / 2);

    let quadrant0 = 0; // Top-left
    let quadrant1 = 0; // Top-right
    let quadrant2 = 0; // Bottom-left
    let quadrant3 = 0; // Bottom-right

    for (const {x,y} of positions) {
        if (x === midX || y === midY) { continue; }

        if (x < midX && y < midY) { quadrant0++; }
        else if (x > midX && y < midY) { quadrant1++; }
        else if (x < midX && y > midY) { quadrant2++; }
        else if (x > midX && y > midY) { quadrant3++; }
    }

    return quadrant0 * quadrant1 * quadrant2 * quadrant3;
}

[–] [email protected] 2 points 6 months ago

Java

Today was pretty easy one but for some reason I spent like 20 minutes overthinking part 2 when all it needed was one new else if. I initially through the concatenation operator would take precedence even tho it clearly says "All operators are still evaluated left-to-right" in the instructions..

I'm sure there are optimizations to do but using parallelStreams it only takes around 300ms total on my machine so there's no point really

The code

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;

public class Day7 {
    public static void main(final String[] _args) throws IOException {
        final List<Equation> equations = Files.readAllLines(Path.of("2024\\07\\input.txt"), StandardCharsets.UTF_8).stream()
            .map(line -> line.split(":\\s"))
            .map(line -> new Equation(
                    Long.parseLong(line[0]),
                    Arrays.stream(line[1].split("\\s"))
                        .map(Integer::parseInt)
                        .toArray(Integer[]::new)
                )
            ).toList();

        final char[] part1Operators = {'+', '*'};
        System.out.println("Part 1: " + equations.parallelStream()
            .mapToLong(equation -> getResultIfPossible(equation, part1Operators))
            .sum()
        );

        final char[] part2Operators = {'+', '*', '|'};
        System.out.println("Part 2: " + equations.parallelStream()
            .mapToLong(equation -> getResultIfPossible(equation, part2Operators))
            .sum()
        );
    }

    private static Long getResultIfPossible(final Equation equation, final char[] operators) {
        final var permutations = Math.pow(operators.length, equation.values.length - 1);
        for (int i = 0; i < permutations; i++) {
            long result = equation.values[0];
            int count = i;

            for (int j = 0; j < equation.values.length - 1; j++) {
                // If the result is already larger than the expected one, we can short circuit here to save some time
                if (result > equation.result) {
                    break;
                }

                final char operator = operators[count % operators.length];
                count /= operators.length;

                if (operator == '+') { result += equation.values[j + 1]; }
                else if (operator == '*') { result *= equation.values[j + 1]; }
                else if (operator == '|') { result = Long.parseLong(String.valueOf(result) + String.valueOf(equation.values[j + 1])); }
                else {
                    throw new RuntimeException("Unsupported operator " + operator);
                }
            }

            if (result == equation.result) {
                return result;
            }
        }

        return 0L;
    }

    private static record Equation(long result, Integer[] values) {}
}

view more: ‹ prev next ›