Any adventofcode participants?

Since I know that a few of you are engineers and/or programmers, is there anyone who’s participating in this year’s adventofcode?

2 Likes

Sadly my skills in coding have deteriorated quite a bit, as I haven’t been coding a lot during the last few years. Time is also a factor.
I wish I had enough skill and time to do such things again. 15 years ago I was all over that kind of stuff.

3 Likes

If any of you want to talk about implementations or just want to backseat drive with me, I’m uploading my sources at GitHub - yetyetanotherusername/adventofcode2022: solutions for the 2022 edition of adventofcode.

1 Like

Nice.

I haven’t got a compiler active on anything at the minute so will gladly come along for the ride. I marvel at the ingenuity some people have to create things for fun on the internet. I checked some of the scenarios and they are quite complicated.

Some of the examples seemed to click with me for potential solutions, some I struggled to even think of a starting point, but I guess a lot is based on our experience

1 Like

These coding challenges are really humbling. The quickest I managed on one of the easier problems was 26 minutes and I barely made the top 11000. The winner for that day took barely over a minute to solve it. That is insane, I can’t even read the damn problem statement that quick.

2 Likes

Never heard of this, but looks cool! I’ll check out the site later

1 Like

Checked out the site - really cool idea/game. Questions remind me of my interview with Garmin…
Too much work to do before Christmas to get involved, but next year I will have a lot of time

1 Like

Well the good part is, you don’t have to solve them the day they come out, unless you really care about what place you finish on. You can still do the puzzles from, say, 2016, there’s really no stress to it unless you pressure yourself.

2 Likes

Nice and challenging. Just completed todays puzzle.

Took me many hours, but it was welcome training for my now bit rusty problem solving skills in Python. Just going to paste it here for review :smile:

The code was developed/run in Jupyter Notebook, so no input data loading. Instead it has to be preloaded in input_data variable.

from collections import namedtuple, Counter
from itertools import chain, product, starmap, islice
import math
from functools import partial

Coords = namedtuple('Coords', 'x y')

def process_row(row):
    direction, count = row.split(" ")
    return direction * int(count)

input_rows = input_data.strip().splitlines()
head_directions = chain.from_iterable(map(process_row, input_rows))

OFFSETS = {
    'R': Coords(1, 0),
    'L': Coords(-1, 0),
    'U': Coords(0, 1),
    'D': Coords(0, -1),
}

def location_in_dir(origin: Coords, direction):
    offset = OFFSETS[direction]
    return Coords(origin.x + offset.x, origin.y + offset.y)

def directed_locations(origin: Coords, directions):
    loc = origin
    yield loc
    for d in directions:
        loc = location_in_dir(loc, d)
        yield loc

def neighbours(center: Coords):
    neighbors = starmap(Coords, product(*[[-1, 0, 1]] * 2))
    return {Coords(center.x - n.x, center.y - n.y) for n in neighbors}

def aligned(loc1, loc2):
    return loc1.x == loc2.x or loc1.y == loc2.y
    
def follow_locations(origin: Coords, lead_locations):
    loc = origin
    for lead_loc in lead_locations:
        if lead_loc not in neighbours(loc):
            contacts = neighbours(loc) & neighbours(lead_loc)
            contacts = sorted(contacts, reverse=True, key=partial(aligned, lead_loc))
            loc = contacts[0]
        yield loc

def knots_generator(origin, locations):
    while True:
        locations = follow_locations(origin, locations)
        yield locations

head_locations = directed_locations(Coords(0, 0), head_directions)
knots = knots_generator(Coords(0, 0), head_locations)
tail, = islice(knots, 8, 9)

len(Counter(tail))
3 Likes

Holy cow did I make this hard on myself. I shouldn’t do these in the evening after hacking c++ all day. I had to put the training wheels on and make this as readable as possible so my brain could still comprehend it.

import math


class Coordinate:
    def __init__(self):
        self.x = 0
        self.y = 0


class State:
    def __init__(self):
        self.state = [Coordinate() for _ in range(10)]


def parse(filename: str) -> list[str]:
    with open(filename, "r") as file:
        return file.read().split("\n")


def euclidean_distance(this: Coordinate, other: Coordinate) -> float:
    return math.sqrt((this.x - other.x) ** 2 + (this.y - other.y) ** 2)


def norm(num: int):
    if num == 0:
        return 0
    elif num > 0:
        return 1
    else:
        return -1


def follow(state: State):
    for idx in range(0, 9):
        d2 = euclidean_distance(state.state[idx + 1], state.state[idx])
        if d2 > math.sqrt(2):
            pull_vector = (
                state.state[idx].x - state.state[idx + 1].x,
                state.state[idx].y - state.state[idx + 1].y,
            )

            state.state[idx + 1].x += norm(pull_vector[0])
            state.state[idx + 1].y += norm(pull_vector[1])


def up(state: State):
    state.state[0].x += 1


def left(state: State):
    state.state[0].y -= 1


def down(state: State):
    state.state[0].x -= 1


def right(state: State):
    state.state[0].y += 1


def apply_command(state: State, command: str, tail_positions: list[tuple[int, int]]):
    direction, distance = command.split(" ")

    match direction:
        case "U":
            function = up
        case "L":
            function = left
        case "D":
            function = down
        case "R":
            function = right
        case _:
            raise Exception("Unknown direction!")

    for _ in range(int(distance)):
        function(state)
        follow(state)
        tail_positions.append((state.state[9].x, state.state[9].y))


def main():
    state = State()
    tail_positions = [(0, 0)]
    lines = parse("data.txt")

    for line in lines:
        if line == "":
            break
        apply_command(state, line, tail_positions)

    print(len(list(set(tail_positions))))


if __name__ == "__main__":
    main()

@UncleZam Nice usage of builtins, you certainly made this very concise and elegant.

2 Likes

Thanks, I have been trying to do data driven solving with all kinds of language features available (iterators, generators, functional tools, etc.)

From your Github repo I noticed your nice use of Numpy features. Numpy (with all its accessories) is so powerful in expression and also performance. For me it is just so easy to forget all the Numpy tricks and programming style if not using it for a while :sweat_smile:

2 Likes

Yeah, though it can get very hard to read. I tried solving last year’s puzzles completely vectorized in numpy but I gave up after 4 because it got too hard to do without writing tests. This year I’ve been following the KISS paradigm and it’s been much more fun that way, though I do like making stuff performant, but at a certain point it just takes too much time.

2 Likes

Just quickly read your solution in the comment and for me it seems very nice and concise.

Nowadays I really appreciate code that’s to the point without unnecessary boilerplate. I think you managed that very well :+1:

1 Like

angry stop GIF

One thing that I’ve really come to appreciate at my new company (and since getting back into c++) is using pyright together with type hints. Untyped python is the devils plaything.

True in that. It is kind of must for professional development. I have the most experience in Mypy, which use to be the goto type checker. Probably should give pyright a spin too.

My C++ skills date back to 2005, I bet a lot has changed since. Now, Rust could be interesting competition to C++ as I heard even Linux community is embracing it.

2 Likes

Yeah, although the learning curve is supposed to be steep, but memory safety! We’re kind of locked into C++ at work because we use JUCE. But even so, were at C++17 and that’s a completely different animal with all the RAII stuff going on. Smartpointers asf. It really has gotten a lot better. But the syntax is just kind of borked in so many ways.

That’s why I’m really curious about how carbon will turn out. Google wants it to be what TypeScript is to JS.

2 Likes

I’d say today’s puzzle was the best so far. You have to simulate a CRT monitor, that was a nice touch. Would have been over quickly too if I hadn’t put in a stupid off-by-one error.

1 Like

Good to hear, I will take a look at it in the evening.

What I nice puzzle the number 10 was. I guess mixing of 0 and 1 based indexing was done intentionally to confuse poor coder :thinking:. CRT part was fun, but I had to read the instructions ten times to get all the details right.

I wanted to experiment and export the Jupyter Notebook as markdown and paste here in its whole glory to show off how nice Jupyter is. The exported markdown seems to work perfectly on this messaging platform (below):

Framework

from copy import copy
from itertools import repeat, islice
from pathlib import Path
from types import SimpleNamespace

def noop(regs):
    yield
    
def addx(regs, value: int):
    yield
    yield
    regs.x += value
    
def cpu(program):
    registers = SimpleNamespace(x=1)
    yield copy(registers) # Zero step padding
    
    def execute(instruction):
        for cycle in instruction:
            yield copy(registers)
        
    for line in program:
        match line.split():
            case ['noop']:
                yield from execute(noop(registers))
            case ['addx', value]:
                yield from execute(addx(registers, int(value)))
            case _:
                raise RuntimeError

Puzzles

Input data

program_txt = Path("program.txt").read_text()
program_lines = program_txt.strip().splitlines()

Solution 1

states = cpu(program_lines)
sum(cycle*state.x for cycle, state in islice(enumerate(states), 20, None, 40))
13180

Solution 2

states = cpu(program_lines)
next(states)  # ignore zero index state
for _ in range(6):
    row_states = islice(states, 40)
    crt_char = lambda crt_x, sprite_x: '#' if abs(crt_x - sprite_x) < 2 else '.'
    print("".join(crt_char(crt, sprite.x) for crt, sprite in enumerate(row_states)))
####.####.####..##..#..#...##..##..###..
#.......#.#....#..#.#..#....#.#..#.#..#.
###....#..###..#....####....#.#..#.###..
#.....#...#....#....#..#....#.####.#..#.
#....#....#....#..#.#..#.#..#.#..#.#..#.
####.####.#.....##..#..#..##..#..#.###..
1 Like

So what exactly is Jupyter? Web based IDE? Don’t laugh, but as embedded guy I still use ‘C’. Well, last project was in rust, but jury still out on that.

Congrats on solving puzzle. Nice solution from what I read.

1 Like