#AoC 2022 | Day 10 | Solutions & Spoilers

1841 messages · Page 2 of 2 (latest)

sweet mango
#

J looks like ```
..##.
...#.
...#.
...#.
#..#.
.##..

quasi minnow
#

I, X, V, W, and Y all don't have proper forms AFAIK

#

K and H are fair though

frank kayak
#

You have a moving pointer and a theoretically infinite strip (if you make the width more than 40) though.

nimble shuttle
quasi minnow
#

Yes but you can't read or loop

nimble shuttle
#

exactly

frank kayak
#

True I guess

nimble shuttle
frank kayak
#

If you could read though I don't think you'd have to have a dedicated loop here for it to be turing complete

#

As it resets its position at the end of the screen each time anyway

nimble shuttle
#

as long as you can't create a finite program with an infinite runtime, it's not turing complete

quasi minnow
#

There's no looping or branching, it's not turing complete

light vortex
#

impossible, as you can not disable the first pixel, no matter what you do. X is 1 at the start, and it takes at least 2 ops to change that, in that time, this pixel is already drawn.

my conclusion, might be faulty

#

@hollow void

hollow void
#

yes, youa re right

frank kayak
nimble shuttle
#

what looping lmao

#

no there isn't

hollow void
#

but if you ignore the frst 4 pixels?

nimble shuttle
light vortex
hollow void
frank kayak
quasi minnow
#

But the PC doesn't loop

sweet mango
#

why would the counter reset?

nimble shuttle
#

fr just read the wiki page on turing machines lmaocry

frank kayak
nimble shuttle
#

we can't discuss turing completeness if you don't know what it means

sweet mango
#

but part 1 relies on the counter not resetting

nimble shuttle
#

it's possible

#

i could even write a program that generates the instructions for any given image (excluding starting pixels)

hollow void
nimble shuttle
#

set the sprite to somewhere away from the beam or at the beam 2 cycles ahead

#

not that hard

hollow void
#

I'd prove it in this way:
I can freely update x every 2 pixels.

#

This way, I need to be able to draw all 4 combinations every 2 cycles

nimble shuttle
#

yeah, and you can position the sprite for any combo of the 2 pixels

hollow void
#

#., .., .# and ##

quasi minnow
#

But is it possible if width isn't divisible by 2 though

nimble shuttle
#

you can just use a noop

#

wait

#

actually maybe not

quasi minnow
# nimble shuttle yes

I don't think it is

(some rows, so you can choose the value of X)
# # # # #
# # # # #
#

I don't think it's possible to render that pattern

#

Without a dedicated blanking period anyway

nimble shuttle
#

yeah i think you're right

vernal urchin
#

I tried writing a thing to generate the code for a given output string, and well my brain hurts i am giving up

nimble shuttle
#

rip

half mirage
#

Just caught up on all my AoC - did all Day 9 and Day 10 today

#

Day 10 probably my fave day, though the off-by-one errors are not fun

#

QQ - in the Python match-case syntax, is there a way to cast a matched value to a different type from within the case statement? Or do you have to cast afterwards

quasi minnow
#

I think you have to cast after binding

naive sun
nimble shuttle
#

me3

half mirage
#

right, I did wonder - good to know :)

#

Also only 4 classes for today's solution

nimble shuttle
#

my solution had 0 thinking_derp

hollow void
#

mine had 1 function

hollow void
half mirage
# hollow void java user spotted

Actually, true story, the first time I learned Java, I was lying on my bed reading the first chapter of a Java book, and fell asleep reading it

quasi minnow
#

Lmao

naive sun
#

What the cat??
Look at the tests for trying to cast in a case -
I would have expected it to be a syntax error - But it's actually changing the results...
https://github.com/shenanigansd/scratchpad/commit/0c20735eba3fc0031de1b7b773290e640e271a8c
https://github.com/shenanigansd/scratchpad/actions/runs/3665655477/jobs/6196870308

=================================== FAILURES ===================================
_______________________________ test_run_cycles ________________________________

    def test_run_cycles() -> None:
        cycles = run_cycles(EXAMPLE_INPUT)
    
>       assert cycles[20] * 20 == 420
E       assert (1 * 20) == 420

2022/10/python/test_day10.py:156: AssertionError
=========================== short test summary info ============================
FAILED 2022/10/python/test_day10.py::test_run_cycles - assert (1 * 20) == 420
========================= 1 failed, 36 passed in 0.17s =========================
hollow void
#

amazon: "often bought together: Data Structures in Java - rope - stepladder"

naive sun
half mirage
#

Every time I tried to use a cast in a case statement, Pytest freaked the fuck out

#

it did NOT like me doing that

half mirage
#

ofc I can't recreate it now 🙃

#

it was this 50 line error

naive sun
#

Huh
For me all it's doing is making it to where x is always 1, and stopping after 35 cycles for some reason

chilly plank
hollow void
#
def day10(inp: str) -> tuple[int, str]:
    xhist = [1]
    for i in inp.strip().split("\n"):
        match i.split(" "):
            case "noop",:
                xhist.append(xhist[-1])
            case "addx", val:
                xhist.append(xhist[-1])
                xhist.append(xhist[-1] + int(val))
    gsm = 0
    for i in [20, 60, 100, 140, 180, 220]:
        gsm += i * xhist[i - 1]
    data = []
    for i, j in enumerate(xhist):
        data.append((i % 40 - j) in (0, 1, -1))
    for j, i in enumerate(data):
        print("\u2588\u2588" if i else "  ", end = "")
        if j % 40 == 39:
            print()
    deeta = input("\b\bWhat can you read?\n> ").strip().upper()
    if deeta.isalpha() and deeta.isascii() and len(deeta) == 8:
        return (gsm, deeta)
    print("Misinput, aborting...")
    raise ValueError("Invalid input")```
chilly plank
#

pithink

In [5]: a = ["addx", "3"]

In [6]: match a:
   ...:     case ["addx", int(x)]:
   ...:         print('int')
   ...:     case ["addx", x]:
   ...:         print('other')
   ...: 
other
#

seems to be a constraint, yeah

nimble shuttle
#

makes sense

naive sun
#

OH

#

ic

hollow void
#

!e py match 4: case int(a): print(a) case _: pass

#

yep

violet pondBOT
#

@hollow void :white_check_mark: Your 3.11 eval job has completed with return code 0.

4
hot panther
#

Anyone else's solution missing seemingly one pixel?

#

I mean clearly this is legible but that first Z is killing me

#

Ok figured it out. x at this point is -1, so my x % 40 check is yielding 39 which causes the pixel not to be drawn

quasi minnow
#

This is perhaps too high-resolution

#

(it's not even done encoding yet)

#

190M lines, 1.4G

#

Yikes

bright quarry
chilly plank
#

typod cast into case

#

I don't think case statements ever does a cast

half mirage
#

my robust unit testing caught this for me though :)

coral sorrel
#

I have poked at mine a bit and I can't get the little errors to go away

half mirage
#

today is really easy for off by one errors

#

I had to really think about exactly the error I was getting and what I needed to do

coral sorrel
#

I just can't see it 😅

half mirage
#

If you'd like, I'd be happy to have a look at your code once I finish polishing my unit tests :)

coral sorrel
#

Sure

#

It's only four pixels that are wrong as far as I can see

#

(spoilered for answer)

sweet mango
#

Everyone has a different answer

pseudo crane
#

guys what is tricky about this task because i think im missing out on sth that is important

sweet mango
#

An understanding of crt beams is important

pseudo crane
#

ehmm i dont know what that means

#

im talking about part 1 btw

half mirage
#

For me, it helped just being very regimented in coding part 1

sweet mango
#

Do you know how ticks work?

coral sorrel
pseudo crane
#

not sure what ure talking about haha

#

but i can say how i understand it

half mirage
#

you really have to read part 1, IMO. It's not difficult, but getting the precise details just right can be tricky

pseudo crane
#

everytime there is addx i add the value to the "queue"

#

that has to wait 2 cycles to be added to the x

coral sorrel
#

The 'tricky' bit in part 1 is that the updating register operation takes two cycles

sweet mango
#

I just realized our "communication device" is a pager

pseudo crane
#

then it goes onto the next value in the queue

coral sorrel
#

so you might have to read the answer in the middle of it

wispy topaz
pseudo crane
#

so if there is something waiting to be added i dont read the values from addx?

sweet mango
#

When do we get the challenge that becomes O(n^x) if we do it wrong?

wispy topaz
sweet mango
#

I implemented mine using lots of generators.

pseudo crane
#

what do you mean by start over

wispy topaz
#

get next input

pseudo crane
#

so forget about what was before?

wispy topaz
#

noop is no op aka no operation.

sweet mango
#

basically pass

#

I did mine kind of like this. ```py
registers = {"X": 1}

def noop():
yield

def addx(value):
yield
yield
registers["X"] += value

opcodes = {
"noop": noop,
"addx": addx,
}

def run(data):
counter = 0
for line in data.splitlines():
oc, *args = line.split()
args = [*map(int, args)]
for _ in opcodesoc:
counter += 1

pseudo crane
#

i feel so dumb XD

#

i have no clue what u guys mean with this noop

wispy topaz
#

I just did a for loop.
for cycles in range(2)
if noop break
else
update x

sweet mango
#

noop is short for no operation

pseudo crane
#

i dont understand what does it change

sweet mango
#

noop does nothing.

wispy topaz
pseudo crane
#

ye i know

#

but i get correct answer for the example

#

up to 20 cycles

#

then i get the wrong value of x on other cycles

wispy topaz
pseudo crane
#
    x = 1
    cycles_to_register = [20+(x * 40) for x in range(6)]
    addx = []
    num_of_cycles = 0
    for cycle in file:
        num_of_cycles += 1 
        cycle = cycle.strip().split(" ")
        if cycle[0].startswith("a"):
            v = int(cycle[1])
            addx.append([v,2])
            addx[0][1] -= 1

        if addx[0][1] == 0:
            x += addx.pop(0)[0]
    
            
        if num_of_cycles in cycles_to_register:
            print(x*num_of_cycles)
#

maybe you can take a look

wispy topaz
pseudo crane
#

on cycle 20 x is 21 for me

#

and its correct

wispy topaz
#

why do you have a list addx ?

wispy topaz
pseudo crane
#

addx is my so called queue

#

which some1 said doesnt have a place here

#

i store every value from addx there

wispy topaz
#

there is no queue. it's 2 cycles and then add.

#

no need to queue anything, your queue will never have more than 1 item

#

well maybe if you never take anything off of the queue it will act as a history.

pseudo crane
#

so for example

#

if i have
addx2
noop
noop
addx 3
addx 5
noop

#

what should the x be

#

4?

wispy topaz
#

but it will be:

queue is empty
cycle
read input
if addx: add to queue
cycle
remove from queue
queue is empty
wispy topaz
pseudo crane
#

ohhhh

#

i think i get it

#

so just correct me if im wrong now

#

when i read addx 2

#

i add 2 to cycles count

#

and add 2 to the x

#

and then move on to the next line

wispy topaz
#

sort of

pseudo crane
#

haha

wispy topaz
#

it's impoartnt that you understand that it's:

if addx:
+1cycle
+1cycle

and not:

if addx:
+2cycle
coral sorrel
#

⬆️

wispy topaz
#

there is stuff happening during each cycle.

#

and 1 thing happening after both cycles, but not during the cycle. 🙂

chilly plank
#

there is the option of replacing the 2 cycle addx with a noop + 1 cycle addx

coral sorrel
#

Like the issue I suspect is that at some point one of the points you have to read at happens in the middle of an addx

#

and the register is only changed on the second cycle of the addx

coral sorrel
#

yes, sorry

pseudo crane
#

so whats the difrence in

#
            for _ in range(2):
                num_of_cycles += 1
#

from

#
if cycle[0].startswith("a"):
            num_of_cycles += 2
#

if after reading addx 3

#

i have to wait 2 cycles for the 3 to be addex to x

#

what can happen during this 2 cycles that addx 3 takes to complete

wispy topaz
pseudo crane
#

ok i think i got it

#

thanks a lot ;d

#

i know why it mattered

#

at least i think so

#

because while addx is happening it may be cycle 20 that i have to register

#

and if i just added 2 cycles i may never be on cycle 20

stark quest
#

Dumb question, but im trying to figure out my loop condition, we need to read through every command in the list, but we also need to keep going until we read through all the cycles right?

pseudo crane
#

how the hell do i get correct signal strengths on all cycles except 220

bright quarry
pseudo crane
#

i got it

#

thank you to every1 who helped me

#

hopefully i get part2 without problems XD

half mirage
#

Just finished my code and test refactoring for today

#

Tests have 673 lines 👀

#

My code for today:

import collections
from collections.abc import Iterator, Container
import dataclasses
import enum
import itertools


class CycleState(enum.Enum):
    START = enum.auto()
    DURING = enum.auto()
    AFTER = enum.auto()


@dataclasses.dataclass(frozen=True)
class Cycle:
    no: int
    state: CycleState


@dataclasses.dataclass
class Instr:
    cycle_no: int
    add_val: int

    def decrement_cycle(self) -> None:
        self.cycle_no -= 1


class CathodeRayTube:
    def __init__(self, program: str, watch_cycles: Container[Cycle] = ()) -> None:
        self.program = collections.deque(program.splitlines())

        self.register = 1

        self._cycle_gen = self._cycle_gen_fn()
        self.cycle: Cycle

        self.instr: Instr | None = None

        self._watch_cycles = watch_cycles
        self.watched_cycles: dict[Cycle, int] = {}

        self.screen = ""

    @classmethod
    def read_file(cls, watch_cycles: Container[Cycle] = ()) -> "CathodeRayTube":
        with open("input.txt") as f:
            return cls(f.read(), watch_cycles=watch_cycles)

    @staticmethod
    def _cycle_gen_fn() -> Iterator[Cycle]:
        for x in itertools.count(1):
            for y in CycleState:
                yield Cycle(x, y)

    def _increment_cycle(self) -> None:
        self.cycle = next(self._cycle_gen)

    def _parse_instr(self, instr_text: str) -> None:
        match instr_text.split():
            case ["noop"]:
                instr = Instr(cycle_no=1, add_val=0)
            case ["addx", add_val]:
                instr = Instr(cycle_no=2, add_val=int(add_val))
            case _:
                raise Exception("Unexpected instruction")
        self.instr = instr

    def _execute_pre_cycle(self) -> None:
        if self.instr is None:
            try:
                instr_txt = self.program.popleft()
            except IndexError as exc:
                raise StopIteration from exc
            self._parse_instr(instr_txt)

    def _execute_mid_cycle(self) -> None:
        if ((self.cycle.no - 1) % 40) in (
            self.register - 1,
            self.register,
            self.register + 1,
        ):
            self.screen += "#"
        else:
            self.screen += "."

        if self.cycle.no % 40 == 0:
            self.screen += "\n"

    def _execute_post_cycle(self) -> None:
        assert self.instr
        self.instr.decrement_cycle()
        if self.instr.cycle_no == 0:
            self.register += self.instr.add_val
            self.instr = None

    @property
    def signal_strength(self) -> int:
        return self.cycle.no * self.register

    def __iter__(self) -> "CathodeRayTube":
        return self

    def __next__(self) -> int:
        self._increment_cycle()

        cycle_fns = {
            CycleState.START: self._execute_pre_cycle,
            CycleState.DURING: self._execute_mid_cycle,
            CycleState.AFTER: self._execute_post_cycle,
        }

        cycle_fns[self.cycle.state]()

        if self.cycle in self._watch_cycles:
            self.watched_cycles[self.cycle] = self.signal_strength

        return self.signal_strength


def main() -> None:
    key_cycles = [
        Cycle(no=20, state=CycleState.DURING),
        Cycle(no=60, state=CycleState.DURING),
        Cycle(no=100, state=CycleState.DURING),
        Cycle(no=140, state=CycleState.DURING),
        Cycle(no=180, state=CycleState.DURING),
        Cycle(no=220, state=CycleState.DURING),
    ]

    crt = CathodeRayTube.read_file(watch_cycles=key_cycles)

    for _ in crt:
        pass

    print(
        "Sum of interesting signal strengths:",
        sum(crt.watched_cycles.values()),
        end="\n\n",
    )
    print("Screen:\n")
    print(crt.screen)


if __name__ == "__main__":
    import timeit

    print(timeit.timeit(main, number=1))
naive sun
#

Why?

sweet mango
#

when your tests are longer than your actual program.

mossy dock
#

I think I'm missing the first column but well it worked

half mirage
#

You’ll see if you have a look

mossy dock
#

I think they mean why did you have to make it that long lol

half mirage
#

I had to make it that long to fit all the test cases

#

I want to be able to assert every detail given in the problem description about the test inputs

#

Part 2 has a crap ton of test cases though

#

20 cycles * 3 cycle stages (before, during, after) leads to around 60 cases to assert just for part 2

naive sun
#

I still don't even understand how it works

#

I'm opening up the docs just to figure out what a Container is

chilly plank
#

I had a weird solution for dealing with part 1, but otherwise my dist code is straightforward

fn solve(input: &[Command]) -> AocResult<(i32, String)> {
  use Command::*;

  let mut res = 0;

  let mut cycle = 0;
  let mut x = 1;

  let mut display = vec![];
  let mut draw = |pos, x| {
    display.push(pos - 1 <= x && x <= pos + 1);
  };

  for cmd in input {
    let prev_cycle = cycle;
    let prev_x = x;

    match cmd {
      Noop => {
        draw(cycle % 40, x);
        cycle += 1;
      }
      Addx(arg) => {
        draw(cycle % 40, x);
        cycle += 1;
        draw(cycle % 40, x);
        cycle += 1;
        x += arg;
      }
    }

    if (20 + prev_cycle) % 40 > (20 + cycle) % 40 {
      let aligned = cycle - cycle % 20;
      res += aligned * prev_x;
    }
  }

  let display = display
    .chunks_exact(40)
    .map(|row| {
      row
        .iter()
        .map(|b| if *b { '#' } else { '.' })
        .collect::<String>()
    })
    .join("\n");

  Ok((res, format!("\n{display}")))
}
#

parsing code left out, it's not too interesting

chilly plank
#

just parses the thing into commands, rust enums are neat

pub enum Command {
  Addx(i32),
  Noop,
}
half mirage
#

I pass in a list in one place, and dict.keys() in another, both of which support doing an “in” check

#

That means they both use __contains__, so they are both a Container

chilly plank
half mirage
naive sun
violet pondBOT
#

day_10/process.py lines 136 to 142

print(
    "Sum of interesting signal strengths:",
    sum(crt.watched_cycles.values()),
    end="\n\n",
)
print("Screen:\n")
print(crt.screen)```
`day_10/test.py` line 5
```py
LONG_PROGRAM = """\```
`day_10/test.py` line 157
```py
program = """\```
half mirage
#

And the constant is just because I have that long program in two test functions and didn’t want a copy paste of it

#

And hey, my code is understandable! XD

#

More than the golf courses that’s for sure

naive sun
chilly plank
half mirage
#

I am verbose I admit

naive sun
chilly plank
naive sun
#

necessarily

#

yeah

half mirage
#

I could stand to turn it down a notch I admit

#

Mostly with the variable names though

naive sun
#

nah, this is fine

stark quest
#

using the test input, for some reason mine gets the first two but thats it

cycle, val, cycle*x
20 21 420
60 19 1140
100 17 1700
140 30 4200
180 16 2880
220 18 3960
naive sun
#

Well, actually, no
Instr is bad
Don't shorten variable names
Not verbose enough

stark quest
#

the vals are wrong as well

half mirage
naive sun
half mirage
#

Yup that’s the joke I had in mind 😂

#

Had to deal with two of those today

naive sun
#

You too!?

half mirage
#

With all the testing I did, I still got an off by one error afterwards 😂

#

But I quickly found it

stark quest
#

to interject

half mirage
#

Have you worked out the error or still trying to figure it out?

stark quest
#

i got it

#

i init'ed my cycle count at 1 for some reason

#
def check_cycle(cycle, x):
    if cycle % 40 == 20: 
        return cycle * x
    return 0

def part_one():
    with open("day10/instructions.txt", "r") as f:
        instructions = f.read().split('\n')

    x = 1
    cycle = 0
    strength = 0

    for i in instructions:
        if 'addx' in i.split():
            _, val = i.split()

            cycle += 1
            strength += check_cycle(cycle, x)

            cycle += 1
            strength += check_cycle(cycle, x)

            x += int(val)
        else:
            cycle += 1
            strength += check_cycle(cycle, x)
    print(strength)
chilly plank
#

to give some criticism, I see a bunch of methods that are used once and do trivial work

e.g. _increment_cycle should just be inlined in the one place it's called imo

read_file is a paper thin wrapper around the constructor with a file hard coded, why not just read the file and pass the string to the constructor in main?

wispy topaz
stark quest
#

yeah i fixed it

#

accidently defined cycle = 1

quasi minnow
#

Lmao that'll do it

half mirage
#

And yes, read_file absolutely doesn’t have to be a class method, it could be a separate one

#

But I like alternative initialisers :)

pseudo crane
#

@wispy topaz thanks a lot at part 2 i understood even more why making it 2 seperate cycles is that important

#

but you made me really understand this problem

chilly plank
#

alternative initializers are fine, but having one that just reads from a hard coded file is very weird from a usability standpoint

wispy topaz
chilly plank
#

something like this would make more sense

def make_crt_from file(fname):
  ...
#

(though I would call also that overkill, but that's more in opinion land)

half mirage
#

I just have it hardcoded cos I know I’ll only read from one file ever in this case

chilly plank
#

you don't run the samples from file?

wispy topaz
half mirage
quasi minnow
wispy topaz
stark quest
half mirage
wispy topaz
chilly plank
#

I tend to opt to keep things as simple as possible, no extravagant structures unless they are obviously good ideas from the beginning

#

During writing patterns tend to emerge and you can factor pieces out

quasi minnow
#

^

#

People spout DRY but they need to consider WET

#

('Write Everything Twice', the principle that your code is actually fairly likely to diverge if you've only had to write it twice)

half mirage
#

I am definitely overengineering my code for these puzzles, that’s for sure

chilly plank
#

Oh, I do try to follow DRY, but things that repeat tend to become very obvious as you write code

half mirage
#

But the reason that the structures are there are so the unit tests work nicely

quasi minnow
wispy topaz
# quasi minnow ^

There's also the concept of reasonable numbers. The only reasonable numbers in computer science are 0, 1 and inf. 🙂

quasi minnow
#

If the code is for two different things that just look similar, that's where WET applies

half mirage
#

Well, that’s part of it. The other part is that I like named attributes for things

chilly plank
#

I do find the fact that iter steps partway through steps a bit weird as well, but that could just be me. There could still be a split internally for unit testing purposes "execute_pre_cycle/execute_mid_cycle/execute_post_cycle", but a lot of the cruft seems to be to try to accommodate the iterator part

tidal forum
#

a

chilly pumice
#
with open("Inputs/10.txt") as f:
    ops = f.readlines()

# Cycle: value
graph: dict[int, int] = {}

cycle = 0
x = 1

for op in ops:
    op = op.strip()
    if op == "noop":
        cycle += 1
        graph[cycle] = x
    else:
        to_add = int(op.split(" ")[-1])
        graph[cycle] = x
        graph[cycle+1] = x
        x += to_add
        graph[cycle+2] = x
        cycle+=2

from pprint import pprint
pprint(graph)
#

and yes I did call that variable graph....

#

I couldnt think of a better name lol

tidal forum
#

i think you did your cycles wrong

chilly pumice
#

alright lemme try it again then

chilly pumice
wispy topaz
# half mirage Well, that’s part of it. The other part is that I like named attributes for thin...

but I can't say my attributes always have great names during aoc, see my day8, lot's of them:

    # create an empty class
    class Tree(namedtuple('Tree', 'x y h')): v=0;s=1

    #read the data into a dictionary
    data = open(filename).read().splitlines()
    forest = {(x,y):Tree(x,y,h) for y,row in enumerate(data) for x,h in enumerate(row)}
    H,W = max(forest)

    # loop over each tree
    for t in forest.values():
        # loop over the 4 directions
        for z,d in [
                (list(zip( range(0,t.x)[::-1], repeat(t.y))),         t.x),
                (list(zip(   range(t.x+1,W+1), repeat(t.y))),         W-t.x),
                (list(zip(        repeat(t.x), range(0,t.y)[::-1])),  t.y),
                (list(zip(        repeat(t.x), range(t.y+1,H+1))),    H-t.y)]:
            t.v |= all(t.h>forest[x,y].h for x,y in z)
            t.s *= next((c for c,e in enumerate(z,1) if t.h<=forest[e].h),d)

    print('part1', sum(t.v for t in forest.values()))
    print('part2', max(forest.values(),key=lambda t:t.s).s)
wispy topaz
half mirage
tidal forum
chilly pumice
#

0

half mirage
tidal forum
#

if the first instruction is noop then your graph should look like {0: 1} no?

wispy topaz
tidal forum
#

why

chilly pumice
#

its cycle:value, not the other way around

wispy topaz
tidal forum
chilly plank
#

I'm also curious why _parse_instr isn't a free function that returns an Instr, it doesn't really have any business being part of the class. It doesn't depend on anything in the class at all

def parse_instr(self, instr_text: str) -> Instr:
    match instr_text.split():
        case ["noop"]:
            instr = Instr(cycle_no=1, add_val=0)
        case ["addx", add_val]:
            instr = Instr(cycle_no=2, add_val=int(add_val))
        case _:
            raise Exception("Unexpected instruction")
        return instr

class ...:
    # ...

    def _execute_pre_cycle(self) -> None:
        if self.instr is None:
            try:
                instr_txt = self.program.popleft()
            except IndexError as exc:
                raise StopIteration from exc
            self.instr = parse_instr(instr_txt)
half mirage
chilly pumice
#

oh wait reg starts at 1

tidal forum
chilly pumice
#

so it would be 1:1

half mirage
#

Since dataclasses came out, namedtuples have basically been dead to me

wispy topaz
tidal forum
#

if you're doing 1:1 then why does your dict look like {0:1, 1:1, 2:2} if there's an addx 1

wispy topaz
half mirage
#

Friendship ended with namedtuple
Now dataclasses is my best friend

half mirage
chilly plank
#

I don't really like python enums pithink

#

compared to enums in other langs

chilly pumice
chilly plank
#

they are very much not first class citizens in python

half mirage
chilly plank
#

I guess you could make a case for a staticmethod or classmethod

chilly pumice
#

okay got it!

half mirage
#

Definitely not classmethod

chilly pumice
#

my starting cycle was wrong @tidal forum. Thank you

chilly plank
stark quest
#

I dont really understand what we are doing in part 2. X is the position of the middle of our sprite? And that somehow relates to what gets drawn?

chilly plank
#

ah classmethod takes class as an arg

half mirage
#

Class method is really mostly for alternative initialisers

calm shard
#

If I ever feel the need to type @staticmethod. I stop and write a free function instead.

If it doesn't need an instance and doesn't need the class, it has nothing to do with the class and shouldn't be there.

half mirage
#

If it's a function only used by a class, even if it doesn't need self, I'm ok with it as long as it's sparingly used

calm shard
#

tbh if it's basically a helper to another method I have no issue with it just being a method. regardless if you use self or not.

Otherwise, there's no room at the inn!

stark quest
#

is the gist of part 2?

if cycle in range(x-1,x+3): return '#'
return '.'
calm shard
#

I have a similar line of code in my solution... so it's not a terrible idea

chilly plank
#

wrong range, but basically

stark quest
#

oh yeah x+2

#

because we still need inclusive

#

and then like print newline at cycle % 40

calm shard
#

tbh I just went with in (x-1, x, x+1)

chilly plank
#

I just dumped true/false into a list and built the actual string afterwards

stark quest
#

like a list of bools and #/. based on the truth value?

chilly plank
#

feels like it describes the intent better

calm shard
#

Dunno, is the beam in one of these 3 positions feels better to me.

#

I'll see what my senior says at code review 😛

half mirage
#

I did enjoy the code review of my code just now. Usually I'm the one rigorously reviewing people's code, not the other way around XD

chilly plank
#

hopefully it comes off as constructive criticism rather than just ranting 😛

naive sun
stark quest
#

wait, how are you guys printing the drawing as a contiguous block? I put everything into a list and was just going to iterate over it but that just prints down the terminal lol

#

and i couldnt just print the list because of the newlines

#

nvm i can see the data is wrong anyways

#

oh i had the wrong dataset loaded

#

long day

#

nah either way this is wrong lol

#

but the test input matches what is shown

vernal urchin
stark quest
#

wtf

#

oh actually its just the first line thats printing

#

then its . always

rancid cave
#

i print with end=""

chilly pumice
#

day 10 part 2 done!

stark quest
#

isnt it actually cycle % 40 in [x-1,x,x+1]? because my cycle counter keeps going up to 240 and the x obviously never goes that high

chilly pumice
#

I really don't like my code tho

#

its garbage

stark quest
#

cycle % 41

potent wadi
#

(cycle + 1) % 40?

stark quest
#

or that

potent wadi
#

I was pretty happy with my solution today

#

I didnt think the problem itself was that hard, working out what you really had to do was quite challenging though

gray olive
chilly pumice
#

I feel day 9 was easier

gray olive
#

the difference between part 2 and part 1 today is a couple variables and an if

potent wadi
#

Day 9 wasnt too tough either - I just got stuck on a silly bug for ages

chilly pumice
#

day 9 I at least knew what I was doing. day 10 I was literally changing the order of the lines to make it work

#

noop was causing issues

gray olive
chilly pumice
#

its part 1 but with a loop

#

pretty simple imo

potent wadi
#

If you kept a history of the register for each cycle then pt 2 was incredibly easy

gray olive
violet pondBOT
#

2022/Python/day9.py line 42

for i in range(1, len(rope)):```
chilly pumice
#

well

potent wadi
#

Oh this is the rope one

chilly pumice
#

not very helpful

potent wadi
#

not the forrest trees one

chilly pumice
#

yeah

potent wadi
#

I liked that one actually

#

Pt 2 felt like a good extension as well

chilly pumice
#

me too

potent wadi
#

basically "take pt 1, make it work for n dimensions"

chilly pumice
#

I couldnt believe when my code ran first try and was correct

potent wadi
#

Yeah, the answer somewhat fell out on me too

chilly pumice
chilly pumice
#

you expect me to read that? :kekw:

potent wadi
#

You really need to layout your code in a more human friendly way 😂

chilly pumice
#

I hate code golfing

#

like why

gray olive
#

what do you expect me to do in a rush

potent wadi
#

I always find that if you rush and dont take the time to make it readable you will never fix the bugs you come up against

modest wren
#

that's only an issue if you have bugs

chilly pumice
#

why rush

modest wren
#

to be faster

chilly pumice
#

eh

gray olive
#

but the only thing i can't figure out is the bug

#

how does part 2 work

chilly pumice
#

what you're doing for head and tail, you gotta apply for current knot and previous knot

calm shard
#

Formatting usually comes second... sometimes third... because when I see what Part 2 is I usually need/want to refactor Part 1 to make it nicer code. Then I will format it. 😄

chilly pumice
#

and loop over all knots

chilly pumice
gray olive
chilly pumice
#

rewrite it with better names and I might just look at it 🙃

calm shard
modest wren
chilly pumice
# gray olive i did

or you can just see how my code works and compare. You say you are doing this, so it should be comparable

chilly pumice
gray olive
potent wadi
nocturne aurora
#

I don't like that this one is nearly impossible to complete programmatically

#

I thought this was Advent of Code, not Advent of Reading

gray olive
chilly pumice
#

yeah lmao

nocturne aurora
#

reminds me a bit of the cursed picoCTF 2022 challenge Wizardlike where it was nearly impossible to read the (ASCII art) flag and actually complete the challenge

chilly pumice
#

when I read What eight capital letters appear on your CRT? I was like wtf

modest wren
chilly pumice
#

but as you can see from my github, I ditched that

nocturne aurora
vernal urchin
#

you all are not talking about day 10 right?

nocturne aurora
#

if so why

chilly pumice
#

maybe we should move

gray olive
vernal urchin
#

I was just confused more than anything, but yeah

stark quest
nocturne aurora
#

I'm getting spoiled for day 9 lol I should wait to go to this channel

gray olive
chilly pumice
calm shard
#

Please move Day 9 chat to #1050641552524976129

#

You can skip days

chilly pumice
#

riiiiiiiiiight

calm shard
#

Please move Day 9 chat to #1050641552524976129

nocturne aurora
chilly pumice
#

yeah

chilly pumice
#

I forget only I try to lol

gray olive
nocturne aurora
#

okk

calm shard
#

@nocturne aurora @gray olive

gray olive
nocturne aurora
#

😂

#

for Day 10 Part 2 I just add dummy array item before every addx, this is easiest way

junior coyote
#

assuming register start point is 1

#

and i have addx 15

#

cycle 1: register = 1

#

cycle 2: register = 16

vernal urchin
#

no

#

you update X after cycle 2

#

but before cycle 3

junior coyote
#

yes so while my cycle var is 2

#

register is 16

#

i mean

vernal urchin
#

any updates during cycle 2 must use X=1

#

you will only get X=16 effectively in 3rd cycle

half mirage
#

during cycle 2: x = 1
after cycle 2: x = 16

#

part 1 only cares about during values

junior coyote
#

im part 2

vernal urchin
#

to be fair even in part 2, the drawing to screen is based on during-value

half mirage
#

well, part 2 as well, if we are talking about setting pixels on the screen

vernal urchin
#
if line.startswith("addx"):
  tick()
  tick()
  X += int(line[4:])
#

essentially

stark quest
#

lets go

junior coyote
#

[(1, 1), (2, 1), (3, 16), (4, 16), (5, 5), (6, 5), (7, 11), (8, 11), (9, 8), (10, 8), (11, 13), (12, 13), (13, 12), (14, 12), (15, 4), (16, 4), (17, 17), (18, 17), (19, 21), (20, 21), (21, 21), (22, 20), (23, 20), (24, 25), (25, 25), (26, 24), (27, 24), (28, 29), (29, 29), (30, 28), (31, 28), (32, 33), (33, 33), (34, 32), (35, 32), (36, 37), (37, 37), (38, 36), (39, 36), (40, 1), (41, 1), (42, 2), (43, 2), (44, 26), (45, 26), (46, 7), (47, 7), (48, 8), (49, 8), (50, 24), (51, 24), (52, 13), (53, 13), (54, 13), (55, 13), (56, 34), (57, 34), (58, 19), (59, 19), (60, 19), (61, 19), (62, 16), (63, 16), (64, 25), (65, 25), (66, 26), (67, 26), (68, 23), (69, 23), (70, 31), (71, 31), (72, 32), (73, 32), (74, 37), (75, 37), (76, 37), (77, 37), (78, 37), (79, 37), (80, 37), (81, 1), (82, 1), (83, 1), (84, 2), (85, 2), (86, 9), (87, 9), (88, 9), (89, 9), (90, 9), (91, 11), (92, 11), (93, 17), (94, 17), (95, 17), (96, 17), (97, 17), (98, 17), (99, 17), (100, 18), (101, 18), (102, 18), (103, 18), (104, 25), (105, 25), (106, 26), (107, 26), (108, 26), (109, 13), (110, 13), (111, 26), (112, 26), (113, 33), (114, 33), (115, 33), (116, 34), (117, 34), (118, 1), (119, 1), (120, 1), (121, 1), (122, 1), (123, 3), (124, 3), (125, 3), ]

stark quest
#

back on track

junior coyote
#

so i have this

nocturne aurora
#

why do you have this

vernal urchin
junior coyote
#

in cycle one my sprite is on which pixel

#

?

#

i cant understand the next lemon_angrysad

vernal urchin
#

cycle 1/2 sprite is at X=1

junior coyote
#

but why is the sprite 3 twitter symbols

stark quest
#

I will be honest I couldnt figure out how to get the newlines working so i just used a library

print(textwrap.fill(''.join(drawing), 40))
#

lol

vernal urchin
#

because it's 3 characters wide

#

the leftmost character is at X=1

#

but it covers columns 1,2,3

junior coyote
#

ok so my first tuple should be drawn

#

a #welcome

#

on my render correct?

vernal urchin
#

Yeah first 2 should be ## because you can't move the sprite until 3rd cycle

junior coyote
#

at cycle 40

#

38

#

it will be

.....................................###```
#

?

vernal urchin
#

at cycle 38 it seems like the sprite is at X=36, so it covers 36,37,38, so you should get a #

nocturne aurora
calm shard
#

"twitter symbols"

naive sun
#

That better be a language barrier

vernal urchin
#

octothorpe

calm shard
#

pound!

naive sun
junior coyote
#

and on cycle 42 will it be

...................................###..```
or will it be

.......................................#```

vernal urchin
#

o c t o t h o r p e

junior coyote
#

which one of these is correct

half mirage
#

hash

vernal urchin
#

is octothorpe

half mirage
#

tag

calm shard
#

octothorpe is overly fancy name for it lol

naive sun
vernal urchin
#

it is, I like being that guy

junior coyote
calm shard
#

no just hash

vernal urchin
naive sun
echo wolf
vernal urchin
vernal urchin
junior coyote
#

its not about counting dots

#

its about will the thing go into the edge

#

or will it return

#

the moment the 3 hash touch the right side

#

*reverse

vernal urchin
#

on cycle 42 you are on the second row

#

and X=2

nocturne aurora
#

is an octothorpe

junior coyote
#

wth

vernal urchin
#

so it will be

..XXX....
junior coyote
#

i thought it moves like

vernal urchin
#

first 40 cycles = 1st row

nocturne aurora
vernal urchin
#

second 40 cycles = 2nd row

junior coyote
#

i thought it moves like this

#

=(((((

vernal urchin
#

you get the "column" by cycle % 40

naive sun
junior coyote
#

rust language is garbage

#

c++ is better it has more plus signs

vernal urchin
#

no, rust has no garbage collection

gray olive
vernal urchin
#

Java is garbage

#

collected

junior coyote
#

haha

vernal urchin
nocturne aurora
#

boehm ftw

gray olive
junior coyote
#

only reason java is not dead is because of my minecraft channel

naive sun
vernal urchin
naive sun
#

Can't argue with that

vernal urchin
#

i made rope simulation with it how bad can it be

junior coyote
#
2 + "2" = 22

#

or will it be string

#

i forgot

#

which makes more "sense"

vernal urchin
#

string

#

everything gets implicitly converted to string IIRC if js doesn't know what to do

nocturne aurora
nocturne aurora
#

actually some security exploits came like this

wispy topaz
#

(I kid, java is widely distributed and will remain relevant for many years to come in some form or another)

junior coyote
#

but i also dont want to learn it

nocturne aurora
junior coyote
#

i want to learn rust or c++

naive sun
junior coyote
#

i cant do second part from today

#

yesterday was easier

#

or is it me

naive sun
#

Yesterday took me the entire day
Today took me an hour

nocturne aurora
#

learn Rust! 🦀🚀

nocturne aurora
#

should I do yesterday's

#

this one second part is almost identical to first part

junior coyote
#

how fast did you do today?

naive sun
naive sun
junior coyote
#

and now i sit on second part

#

1 hour

#

because i cannot understand the task

junior coyote
naive sun
#

Yeah I'll admit I had to look at this channel for a second before I completely understood the problem

kind egret
#

Today is a bit like reading a datasheet and building up a simple circuit based on it. It's all about precision, timing, and reading comprehension

vernal urchin
#

Day 9 included a food break in between because i kinda got annoyed after seeing part 2 lmao

echo wolf
#

i remember it being midnight and I was about to go to bed because I was expecting this one to be harder like day 9, but then I quickly read through it and went "man I could do that pretty quickly"

naive sun
#

Takes me longer than that just to understand the problem

junior coyote
#

some other moderator/helper had a animation that looked cool

naive sun
#

salt-die

junior coyote
#

yes

vernal urchin
#

oh salt-die too I guess

junior coyote
#

show yours

#

too

#

id like to see

naive sun
#

here

vernal urchin
junior coyote
#

thats cool

vernal urchin
#

I also did a discrete version in python like salt-die but that wasn't as cool as this

junior coyote
#

why is at the end when you have let go of it already

#

some movement still happening?

vernal urchin
#

because you can move more than 1 pixel in every frame, so I make everything go closer over time

#

rather than just snapping instantly

#

basically each node goes closer to its parent at a speed proportional to how far away it is from the expected position

#

takes a few frames for it to converge

#

it's not completely rigid, basically, similar to how in the 2d version there was some "leeway" before the child snaps

vernal urchin
#

Day 4 is my proudest achievement

junior coyote
#
###...##..#..#..##..####.###..####.####.
#..#.#..#.#.#..#..#.#....#..#.#.......#.
###..#....##...#..#.###..#..#.###....#..
#..#.#.##.#.#..####.#....###..#.....#...
#..#.#..#.#.#..#..#.#....#.#..#....#....
###...###.#..#.#..#.####.#..#.####.####.```
#

i get this

#

am i done finaly?

vernal urchin
#

nice!

#

yep

junior coyote
#

😭

warm edge
#

Here is my dreadful looking code for part 2


with open('day10\input.txt','r') as f:
    data = f.read().split('\n')


cycle = 0
x = 1
screenline = ''
screen = []
pixel = -1

def add_line(cycle):
    global pixel
    global screenline
    if cycle in [40, 80, 120, 160, 200, 240]:
        screen.append(screenline)
        screenline = ''
        pixel = -1

def draw_pixel(x):
    global pixel
    global screenline
    pixel += 1
    add_line(cycle)

    if pixel in (x+1,x-1,x):
        print(x, pixel, '#')
        screenline += '#'
    else:
        print(x, pixel)
        screenline += '.'
    

for line in data:
    if 'noop' in line:
        cycle += 1
        draw_pixel(x)
    else:
        line = line.strip('addx ')
        cycle += 1
        draw_pixel(x)
        cycle += 1
        draw_pixel(x)
        x += int(line)


for i in screen:
    print(i)```

As always, lmk if you see any obvious improvements
naive sun
# naive sun

Doesn't help that I go to sleep like an hour or two before they're released

vernal urchin
#

if you replace . with a space it's easier to read the characters @junior coyote

echo wolf
#

If you think about it, there could be a possibility that someone's random letters spelled out some word

vernal urchin
vernal urchin
# warm edge Here is my *dreadful* looking code for part 2 ```py with open('day10\input.txt'...

here's my cleaned up implementation:

res = 0
screen = ""
X = 1
cycles = 0

def tick():
    global cycles,res,screen
    cycles += 1
    if cycles % 40 == 20:
        res += X * cycles
    
    if cycles % 40 == 0:
        screen += "\n"
    else:
        screen += " #"[X <= cycles % 40 < X+3]

for line in lines:
    if line == "noop":
        tick()
    elif line.startswith("addx"):
        tick()
        tick()
        X += int(line[4:])

print("Part 1:", res)
print("Part 2:")
print(screen)
junior coyote
#

hardcoded

junior coyote
#

finally can read

vernal urchin
#

I'm not against hardcoding but it's just... more work in this case

vernal urchin
sterile pagoda
vernal urchin
gray olive
#

why does the input go negative in some places

#

it completely ruins my VM

vernal urchin
#

lmao this is exactly what i was trying to do

#

with the rick roll

#

how did you generate this?

sterile pagoda
vernal urchin
# junior coyote finally can read

if you want to see the golfed solution we have all been optimizing in the other channel:

R=c=X=0
S=n="\n"
T='c+=1;W=c%40;R-=~X*c*(W==20);S+=n[W:]or" #"[X<W<X+4];'
for L in open(0):exec(T+(T>L)*f"{T}X+=int(L[4:])")
print(R,S)
#

it's so horrible I love it

junior coyote
#

what does

#

=~ supposed to do

#

i have never seen it

vernal urchin
#

R-=(~X)*...

#

bitwise not

junior coyote
#

i go out of my way to say today was harder than all other ones

#

my english reading comprehension is horrible ig

#

🥴

sterile pagoda
#

I didn't do anything fancy to generate the ascii art itself 😄

#

I looked up pixel fonts but got bored.

sterile pagoda
vernal urchin
#

then i just said screw it and started working on the rope thing

junior coyote
#

what did you use for rope thing

#

which gui

vernal urchin
#

custom graphics library in my own programming language lmao

sterile pagoda
#

Plot/puzzle predictions for day 11?

vernal urchin
#

saturday night, prolly gonna be a doozy

sterile pagoda
#

We're still in the ravine right?

vernal urchin
#

I'm guessing some sort of graph traversal

restive path
#

something like day 15 of last year I'd think

stark quest
junior coyote
#

how

#

emojis?

stark quest
#

its unicode

#

but yeah

junior coyote
#

idk what U+2B1C mean

stark quest
#

unicode

#
def check_draw(cycle, x):
    #Replaced '#' and '.' because they are difficult to read
    if (cycle-1) % 40 in [x-1,x,x+1]: return '⬜'
    return '⬛'
#

no idea

mint tangle
junior coyote
#

i think my console didnt like it ig?

#

it work in other one

#

oh no

#

i forgot smth in other=)

#

nvm

nocturne aurora
#

I used same

junior coyote
junior coyote
nocturne aurora
nocturne aurora
junior coyote
#

ooh

#

i see because its somewhere in the HTML document

#

you can just use it

#

from browser?

nocturne aurora
junior coyote
#

its in this pre style="word-wrap" thing

#

why document.body.textContent

#

can fetch it

nocturne aurora
#

textContent only gets the text, and strips any HTML tags

#

it basically takes all the text nodes from every element and puts them together

junior coyote
#

oh so every <asdf> get excluded

#

cool

#

ty

#

+1 knowledge

nocturne aurora
#

:D

vernal urchin
junior coyote
vernal urchin
nocturne aurora
sterile pagoda
#

Did you make the letters of the font yourself?

vernal urchin
#

nope, stolen from salt-die which he crowdsourced I think

gray olive
#

i finally made the VM work

gleaming kelp
#

most fun challenge so far ngl

gray olive
gray olive
#

nvm it does

sweet mango
gray olive
rocky charm
#

and the missing uppers

gray olive
rocky charm
#

i only made one punctuation

gray olive
#

why

vernal urchin
rocky charm
#

i'll probably do all printables later

rocky charm
sweet mango
#

You could make a text file containing pre-rendered images of all the ascii characters

gray olive
rocky charm
#

it's not a program, it's a text file

gray olive
#

ok

vernal urchin
gray olive
vernal urchin
#

I would hope so?

sweet mango
#

The redirects work, but not the &

gray olive
sweet mango
#

& is for running something in the background in bash

vernal urchin
#

Ah I guess I tried it on PowerShell at some point

#

I don't use windows often

#

Or at all, really

sweet mango
#

in powershell, & is to run a program by file path

#

pwsh (run program): & ./path/to/file.exe
bash (run program in background): ./path/to/file.sh &

vernal urchin
#

I'm talking about piping with |

#

Idk what you're referring to

sweet mango
#

<> is also a pipe

vernal urchin
#

🤷‍♂️

gray olive
#

i made the programs work with lengths greater than 40 now

nocturne aurora
#

epic

gray olive
vernal urchin
#

Yeah I was surprised

#

That's like, one of the fundamental ways to use a shell

vernal urchin
gray olive
#
>.\get_art.py "Have you ever thought of something as   great as this" 200 | .\vm.py 200

works pretty well
now all i want is word wrap instead of character wrap

sweet mango
#

Now do famous song lyrics

abstract python
#

never g-

sweet mango
#

do a url

#

you know which one

gray olive
hollow herald
sweet mango
vernal urchin
#

add them!

gray olive
#

idk how

sweet mango
#

You need to support the full printable ascii table

#

0-19 can be skipped

gray olive
vernal urchin
#

print out the uncompressed data from load_font(), add whatever you want, re-compress it

#

salt-die just read it from a text file the compression shenanigans are mine

#

for easy sharing

#

lemme refactor it

vernal urchin
#

here, should be much easier to change the font here

gray olive
#

ok

nocturne aurora
#

then replace the FONT = line starting with b'

gray olive
#

inverse is actually pretty cool

tidal forum
#

did someone make a program to generate instructions to create anything for a monitor

#

.-.

vernal urchin
tidal forum
#

nice

nimble shuttle
#

it is almost the hour of choking yet again

vernal urchin
#

indeed, wactch me choke so bad

quasi minnow
#

Lmao

restive path
#

see yall in like 3 hours

gray olive
#

i got word wrap done ```

.\get_art.py "Never gonna tell a lie and hurt you..." 50 | py vm.py 50 : 5

#
>.\get_art.py 200 < lyrics.txt | py vm.py 200 "#" 5
rocky charm
gray olive
rocky charm
#

implied empty lines above it

gray olive
#

ok

#

probably

rocky charm
#

the 5 is exactly the same as a S too, trying to change it

#

maybe just add a # at the top-left corner so it isn't rounded

violet pondBOT
gray olive
fading hull
#

Had to change my code, after part 1, because it is not any good for part 2.

#

now with the rework part 1 doesn't work anymore 😦