Zikeji

joined 2 years ago
[โ€“] Zikeji@programming.dev 2 points 7 months ago

Javascript

Spent 10 minutes debugging my solution until I reread and found out they wanted the number of keys that fit, not the ones that overlapped. Reading comprehension is not it tonight.

const [locks, keys] = require('fs').readFileSync(0, 'utf-8').split(/\r?\n\r?\n/g).filter(v => v.length > 0).map(s => s.split(/\r?\n/g).filter(v => v.length > 0)).reduce((acc, s) => {
    const lock = s[0].split('').every(v => v === '#');
    const schema = s.slice(1, -1);
    let rotated = [];
    for (let i = 0; i < schema[0].length; i += 1) {
        for (let j = 0; j < schema.length; j += 1) {
            if (!rotated[i]) rotated[i] = [];
            rotated[i].push(schema[j][i]);
        }
    }
    if (!lock) {
        rotated = rotated.map(v => v.reverse());
    }
    const pinHeights = [];
    for (const row of rotated) {
        const height = row.indexOf('.');
        pinHeights.push(height !== -1 ? height : 5);
    }
    if (lock) {
        acc[0].push(pinHeights);
    } else {
        acc[1].push(pinHeights);
    }
    return acc;
}, [[],[]]);

let fits = 0;
for (const lock of locks) {
    for (const key of keys) {
        let overlapped = false;
        for (let i = 0; i < lock.length; i += 1) {
            if ((lock[i] + key[i]) > 5) {
                overlapped = true;
            }
        }
        if (!overlapped) {
            fits += 1;
        }
    }
}

console.log('Part One', fits);
[โ€“] Zikeji@programming.dev 2 points 7 months ago* (last edited 7 months ago)

Javascript

Part one was easy, though despite starting at midnight I only placed 1786 for part one. I think my tendency to want to do OOP makes it take longer...

Part two.. Well, I figured it was some sort of binary circuit for trying to add binary numbers. So I hoped that the sum of the x registers and the y registers was the expected result of simulating the circuit like in part one. I later verified that it is the expected result.

I didn't want to try and manually figure out the bad outputs, coffee wasn't helping, I wanted sleep. So I uh.. I wrote logic to randomly create swaps. And then just hoped RNG got me covered. To help my chances, I ran it on 8 different processes.

When I woke up in the morning I discovered 8 stopped processes, each with "a solution" that was different. Turns out, if you just randomly swap wires at some point you get a system that outputs the desired result - but only because you sufficiently screwed it up more to produce the expected result, even if the system itself would not work for other input.

I could probably change the registers to another value, run it, and see if they match, thus ruling out an incorrect set of swaps causing a correct result with the original binary inputs. But at this point I just decided to do it the manual way following advice on here. My brain is fried, I'm stepping away to take a shower and get ready to visit family.

I had really hoped the bruteforce would work, I modified the bruteforce to run even after it finds a match and I'll let it run while I'm gone today and see if RNG produces any correct result at some point - I just fear the exponential answer timeout will prevent me from submitting these correctly incorrect combinations lol. I might modify it later with my theory above and just run it on a server indefinitely and see if it produces the correct result eventually.

https://blocks.programming.dev/Zikeji/9e4d6e81595d4845b88cf98eb91852d8

Edit:

Created a raw multithreaded bruteforce variant: topaz

[โ€“] Zikeji@programming.dev 5 points 7 months ago

I'm a dog person with a fenced backyard, a dog door, and a mudroom (a room meant to get dirty while I clean them off if it's raining). They get to walk and do their business, I get to not walk them in the rain or cold. Win/win.

[โ€“] Zikeji@programming.dev 2 points 7 months ago

Go

Re-familiarizing myself with Go. The solution to Part 2 is fairly simply, the whole packing of the sequence into a single integer to save on memory was an optimization I did afterwards based on looking at other solutions. I thought it was cool.

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

type SequenceMap struct {
	Data map[int32]int
}

func PackSeq(numbers [4]int8) int32 {
	var packed int32
	for i, num := range numbers {
		packed |= int32(num+9) << (i * 5)
	}
	return packed
}

func UnpackSeq(packed int32) [4]int8 {
	var numbers [4]int8
	for i := range numbers {
		numbers[i] = int8((packed>>(i*5))&0x1F) - 9
	}
	return numbers
}

func NewSequenceMap() SequenceMap {
	return SequenceMap{make(map[int32]int)}
}

func (m *SequenceMap) Increment(seq [4]int8, val int) {
	pSeq := PackSeq(seq)
	acc, ok := m.Data[pSeq]
	if ok {
		m.Data[pSeq] = acc + val
	} else {
		m.Data[pSeq] = val
	}
}

func (m *SequenceMap) Has(seq [4]int8) bool {
	pSeq := PackSeq(seq)
	_, ok := m.Data[pSeq]
	return ok
}

type Generator struct {
	Secret         int64
	LastPrice      int8
	ChangeSequence []int8
}

func NewGenerator(Secret int64) Generator {
	var ChangeSequence []int8
	return Generator{Secret, int8(Secret % 10), ChangeSequence}
}

func (g *Generator) Mix(value int64) *Generator {
	g.Secret = g.Secret ^ value
	return g
}

func (g *Generator) Prune() *Generator {
	g.Secret = g.Secret % 16777216
	return g
}

func (g *Generator) Next() {
	g.Mix(g.Secret * 64).Prune().Mix(g.Secret / 32).Prune().Mix(g.Secret * 2048).Prune()
	Price := int8(g.Secret % 10)
	g.ChangeSequence = append(g.ChangeSequence, Price-g.LastPrice)
	g.LastPrice = Price
	if len(g.ChangeSequence) > 4 {
		g.ChangeSequence = g.ChangeSequence[1:]
	}
}

func ParseInput() []int64 {
	if fileInfo, _ := os.Stdin.Stat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 {
		fmt.Println("This program expects input from stdin.")
		os.Exit(1)
	}
	scanner := bufio.NewScanner(os.Stdin)

	var numbers []int64
	for scanner.Scan() {
		line := scanner.Text()
		num, err := strconv.ParseInt(line, 10, 64)
		if err != nil {
			fmt.Printf("ERROR PARSING VALUE: %s\n", line)
			os.Exit(1)
		}
		numbers = append(numbers, num)
	}

	return numbers
}

func main() {
	numbers := ParseInput()

	m := NewSequenceMap()
	sum := int64(0)

	for i := 0; i < len(numbers); i += 1 {
		g := NewGenerator(numbers[i])
		tM := NewSequenceMap()
		for j := 0; j < 2000; j += 1 {
			g.Next()
			if len(g.ChangeSequence) == 4 {
				if !tM.Has([4]int8(g.ChangeSequence)) {
					tM.Increment([4]int8(g.ChangeSequence), 1)
					if g.LastPrice > 0 {
						m.Increment([4]int8(g.ChangeSequence), int(g.LastPrice))
					}
				}
			}
		}
		sum += g.Secret
	}

	fmt.Printf("Part One: %d\n", sum)

	var bestSeq [4]int8
	bestPrice := 0
	for pSeq, price := range m.Data {
		if price > bestPrice {
			bestPrice = price
			bestSeq = UnpackSeq(pSeq)
		}
	}

	fmt.Printf("Part Two: %d\n", bestPrice)
	fmt.Printf("Best Sequence: %d\n", bestSeq)
}
[โ€“] Zikeji@programming.dev 6 points 7 months ago (3 children)

Javascript

Behold an abomination!

const input = require('fs').readFileSync(0, 'utf-8').toString();
const towels = new Set(input.split(/\r?\n\r?\n/g)[0].split(', '));
const count = (p, t) => [...new Array(p.length).keys()].reduce((acc, i) => [...new Array(i + 1).keys()].forEach(j => acc[j] > 0n && t.has(p.substring(j, i + 1)) ? acc[i + 1] += acc[j] : null) ? acc : acc, [1n, ...new Array(p.length).fill(0n)])[p.length];
input.split(/\r?\n\r?\n/g)[1].split(/\r?\n/g).filter(p => p.length > 0).reduce((acc, p) => { let c = count(p, towels); acc[0] += c > 0 ? 1 : 0; acc[1] += c; return acc }, [0, 0n]).forEach((v, i) => console.log(`Part ${i+1}: ${v}`));
[โ€“] Zikeji@programming.dev 8 points 7 months ago (1 children)

The placement of the dog is just evil.

[โ€“] Zikeji@programming.dev 4 points 7 months ago (2 children)

The AM5 chipset only supports up to 28.

That being said, performance loss depends on your inference engine. You could try and find a older threadripper to get proper 2x 16x, but you'd still be spending a pretty penny for PCIe Gen 4.

Unfortunately, whole gen 5 is twice the bandwidth as gen 4, 2x 8x PCIe 5 doesn't become 2x 16x PCIe 4, though that would have been nice.

[โ€“] Zikeji@programming.dev 2 points 7 months ago

Javascript

Reused my logic from Day 16. For part two I manually changed the bytes (i on line 271) to narrow in on a solution faster, but this solution should solve it eventually.

https://blocks.programming.dev/Zikeji/c8fdef54f78c4fb6a79cf1dc5551ff4d

[โ€“] Zikeji@programming.dev 1 points 7 months ago* (last edited 7 months ago)

Javascript

So my friend tells me my solution is close to Dijkstra but honestly I just tried what made sense until it worked. I originally wanted to just bruteforce it and get every single possible path explored but uh... Yeah that wasn't gonna work, I terminated that one after 1B operations.

I created a class to store the state of the current path being explored, and basically just clone it, sending it in each direction (forward, 90 degrees, -90 degrees), then queue it up if it didn't fail. Using a priority queue (array based) to store them, I inverted it for the second answer to reduce the memory footprint (though ultimately once I fixed the issue with the algorithm, which turned out to just be a less than or equal to that should have been a less than, I didn't really need this).

Part two "only" took 45 seconds to run on my Thinkpad P14 Gen1.

My code was too powerful for Lemmy (or verbose): https://blocks.programming.dev/Zikeji/ae06ca1ca88649c99581eefce97a708e

[โ€“] Zikeji@programming.dev 14 points 7 months ago (1 children)

What you describe - that feeling when you think of doing those things, my personal experience has me classify it as overthinking becomes getting overwhelmed. And once I'm overwhelmed, I want to escape.

Keeping in mind coping mechanisms aren't one size fits all, the coping mechanism that helped me is to write out the problem step by step. This forces me to think slower, and helps me get out of that recursion of thinking about the same things.

I've also found some success in the age of AI LLMs asking one to break it down as well.

An example would be the dentist. First I need to find one, I need to look at reviews, I need to make sure they accept my insurance, I need to make sure they're reasonably close by. Alright, I compile a list of a few options, now the next part is the hard part: I have to actually call to get scheduled. But once I have it scheduled, my social anxiety is superceded by my desire to just get it over with. Sure I may feel that anxiety once I get close to the appointment, but I can cope with that - the real trick is by breaking down the process I didn't get overwhelmed as quick, and if I did I had notes to come back to.

[โ€“] Zikeji@programming.dev 15 points 7 months ago (3 children)

I'd recommend just getting a live version of a distribution that you don't have to install, that way you can play around with it before committing.

[โ€“] Zikeji@programming.dev 13 points 7 months ago (1 children)

I used to have a fair bit of imposter syndrome but now that I've been working with a proper team I've come too accept I have an aptitude for code and logic in general, alongside a fairly good abstract memory.

I'm not the best by any stretch of the imagination, but I'm a little more competent than the average software engineer, enough that it gets noticed.

I also got lucky and scored a job at 17 in the field (with no nepotism involved), not a great one but enough to look good on my resume, and have been working in the industry for just over a decade with no college.

view more: โ€น prev next โ€บ