#Day 1 Trebuchet?!

1 messages · Page 1 of 1 (latest)

teal vault
whole coral
#

part 2 means i'll have to rewrite like, everything

teal vault
#

C++, both parts

whole coral
teal vault
whole coral
#

this feels like the wrong way to solve this problem but I don't know OCaml well enough yet

teal vault
#

I'm looking at the OCaml wikipedia page and my brain broke

whole coral
#

the way to solve every problem is a recursive algorithm and a match statement

#

I collapsed the pattern match functions so it'd fit on one screen, but here's both parts solved

#

I used the Jane Street stdlib

teal vault
#

🤔 consistent rank between parts 1 and 2

whole coral
#

yup I definitely did this wrong

iron elbow
#

I was too lazy to do something proper for part 2 so I ||just reversed the input string and the list of needles to find the rightmost number||

fossil mulch
#

Here's part 1 in Turing Complete. Part 2 should be easy but tedious, so I'll save it for the morning.

whole coral
fossil mulch
#

The wiring could definitely be cleaned up. I was preparing for it to be much more complex and didn't put much focus in keeping it neat.

whole coral
iron elbow
#

Oh lol you did it literally

thin stump
#

I said I'd do it in c++ but here's my (very naive) zig solution lol

teal vault
#

Oh, I didn't even think of ||just replacing the words with digits||

shell pasture
unkempt topaz
#

Part 1 was like "oh a nice easy one to start with", then part 2 "oh no, this is gonna be a mess" and it was lol. Though in retrospect, I realize that all I did was try to adapt what I did for part 1, which wasn't the best choice.

shell pasture
#

Part 1. Yes I'm lame and this is C++ developed in replit on my phone

shell pasture
unkempt topaz
#

Part 1
||```rust
fn part1() -> impl Display {
INPUT.lines()
.map(|line| {
let first = line.chars().find(|c| c.is_numeric()).unwrap();
let last = line.chars().rfind(|c| c.is_numeric()).unwrap();

        format!("{first}{last}").parse::<usize>().unwrap()
    })
    .sum::<usize>()

}


My initial problem at part 2 was ||that I can't simply use `.find()` to say "if this char is number, OR some unknown length of chars matches one of a bunch of strings".|| The very ugly way I came up with, was to ||keep using `.find()` and check separately for numbers, and for matching words, and then determine which was the closest to the start/end of the data.||
#

Won't post my original part 2. But after reading about a certain issue that other people ran into, I figured out I could just do this:
||```rust
const PAT_REPLACE: [(&str, &str); 10] = [
("zero", "zero0zero"),
("one", "one1one"),
("two", "two2two"),
("three", "three3three"),
("four", "four4four"),
("five", "five5five"),
("six", "six6six"),
("seven", "seven7seven"),
("eight", "eight8eight"),
("nine", "nine9nine"),
];

fn part2() -> impl Display {
INPUT.lines()
.map(|line| {
let mut line = line.to_string();

        for (pattern, replace) in PAT_REPLACE {
            line = line.replace(pattern, replace);
        }
        
        let first = line.chars().find(|c| c.is_numeric()).unwrap();
        let last = line.chars().rfind(|c| c.is_numeric()).unwrap();
        
        format!("{first}{last}").parse::<usize>().unwrap()
    })
    .sum::<usize>()

}

silent quarry
#

Both parts, Kotlin
||

class Day1 : Puzzle(1) {
    private val digitMap = mapOf(
        "one" to 1, "two" to 2, "three" to 3, "four" to 4, "five" to 5,
        "six" to 6, "seven" to 7, "eight" to 8, "nine" to 9
    ) + (1..9).map { it.toString() to it }

    override fun part1() =
        input.lines().asSequence()
            .map { line ->
                line.asSequence()
                    .filter { it.isDigit() }
                    .map { it.digitToInt() }
                    .let { it.first() * 10 + it.last() }
            }.sum().toString()

    override fun part2() =
        input.lines().asSequence()
            .mapNotNull { line ->
                val first = line.findAnyOf(digitMap.keys)?.second
                val last = line.findLastAnyOf(digitMap.keys)?.second
                if (first == null |\| last == null) return@mapNotNull null

                (digitMap[first]!! * 10) + digitMap[last]!!
            }.sum().toString()
}

||

ornate raven
#

python solution
||

def find_num(s: str, rev: bool, p2: bool) -> int:
    nums = {
        "1": "one",
        "2": "two",
        "3": "three",
        "4": "four",
        "5": "five",
        "6": "six",
        "7": "seven",
        "8": "eight",
        "9": "nine",
    }

    if rev:
        s = s[::-1]
        nums = {k: v[::-1] for (k, v) in nums.items()}

    for i in range(len(s)):
        for k, v in nums.items():
            if (s[i:].find(k) == 0) or (p2 and s[i:].find(v) == 0):
                return int(k)


p1, p2 = 0, 0
for l in open("input.txt").read().splitlines():
    p1 += find_num(l, 0, 0) * 10 + find_num(l, 1, 0)
    p2 += find_num(l, 0, 1) * 10 + find_num(l, 1, 1)

print(p1, p2)

||

#

@silent quarry how did you get the colored syntax ?

silent quarry
#

after the three ``s` put the name of the language

ornate raven
#

@silent quarry thank you

unkempt topaz
#

Also please wrap with ||

#

(to spoiler it)

green birch
#

Trigger warning: Java

shell pasture
#

lmao trigger warning

dull edge
#

part 1 and 2 in factorio lmao

silent quarry
#

part 2 in vim key inputs

teal vault
blazing vigil
#

part2 haskell

dull edge
#

though you can make that work || by replacing "one" with "o1e" and the same for other numbers ||

fossil mulch
#

Part 2 in Turing Complete. Props to anyone who can decipher this.

iron elbow
#

Lol you should post that on Reddit

#

Impressive

fossil mulch
#

I don't think I have a Reddit account anymore.

buoyant ravine
#

bit of a weird one and in the end i ended up writing my own matching code but it could be worse

shell pasture
#

Still stuck in part 2. Can you guys give me confirmation that I'm understanding correctly: if there's only one digit in a line, it gets repeat into two, right?

whole coral
#

or vfourv or whatever, also 44

shell pasture
#

Dammit then I'm still stuck

whole coral
#

are you using regex?

shell pasture
#

Thanks ❤️

#

Nope

whole coral
#

hmm

shell pasture
#

Also I'm printing all of my single nums and they seem to match, looking manually at the file

whole coral
#

well what i'd suggest is doing a print statement that prints the line and the calculated first and second digits and then scrolling through it until you see one thats wrong

#

oh

shell pasture
#

NEVERMIND

#

I found one

sonic barn
#

Someone I know came up with an interesting solution

#

||He realized that the only characters that matter for overlapping are the first and last characters||

#

|| because of this, you can solve part two by replacing one with o1e, two with t2o, three with t3e etc, and then just run the solution from the first part||

#

|| I guess that’s quite similar to what bigbass did actually||

iron elbow
#

A colleague of mine came up with the same

#

I think there's two main ways people solve it.. this one and the one I used (why isn't this damn spoiler tag working now)

fossil mulch
#

I feel like ||replacing text is overcomplicating it. For every character, I check if it’s a number or if it and the following characters match one of the 10 words.||

thin stump
fossil mulch
#

What’s typing?

iron elbow
#

The thing you do on a keyboard

teal vault
shell pasture
#

I overcomplicated my life a lot I feel like

whole coral
#

don't worry mine was crazy overcomplicated too 😆

shell pasture
#

Aight I give up

#

It's like this every year

#

Start doing AoC -> fixate for a day on solving a problem without succeeding -> feel stupid because you work as a programmer and have a working Nintendo 64 emulator but supposedly can't solve stupid problems while everyone else finished in about 5 minutes -> get angry at yourself and depressed
This isn't healthy for me

#

So i'm calling it quits

blazing vigil
#

it's just for fun anyway

#

if you aren't having fun then there's no reason to do it imo

shell pasture
#

Exactly so yeah

#

I'm maybe going to try again tomorrow but yeah no

#

If it has to be string parsing fiasco every fucking time

#

I swear this guy just loves typing he should do web dev He does lmao

#

(Yeah I'm still salty)

iron elbow
#

Some people call it Advent of Parsing

shell pasture
#

Yeah it literally is

iron elbow
#

The puzzles get more fun and challenging than this though. But if it is not fun for you then maybe better not 🙂

fossil mulch
#

I'm actually not that unique. The TC Discord server has a leaderboard running.

unkempt topaz
# shell pasture > Start doing AoC -> fixate for a day on solving a problem without succeeding ->...

This happens every year to a lot of people. Even happened to me many times. I've spoken on it before, but AoC usually boils down to whether or not you already happen to know how to solve the problem, and then implementing it. The first few days can usually be worked through without knowing the best methodology to use, but even then it can feel frustrating.

AoC tends to make use of certain algorithms or ways of thinking that you don't need in a lot of other programming fields/scenarios. You could work on quantum computers but struggle with AoC because you've never parsed strings in arbitrarily complex ways before.

shell pasture
#

:/

unkempt topaz
#

I've gotten better over the years, and I take it much less seriously now, which helps reduce any frustration. If I get stuck, I head over to the Rust server, as there's people there that are really helpful.

iron elbow
#

Yeah, I mean, in the end it's about fun. I didn't finish most years but also if I get stuck on something for too long it helps to be able to ask for help. I guess people with a compsci or maths degree have an edge because you know all those algoritms you normally never use in practice 🙂

#

Also usually stuff from previous years is repeated sometimes so you definitely get better at it with time

shell pasture
#

I fucking did it

iron elbow
#

You rock

shell pasture
#

My solution sucks. I tried to use cool containers standard functions and shit but it wouldn't work and at this point I'm too tired to try and figure out a cleaner solution. ||I just went nuts with manual index searching||

bold heart
#

day 1 and its already getting chunky

bold heart
#

this is what they mean by thinking outside the box

young obsidian
#

i just did it the straightforward way and didn't have to deal with that 🤷‍♀️

fossil mulch
#

I’m surprised we’re getting stuff like this on day 1

young obsidian
#

yeah, the first few days have been trivial in previous years

silent quarry
#

The way that problems are described can also at times be a bit obtuse, and important details can be easy to miss because of how they’re written

#

for example how to parse “oneight “ today

buoyant ravine
#

i somewhat agree but i actually don't think the ambiguity in this problem was atypical or even difficult but unexpected for day 1 which is why people had problems with it. different mindset and stuff, if it was like day 7-10, sure people would still be like "ah didnt see the overlap coming" but no one would complain about the difficulty

#

also while i was annoyed by it being overlapping and it not being mentioned explicitely myself, i also kind of get the choice. technically the info is all there if you read it very carefully - the example is unfortunate but that might have also been intentional to throw people off. at that point its personal taste if people find that frustrating or challenging (and again, day 1 people assume the easiest way)

unkempt topaz
#

Yeah but too often an ambiguity has lead many people to misunderstanding the rules of the problem. On later days, the expectation for clear instructions should increase not decrease, as the complexity of the problems increase. When a significant number of people completely misinterpret what the expected behavior should be, then that's an issue that should be fixed.

Another way to think about it: Is AoC supposed to provide programming challenges, or english comprehension challenges?

buoyant ravine
#

Very true, there is a fine line between not giving the solution away and keeping it riddle-like or straight up not providing enough info to solve the problem

#

ig we'll see a trajectory for this year in about 6 hours

ornate raven
dawn onyx
#

No other help please, but ||can you have overlap between words? Does twone parse as 21 or 22?||

dawn onyx
#

||or I guess as 11||

dawn onyx
dawn onyx
#

||Alright, I used a regex to find the first match, then I reversed each line and ran a reverse regex eno|owt to find the last word.||

#

So earlier in the thread I'm seeing people ||replace one with o1e and then run the p1 parser on the result. which is a clever solution.|| But wouldn't you just need to do ||1e because you're only looking for overlap with the next possible word?||

#

Or wait no I see why that'd be required. ||I'm using a regex to find the words all at once, but if you're replacing one then two then three and you're not sure what order they go in, then that makes sense.||

carmine zenith
#

i dont know how im gonna find time to do ts

tawny steppe
#

while not hard as such, is it just me that thinks this day 1 puzzle is harder than usual for AoC? Straight into string parsing lol

iron elbow
#

I thought the same

lunar forge
#

bit late but i did part 1 in scratch

lunar forge
#

part 2 as well, the overlapping characters threw me for a loop :<

#

the way i handle the overlapping characters is by ||starting the string check with the last character of the most recently previously matched word||

tawny steppe
#

well, that wasn't clear at all - finally done part 2 - those examples were misleading

#

|| I was reading four1eightwo as 418 instead of 4182 as nowhere does it say overlap is fine - unless I missed it ||

#

I'll spoiler it, but I think you've all done this by now

tawny steppe
#

it was probably mentioned on here, but I've avoided spoilers

#

there's mine anyway, boring c#

fossil mulch
tawny steppe
#

yeah, was annoying, spent like an hour printing stuff out lol

#

all I needed was || the -1 here: currentIndex += numberWord.Length - 1; ||

#

my code was right according to my understanding of the assignment lol

blazing vigil
#

i redid my day 1... i'm not sure if i like this better or worse

sage lodge
#

I see people ||replacing the strings with the digits, does that really work? It looked to me like there could be two results if you replaced left to right and right to left. Unsure if that should matter, but some examples looked ambiguous||

dawn onyx
dawn onyx
sage lodge
#

Ah, interesting

dawn onyx
#

I was confused in the other way when I saw it

#

I figured ||they only needed to keep the last char||, but my mistake there was thinking about it executing ||from left to right instead of in numeric replacement order||

sage lodge
#

I ||create a window going left to right and then right to left, check if the first (direction dependent) is a number, then if it is I return that, else I check if the window ends with one of the digit strings||

teal vault
#

and because I just hate modifying strings for problems that don't need it.

dawn onyx
#

Yeah but at the same time knowing the problem domain is a part of any puzzle solution

young obsidian
#

i just ||scan the input from left to right once|| and didn't have any issues

dawn onyx
sage lodge
#

I do dislike when problems require you to know the problem domain though

#

Especially true for competitive programming challenges where a naive approach is unfeasible

dawn onyx
young obsidian
#

yes

dawn onyx
sage lodge
#

Ah no, this one was simple, I was referring to your comment

dawn onyx
#

Fair

sage lodge
#

I guess one good thing that I like about AoC is that it only cares about the output, not how you found it 😄

tawny steppe
#

am I the only one who doesn't enjoy string parsing? 😦

#

maybe it's cos I'm crap at it lol

#

doesn't interest me at all

fossil mulch
#

I hate it too. Especially this year.

sage lodge
#

I normally don't like it but I needed practice tbh

tawny steppe
#

I just cheat and use LinQ cringeharold

young obsidian
#

maybe for next year i'll finish my parser lib

#

i started making one but stopped bc i kept running into internal compiler errors in rustc

#

but that was a while ago and they've stabilized more nightly features now

tawny steppe
#

do we still need spoilers for in here?

#

||Console.WriteLine(File.ReadLines("Day1Input").ToArray().Select(l => (First:new [] {"one", "two", "three", "four","five","six","seven","eight","nine", "1", "2","3","4","5","6","7","8","9"}.Select(p => (p,l.IndexOf(p))).Where(pair => pair.Item2 != -1).MinBy(p => p.Item2).p switch {"one" => 1, "two" => 2, "three" => 3, "four" => 4, "five" => 5, "six" => 6, "seven" => 7, "eight" => 8, "nine" => 9, var x => int.Parse(x)}, Second: new [] {"one", "two", "three", "four","five","six","seven","eight","nine", "1", "2","3","4","5","6","7","8","9"}.Select(p => (p,l.LastIndexOf(p))).Where(pair => pair.Item2 != -1).MaxBy(p => p.Item2).p switch {"one" => 1, "two" => 2, "three" => 3, "four" => 4, "five" => 5, "six" => 6, "seven" => 7, "eight" => 8, "nine" => 9, var x => int.Parse(x)}) ).Select(fnl => int.Parse($"{fnl.First}{fnl.Second}")).Sum());||

#

not my code, but 1 liner in linq 😄

grand cedar
#

I'm very late to the party but anyways here is my horrible solution written in good old C

#

has too many lines to show it in discord fuck me

ornate raven
grand cedar
ornate raven
#

@grand cedar i hope you're open to comments -
the switch statement has many blocks with very similar structure ..
i think you could use a table driven approach here 👍

grand cedar
sage lodge
grand cedar
sage lodge
#

Lol yep. Can always just write C with classes, without going into the C++ insanity too deep

sage lodge
shell pasture
#

Yes I think Chiaki used that phrasing to say "write in C++ without any of the features except classes"

sage lodge
#

But it's also a way of sayi- yes what Simone said

ornate raven
#

i like c, it's kinda like a lingua franca amongst programmers;
someone who knows either one of: c++, java, javascript, php, golang will probably understand it

#

besides, it's extremely fast, there's a reason they use it to write operating systems

fossil ether
#

it's a cute little language, fun to write a compiler for

young obsidian
#

i like c too, but it's the worst choice for string manipulation

grand cedar
#

Now with a lookup table, thanks for the feedback asarandi

ornate raven
#

Khoi nice, much shorter 👍

tawny steppe
#

|| also, there are no zeros ||

tawny steppe
young obsidian
#

i mean you can call c functions from asm so it's just as fine as c is

#

no built in support, just like c!

tawny steppe
#

you said worst choice, I was just pointing out that pure asm is probably worse

young obsidian
#

it's a figure of speech. i'm sure there's a lot worse choices available if you really try

fossil ether
#

I know someone last year did it all in x86 asm 👀 imagine doing it an AoC on GB/NES

young obsidian
#

string handling would be the least of your worries on that :p

tawny steppe
#

I did day 1 of 2021 in x64

#

didn't even attempt the rest 😄

#

oh, it was 2020

#

was easy to be fair, and I cheated a bit

#
main proc
     lea rsi, [values]

    .for (r13d = 0 : r13d < 400 : r13d += 2)
        mov ax, word ptr[rsi + r13]
        movzx eax, ax
        mov r12d, eax

        .for (edx = r13d : edx < 400 : edx += 2)
            mov bx, word ptr[rsi + rdx]
            movzx ebx, bx

            mov r15d, ebx
            add ebx, eax

            .if (ebx == 2020)
                imul r15d
                invoke printf, "2020 found, sum of %d and %d. Product is: %d\n", r15, r12, rax
            .endif

            .for (r8d = edx : r8d < 400 : r8d += 2)
                mov r9w, word ptr[rsi + r8]
                movzx r9d, r9w

                mov r14d, r9d
                add r9d, ebx

                .if (r9d == 2020)
                    imul r14d
                    imul r15d
                    invoke printf, "2020 found, sum of %d, %d and %d. Product is: %d\n", r15, r12, r14, rax
                .endif
            .endfor
        .endfor
    .endfor

    invoke exit, 0

main endp```
#

I used an assembler with HLL

ornate raven
#

Spec-Chum whats the name of the assembler ?

ornate raven
#

thank you, these macros look cool, i'll check this out

winter aurora
#

Can you refactor this more?

fossil ether
#

Could solve potentially use a map and sum?

winter aurora
#

Fair enough

unkempt topaz
# winter aurora Can you refactor this more?

This is just personal preference, but, read_from_file() feels unnecessary. There's no reason you need a vec of owned strings. But even just refactor-wise, you have a function that is only called once, and is effectively one line. solve() is similar, in that the body of the function could just go in main().

#

Though I agree with leina, using map() would cut out a lot of these extra functions.

fn main() {
    let answer = std::fs::read_to_string("src/input.txt").unwrap()
        .lines()
        .map(|line| extract_number(line))
        .sum();
    println!("{answer}");
}
young obsidian
#

.map(|line| extract_number(line)) can be written as .map(extract_number)

sage lodge
#

Even better:

fn main() {
    let answer = include_str!("input.txt")
        .lines()
        .map(extract_number)
        .sum();

    println!("{answer}");
}
unkempt topaz
unkempt topaz
# winter aurora Can you refactor this more?

Oh another note, as you used in extract_number, if you're returning something on the last line of a function (or closure) then you don't need to explicitly type return whatever;.

In the first function at lines 5-6, (without analyzing/changing the first line) I'd rewrite this like so:

if temp.is_empty() {
    None
} else {
    Some((first, last))
}
```(replacing `first` and `last` accordingly)

This entire block will be used as the return expression, and imo this makes the function easier to read.
sage lodge
#

Can also do temp.is_empty().then_some((first, last))

young obsidian
#

you forgot to negate temp.is_empty()

unkempt topaz
#

Hmm? Why would you need to negate it?

#

If you did, and the vec is empty, then .first().unwrap() would panic.

young obsidian
#

then_some makes a Some if the bool is true

#

but you want a Some if temp.is_empty() is false

#

going by that code snippet

unkempt topaz
#

Oh you meant in response to Chiaki, yeah that's true then, would need to negate that.

#

(this kind of confusion is why I gave the if-else block example instead; since it's much harder to mix up imo)

sage lodge
#

whoopsie