I tried a couple things with the video today around bitrates and such, please let me know if you see any improvements in the video image quality. I did today's solution in much more of a "for loops and splits" approach since i had some people saying theyd appreciate seeing that and todays looked good to show off what problems that can cause (like mis-ordering x and y). Ive got a refactor video coming later today too showing a much different approach
@chrisbiscardi Loving your Advent of Code series so far! Quick note for you: this video isn't added to your AoC 2023 Playlist, but the refactor video is. I was momentarily confused and found this original solution video on your channel. Might want to drop this one in before the refactor video!
I have never written Rust before, and I am using Advent of Code to learn it. While I think your algorithms are far from optimal, watching your solutions after solving the challenges myself help me understand the language itself and where I can improve my own solutions with the new tools I see in your solutions.
Solved this one a lot different, and it took me WAY longer. I really appreciate seeing your approach to things, and I 100% agree with you on using types to avoid issues like tuple positions, etc. Eager to see your refactor.
I haven't managed to finish part 1 yet because of a bug leading to some numbers being missed. But i took a somewhat different approach. I used 2 regexes, one for symbols, one for numbers. I loop though input twice. I iterate over the input.lines(), and use regex.find_iter() to loop over all the matches. First time through things I just locate symbols, and track the adjacent indexes (I'm using a HashMap to store that stuff, but that's really more of an implementation detail). Second loop around I again use .lines() and .find_iter(), so I loop though each number on each line. I check to see if any of the adjacent indices for the current line are within the bounds of the current number's match. If so, count the number.
First time writing in Rust, so took me a while. I used a queue (VecDeque) to store symbols' indeces for previous line, current line and next line. Then I read the file line by line, shifted values in queue and then checked numbers in current line against indexes in queue. Part 2 was just the other way around: storing numbers in queue and checking current line symbols against it.
I started by build a Vec of all symbols (everything that isn't a dot or a number) with their row and column. This part was pretty easy, since each symbol is just one character, so it was just chars().enumerate().filter_map(). Then I iterated through the lines again to find all the numbers with their coordinates, and filter them based on whether there was a symbol in the previous Vec that was within 1 row and 1 column of the number. That second step was difficult because I was keeping an index to the current slice that I was parsing and I kept messing up when I had to add this offset to get the position in the whole line, and when I had to update it to find the next number in the line. It took me like 40 minutes of debugging until I got it right. Then I asked ChatGPT out of curiosity how it would do the numbers part, and it just used Regex::find_iter, which does exactly what I was trying to do with my manual indices. I guess I do need to practice these crates a bit more.
I used exactly that, .find_iter(). Used it twice. I had 2 regexes, one for symbols, one for numbers. Loop through each line once and find all symbols. Track all locations adjacent to a symbol on the line above, the current line, and the one below. Loop though each line a second time and find all numbers, checking all "adjacent indexes" on the same line whether it's within the range of the number's characters or not. If it of, count it. Overall it's pretty simple conceptually, but I have a bug somewhere leading to some numbers not being counted I still have to deal with :/
Would appreciate it if you called out everything you changed during a cut. It makes you very hard to comprehend if following along with the video. But, uh, considering how messy this implementation you were asked to take is... I can't really blame you that much. Thanks
I'll be better about this in other days (and so far, I feel like I have been better in days 1 and 2 about this). Like you said, the implementation is really messy and I'm not sure how useful it is to actually go through it. I was spending a lot of time remembering which order I had x/y in and such, for example. I'm planning to spend more time explaining in the refactoring video
In part 1, I looped over the input (with two nested for loops) to fill in a HashSet of the row and column of the symbols. Then I looped over the input again to parse the numbers. I kept track of the starting and ending columns for the number, and then looped over all of the adjacent positions to see if they were in the HashSet. No fancy functional programming; just loops and mutable variables. In part 2, I built a HashMap of the locations of '*' symbols; the value was a Vec of numbers. Looped over the input again, and pushed the parsed number onto the Vec for any adjacent '*'. Lastly, looped over the values in the HashMap, filtered for Vec of length 2, mapped the vec to its .product(), and .sum() the products. It would probably be easy to combine the two parts, and solve both with just two iterations of the input. I'm feeling lazy, so I'm not going to bother with that right now; maybe I'll get to it next year.
My part 1 solution worked on the example, but didn't work on the real input. The problem turned out to be numbers that existed at the end of a line. I had been using non-digit characters to detect the end of a number, and start searching for adjacent symbols. The fix was to essentially add a dot to the end of every line by doing `line.chars().chain(Some('.')).enumerate()`. That got me the correct answer.
I had to give up after two hours. I had solved it for the test input, but my result in the test file was too high all the time then and I did not find my error.
I ended up making a hashmap of where record = Number(i32, bool), empty or symbol(char) -- made my life so easy :D I do have to get into doing it the rust way tho, since I ended up doing comparisons like x > &0 because x was a &i32
Usually *x > 0 works to too in that case (but coming from C++ it still feels weird to explicitly dereference a reference, which is why my brain thinks it’s a raw pointer and gets scared lol)
@@TRex266 I'm a long time C programmer, so I totally get the hesitation to dereference. But a greater-than comparison of references (which my C brain reads as pointers) feels far worse.
you supposed we understand the puzzle? what if we don't understand the puzzle, how can I follow the video? also you supposed we know why you are choosing enum and btree... i think you shouldn't suppose that 😁
I tried a couple things with the video today around bitrates and such, please let me know if you see any improvements in the video image quality.
I did today's solution in much more of a "for loops and splits" approach since i had some people saying theyd appreciate seeing that and todays looked good to show off what problems that can cause (like mis-ordering x and y). Ive got a refactor video coming later today too showing a much different approach
The video quality looks excellent to me. I'm watching on a 6K monitor and getting the 2160p 4K stream.
@chrisbiscardi Loving your Advent of Code series so far!
Quick note for you: this video isn't added to your AoC 2023 Playlist, but the refactor video is. I was momentarily confused and found this original solution video on your channel. Might want to drop this one in before the refactor video!
I have never written Rust before, and I am using Advent of Code to learn it.
While I think your algorithms are far from optimal, watching your solutions after solving the challenges myself help me understand the language itself and where I can improve my own solutions with the new tools I see in your solutions.
That's the goal, so I'm glad you're finding it useful in that way!
I was at this one for a while today in rust. Difficulty went from 0 to 60 real quick lol
We all agree: Rust is not normal
Solved this one a lot different, and it took me WAY longer. I really appreciate seeing your approach to things, and I 100% agree with you on using types to avoid issues like tuple positions, etc. Eager to see your refactor.
I haven't managed to finish part 1 yet because of a bug leading to some numbers being missed. But i took a somewhat different approach.
I used 2 regexes, one for symbols, one for numbers. I loop though input twice.
I iterate over the input.lines(), and use regex.find_iter() to loop over all the matches. First time through things I just locate symbols, and track the adjacent indexes (I'm using a HashMap to store that stuff, but that's really more of an implementation detail).
Second loop around I again use .lines() and .find_iter(), so I loop though each number on each line. I check to see if any of the adjacent indices for the current line are within the bounds of the current number's match. If so, count the number.
First time writing in Rust, so took me a while. I used a queue (VecDeque) to store symbols' indeces for previous line, current line and next line. Then I read the file line by line, shifted values in queue and then checked numbers in current line against indexes in queue. Part 2 was just the other way around: storing numbers in queue and checking current line symbols against it.
I started by build a Vec of all symbols (everything that isn't a dot or a number) with their row and column. This part was pretty easy, since each symbol is just one character, so it was just chars().enumerate().filter_map(). Then I iterated through the lines again to find all the numbers with their coordinates, and filter them based on whether there was a symbol in the previous Vec that was within 1 row and 1 column of the number. That second step was difficult because I was keeping an index to the current slice that I was parsing and I kept messing up when I had to add this offset to get the position in the whole line, and when I had to update it to find the next number in the line. It took me like 40 minutes of debugging until I got it right.
Then I asked ChatGPT out of curiosity how it would do the numbers part, and it just used Regex::find_iter, which does exactly what I was trying to do with my manual indices. I guess I do need to practice these crates a bit more.
I used exactly that, .find_iter(). Used it twice.
I had 2 regexes, one for symbols, one for numbers.
Loop through each line once and find all symbols. Track all locations adjacent to a symbol on the line above, the current line, and the one below.
Loop though each line a second time and find all numbers, checking all "adjacent indexes" on the same line whether it's within the range of the number's characters or not. If it of, count it.
Overall it's pretty simple conceptually, but I have a bug somewhere leading to some numbers not being counted I still have to deal with :/
Would appreciate it if you called out everything you changed during a cut. It makes you very hard to comprehend if following along with the video.
But, uh, considering how messy this implementation you were asked to take is... I can't really blame you that much.
Thanks
I'll be better about this in other days (and so far, I feel like I have been better in days 1 and 2 about this).
Like you said, the implementation is really messy and I'm not sure how useful it is to actually go through it. I was spending a lot of time remembering which order I had x/y in and such, for example. I'm planning to spend more time explaining in the refactoring video
In part 1, I looped over the input (with two nested for loops) to fill in a HashSet of the row and column of the symbols. Then I looped over the input again to parse the numbers. I kept track of the starting and ending columns for the number, and then looped over all of the adjacent positions to see if they were in the HashSet. No fancy functional programming; just loops and mutable variables.
In part 2, I built a HashMap of the locations of '*' symbols; the value was a Vec of numbers. Looped over the input again, and pushed the parsed number onto the Vec for any adjacent '*'. Lastly, looped over the values in the HashMap, filtered for Vec of length 2, mapped the vec to its .product(), and .sum() the products.
It would probably be easy to combine the two parts, and solve both with just two iterations of the input. I'm feeling lazy, so I'm not going to bother with that right now; maybe I'll get to it next year.
My part 1 solution worked on the example, but didn't work on the real input. The problem turned out to be numbers that existed at the end of a line. I had been using non-digit characters to detect the end of a number, and start searching for adjacent symbols. The fix was to essentially add a dot to the end of every line by doing `line.chars().chain(Some('.')).enumerate()`. That got me the correct answer.
I had to give up after two hours. I had solved it for the test input, but my result in the test file was too high all the time then and I did not find my error.
I ended up making a hashmap of where record = Number(i32, bool), empty or symbol(char) -- made my life so easy :D
I do have to get into doing it the rust way tho, since I ended up doing comparisons like x > &0 because x was a &i32
Usually *x > 0 works to too in that case (but coming from C++ it still feels weird to explicitly dereference a reference, which is why my brain thinks it’s a raw pointer and gets scared lol)
What would be the purpose of number being an (i32, bool) instead of just an u32?
@@ticua07 I'm using the boolean to indicate it as 'visited' or not, I'm basically using the hashmap as a graph
@@TRex266 I'm a long time C programmer, so I totally get the hesitation to dereference. But a greater-than comparison of references (which my C brain reads as pointers) feels far worse.
same idea
noice!
unreachable! would probably have been more appropriate than unimplemented! 9:35
definitely, but I also wasn't sure if I was correct or would need to go back and fix it.
@chrisbiscardi color theme name, please?
Night Owl
you supposed we understand the puzzle? what if we don't understand the puzzle, how can I follow the video? also you supposed we know why you are choosing enum and btree... i think you shouldn't suppose that 😁