Any tips, tricks, or optimal ways for doing something similar in the future? I am not an expert, just c/c++ enjoyer and I want to get some feedback, thanks.
Code is uploaded on github: https://github.com/bwilk315/aoc23/tree/main/day1
#My AOC23 Day 1 solution, what can I do better?
57 messages · Page 1 of 1 (latest)
Oooff.... A lot of things
I guess vectors are involved
There are very many things that are rather bad with the code. I'll get back home in 20 minutes, make myself some tea and get back to you
appreciate that
the code is more like C than C++
you're using fixed length arrays, when a vector would be far less error prone
same for char buffers vs. std::string
extractDigits is returning a size and writes into a pointer, but it could just return the vector
First of all, you should not use char* in C++. We have better tools to deal with text - not much, but still
However, even if you want to try and use char*, you're using it in an extremely inefficient way, without actually using the standard library
Your function strfind has many issues.
Parameter n is unused, so it always looks for the first occurrence.
Using a separate buffer to compare the strings is very inefficient, especially since you are sitting it left all the time - it's simply bad. Instead use pointer arithmetic to just move one pointer to the next character, and then strncmp here, but...
Even if you use const char*, there is a function for searching for a string in a string. It's called strstr
It will return a pointer to the first found occurrence. If you need the position, subtract the pointers
Don't use ASCII codes, use char literals to convey meaning:
c >= '0' && c <= '9'
I'd recommend using std::print (if you use MSVC) or at least cout instead of printf
Your control sum is boolean in nature, no point of it being an integer
Your while loop should be likely a for loop, counting the loops as you already do, and then as condition for continuation use the flag you'd have instead of control_sum
In your function extract digits you already construct a vector, only to copy it to some fixed size buffer - why not just return the vector and be happy?
One you do all these changes, use std:: during instead of char* you will be able to use range for loop instead of the most of your loops
I literally thought returning such would be inefficient
the same
Yeah I should have done some research on what the standard library provide me with
actually n is used for detecting the n-th occurrence, it is then used to collect all of them but now I realized it is unnecessarily complicated
thank you for details answers
what's your reasoning for this? like, what could happen here that would be less efficient than copying the entire thing?
I should put more effort in theory of the function, I have programmed bunch of practical apps in few different languages (python, c++, unity c#...) and I have never taken efficiency into account - just make it work and you're done ... therefore I ask questions here to explore new ways of thinking about what a good program really is
yeah, so, if you just return the vector, there won't even be a copy i think
because of named return value optimization
but isn't returning vector actually returning a pointer to it?
Nope, that's the thing: std::strings, std::vectors, std::array and friends are ~containers~, they behave like proper objects. Returning them returns their content. Also, it is usually extremely fast. Best case - it's free, the compiler already created the object where it had to end up. Worst case - it's super cheap, as the ownership of the allocated buffer is just "move"d out of the function
c++ has value semantics so if you return a value, it's a value, and if you return a pointer, it's a pointer
I am gonna apply your tips
#include <iostream>
std::string amogus() {
std::string inner = "Among us";
std::cout << &inner << std::endl;
return inner;
}
int main() {
std::string outer = amogus();
std::cout << &outer << std::endl;
return 0;
}
Ownership exists indeed, addresses are the same :O
I refactored the day 1, so it uses string utilities and map
What you see here is not necessarily ownership. It is... complicated.
So, what you see in this example is NRVO - named return value optimization. So, that std::string object that is returned got put immediately in its position after return
That's a very common optimization, but not always the case - you sometimes can have transfer of ownership, but the object is in a different place
You can check the address returned by .data(), so where string data is actually stored
However, strings are rather special as they use something called Small Buffer Optimization
So, quick intro into how strings work (kinda):
namespace std {
class string {
union{
char sbo_buffer[16];
struct {
char* end;
char* storage_end;
};
};
char* begin;
}
So... it's rather complicated, despite being simplified. The idea is, that allocating memory (with new) is a relatively expensive operation, that we would like to avoid. So for strings of small length (in the example above: 15 or smaller) will be stored "within the string", and bigger: will have memory allocated and stored in begin
How do end and storage_end pointers occupy the same space as sbo_buffer?
this is what I understand when I see unions in action
They do occupy the same space - it is kind of interpreted differently, depending on the content of begin - if begin points into the beginning of the string object, it knows it uses SBO
Kind of - it's not exactly like that, but that's the main idea
I'll probably touch this in the future, I focus on exploring optimal ways of programming
About two months ago there was a programming contest in my area that would let you easily join any college, but it was heavily about things in which not any way of achieving a goal is the right way, they love to use fibonacci numbers to test your knowledge of algorithm optimization (because usually the first version is very ineficcient)
yeah, there's much more to algorithms than just that 😅 but it is a good start
this is why my world generation in unity was very buggy when you explored a river xD
this is all fun and games until you do not have any optimization tricks left and the game still runs very slow
then you just have to think more 
terrain generation can be really really difficult tho
in general any sort of spatial stuff is hard, in my experience
actually yes, normally when you have a 2D camera it is not that complicated to for example hide when something is not visible, when you have additional third dimension, you have to do more calculations and invent new ways
it was probably called "oclussion culling"
yeah