Monday, 5 December 2022

Chapter 25 // Exercise 17 - Principles & Practice Using C++

In this exercise I'm using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 17

In section 25.4.3-4 we provided a class Array_ref claimed to make access to elements of an array simpler and safer. In particular, we claimed to handle inheritance correctly. Try a variety of ways to get a Rectangle* into a vector<Circle*> using an Array_ref<Shape*> but no casts or other operations involving undefined behaviour. This ought to be impossible.

Github: N/A

Wow it's been a hot minute since I last looked at the FLTK code. I would avoid using arrays entirely but this little class is handy. There's no code for this one as none of it compiles anyway.

And with that I'm onto the second to last chapter of the book...it feels strange. What will I do without the exercises in this book hanging over my head?


Sunday, 4 December 2022

Chapter 25 // Exercise 16 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 16

Formulate 20 coding style rules (don't just copy those in section 25.6). Apply them to a program of more than 300 lines that you recently wrote. Write a short (a page or two) comment on the experience of applying those rules. Did you find errors in the code? Did the code get clearer? Did some code get less clear? Now modify the set of rules based on this experience.

This was a really interesting exercise for me as my coding style has changed so much over the past 7 years. I could probably make a video talking about this. It's even changed a lot over the past 3 years I've been putting my code on github.

Currently my 20 rules would be:
  1. Dashed lines between functions (I picked this up from work and now I will put bugs on code reviews if people have forgotten dashed lines)
  2. UpperCamelCase to be used for object creation, enums to use capital snake case and everything else should use lowerCamelCase (this is in direct violation of Bjarne's R302 but he can suck it, camelCaseForever. I also use Hungarian Notation for vectors sometimes because why be completely consistent?)
  3. All member variables should be prefixed with m
  4. All global variables should be prefixed with g
  5. Function argument parameters should be prefixed with p
  6. Enums should be prefixed with e and be all uppercase afterwards. Example; ePURPLE_CRAYON
  7. Where a function argument parameter is not modified in the function, it should always be passed by const reference (unless it's cheaper to just pass by const value)
  8. References should be used over pointers where possible
  9. Prefer std::vector over raw arrays
  10. const_cast should not be used
  11. Prefer ifndef/define over pragma once
  12. All local variables should be declared as const/constexpr unless they need to be modified
  13. Commonly used (non-changing) local variables should be declared in a private namespace in the cpp of the file they are used in
  14. Avoid mixing static member variables with non-static. Either create a namespace or singleton with all static functions/members
  15. Try to order member variables in descending size order
  16. Braces {} should always be on their own line. The only exception is 1 line functions in header files (or empty constructors/destructors)
  17. Avoid post-fix increment/decrement unless the functionality of post-fix is specifically needed. Always prefer pre-fix increment/decrement
  18. Includes should be in grouped order of local (""), then global (<>). Each group should be in alphabetical order
  19. Include what you use. Prefer including in the cpp with forward declares in the header. Only include in the header if you must
  20. Avoid lambda's. Only use them if you must
When I first started programming back in January 2016, I had no one to talk to about C++ and used this book or stackoverflow to try and complete exercises. When I started my degree that September, I started picking up habits from my tutors code and youtube videos. For those first 3 years my code style heavily resembled what you see in the book. Then I started working at Rare and at first I fought against the strict coding style/rules. I used them because I had to but over the past 3 and half years I've grown to love some of those rules, and the ones I don't like don't bother me anymore. I'd say my current style is the one I'll probably stick to now as I find it clear, concise and maintainable. 

I would say rules 1-6 are just me being picky and pedantic however the rest are extremely useful in production code and can even help you avoid bugs and provide a better debugging environment.

Saturday, 3 December 2022

Chapter 25 // Exercise 15 - Principles & Practice Using C++

In this exercise I'm using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 15

Measure the time (section 26.6.1) it takes to allocate 10,000 objects of random sizes in the [1000:0)-byte range using new; then measure the time it takes to deallocate them using delete.

Do this twice, once deallocating in the reverse order of allocation and once deallocating in random order. 

Then, do the equivalent  of allocating 10,000 objects of size 500 bytes from a pool and freeing them.

Then, do the equivalent of allocating 10,000 objects of random sizes in the [1000:0)-byte range on a stack and then free them (in reverse order). 

Compare the measurements . Do each measurement at least three times to make sure the results are consistent.

I split this up into several parts. For the object of random size I created a struct that holds a string, the string then reserves a random size between 0, 1000. A vector of that struct is created to hold the pointers to the object created.

---- Part 1 ----
(No pool or reserved allocation)
Allocate 10,000 objects: 1(19ms), 2(20ms), 3(21ms)
Deallocate in reverse order: 1(9ms), 2(10ms), 3(10ms)

---- Part 2 ----
(No pool or reserved allocation)
Allocate 10,000 objects: 1(20ms), 2(20ms), 3(21ms)
Deallocate in random order: 1(11ms), 2(11ms), 3(11ms)

For the ones with a pool I decided to not use new and delete and instead create a vector with a reserved size of 10,000 500-byte objects. That way when you pushback it won't need to allocate more space. Then "freeing" is as simple as just clearing the string.

---- Part 3 ----
(with reserved allocation of 500 bytes per object)
Allocate 10,000 objects: 1(14ms), 2(8ms), 3(8ms)
Deallocate in reverse order: 1(1ms), 2(1ms), 3(0ms)

---- Part 4 ----
(with reserved allocation of 500 bytes per object)
Allocate 10,000 objects: 1(14ms), 2(14ms), 3(14ms)
Deallocate in random order: 1(1ms), 2(1ms), 3(1ms)

---- Part 5 ----
(no pool, on std::stack)
Allocate 10,000 objects: 1(24ms), 2(24ms), 3(24ms)
Deallocate in random order: 1(15ms), 2(16ms), 3(16ms)

Allocating with a pool is always faster because the memory you need is right there. Memory pools are used a lot in games (you may hear them being called "banks" as well).

Friday, 2 December 2022

Chapter 25 // Exercise 14 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 14

Implement a simple vector that can hold at most N elements allocated from a pool. Test of for N === 1000 and integer elements.

I used my vector implementation from Chapter 19 - Exercise 8:

As this uses a custom allocator. I then modified the constructors to be able to take in 2 values; the number of elements required and the size of the allocator. If the size of the allocator given is more than 0 or more than the number of elements given, the constructor for MyVector will then reserve that space.

The allocator uses malloc, free and placement new. So on construction, it will allocate space based on the size of the allocator, then when we specify the number of elements, it will use placement new to "place" those elements into the already allocated memory.

Wednesday, 23 November 2022

Chapter 25 // Exercise 13 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 13

Use TEA (section 25.5.6) to communicate "securely" between two computers. Email is minimally acceptable.

Github: N/A

Using the program I created from here:

I created this "secure" message:

The key is "plumbus".

If you crack it, paste the message in the comments.

(If you're using my code, you'll have to edit the decipher function to read the correct text file).

Tuesday, 22 November 2022

Chapter 25 // Exercise 12 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 12

Write out the clear text of the example from section 25.5.6.

Github: N/A

Deciphering the text was part of Exercise 1. You can find the code here:

The deciphered text reads:
The Tiny Encryption Algorithm is one of the fastest and most efficient cryptographic algorithms in existence.
It was developed by David Wheeler and Roger Needham at the Computer Laboratory of Cambridge University.
It is a Feistel cipher which uses operations from mixed (orthogonal) algebraic groups - XOR, ADD and SHIFT in this case.
This is a very clever way of providing Shannon's twin properties of diffusion and confusion which are
necessary for a secure block cipher, without the explicit need for P-boxes and S-boxes respectively.
It encrypts 64 data bits at a time using a 128-bit key. It seems highly resistant to differential
cryptanalysis, and achieves complete diffusion (where a one bit difference in the plaintext will
cause approximately 32 bit differences in the ciphertext) after only six rounds. Performance on a
modern desktop computer or workstation is very impressive.

Monday, 21 November 2022

Chapter 25 // Exercise 11 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 11

Repeat the previous exercise, but keep the bits in a bitset<32>.
This was extremely easy and just involved converting the bitset to unsigned long longs in places. I like that you can subscript a bitset however, it's weird that you can't do other container-like things like set a range of the bitset.

Sunday, 20 November 2022

Chapter 25 // Exercise 10 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 10

Look at the bitfield example from section 25.5.5. Write an example that initialises a PPN, then reads and prints each field value, then changes each field value (by assigning to the field) and prints the result. Repeat this exercise, but store the PPN information in a 32-bit unsigned integer and use bit-manipulation operators (section 25.5.4) to access the bits in the word.
When I first read this, my immediate thought was "wtf?" Then I read it again, looked at the example and reminded myself it's just a simple bitfield exercise. Then I got to the second half where you have to read and write to an integer and that took me an hour to wrap my head around.

It's safe to say though, I now understand how shifting and masking works. It's actually much simpler that google makes it out to be. I hope my comments on the code show that. I found drawing it out on paper really helped visualise which bits to mask/shift.


Saturday, 19 November 2022

Chapter 25 // Exercise 9 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 9

Without using any standard headers (such as <limits>) or documentation, compute the number of bits in
an int and determine whether char is signed or unsigned on your implementation.


So to print the number of bits in an int we know that sizeof() will return us the number of bytes in a type so you can just multiply that by 8. I don't think this is cheating as sizeof is a keyword in C++ and doesn't require any standard headers to be used. 

For the second part, I used the example from page 964. It shows that char is default signed on my machine.

Friday, 18 November 2022

Chapter 25 // Exercise 8 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 8

Write out the numerical values of each character on your keyboard.


I cheated and just printed out all the ascii characters in a for loop as they're all on my keyboard anyway.

Thursday, 17 November 2022

Chapter 25 // Exercise 7 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 7

Write out the hexadecimal values from 0 to 400; write out the hexadecimal values from -200 to 200.


After the last exercise I honestly thought that this would trigger an infinite loop or something because Bjarne has that type of humour.

Wednesday, 16 November 2022

Chapter 25 // Exercise 5, 6 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 5

Write an infinite loop. Execute it.


Simple enough.

Chapter 25 // Exercise 6

Write an infinite loop that is hard to recognise as an infinite loop. A loop that isn't really infinite because
it terminates after completely consuming some resource is acceptable.


For this one I immediately though of a for loop going backwards but checking if the index was >= 0 (I'm not proud to say I've done this before...). However, Visual Studio is very smart these days and will give you an intellisense warning that the loop is infinite.

It also does the same for the old if(bool = false). I even googled for one but VS even recognised that as infinite. The best way to do it would be to just allocate memory in a recursive function.

Tuesday, 15 November 2022

Chapter 25 // Exercise 4 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 4

Add the bitwise logical operators &, |, ^, and ~ to the calculator from chapter 7.


Just when you thought it was safe, chapter 7 returns. I last touched that code 3 years ago now according to GitHub. I remember absolutely hating tokens and token streams because I thought they were some weird special type...it's just a class that gets characters from the cin buffer lol. I really love going back to old exercises as it makes me realise that I have learnt something after all.

I decided to go with the finished code from exercise 9:

And started by cleaning it up and putting it into seperate files. Then I added the bitwise operators  to my enum of symbols.

Now, as per the rules of the calculator, &, | and ^ are all expressions as they need primary's to operate on. However ~ is a prefix and can be used by itself so that makes it a primary. The main problem though is that you can't use (or shouldn't be using) bitwise operators on doubles as they're made up of 3 parts and our Tokens store all values as doubles.

To get round this I just cast everything to an int and then perform the operations but it prints a warning if the double wasn't safely converted to a float using std::modf();

I also made it so NOT requires parenthesis around the expression so you can do things like ~(5+4+sqrt(25)).

Chapter 25 // Exercise 4 - Principles & Practice Using C++


Monday, 25 July 2022

Chapter 25 // Exercise 3 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 3

Initialise a 32-bit signed integer with the bit patterns and print the result: 
- all zeros, 
- all ones,
- alternating ones and zeros (starting with a leftmost zero), 
- alternating zeros and ones (starting with a leftmost one),
- the 110011001100...pattern, 
- the 001100110011...pattern, 
- the pattern of all-one bytes and all-zero bytes starting with an all-one byte, 
- the pattern of all-one bytes and all-zero bytes starting with an all-zero byte. 
Repeat that exercise with a 32-bit unsigned integer.

.

Sunday, 24 July 2022

Chapter 25 // Exercise 2 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 2

Make a list of words that can be spelled with hexadecimal notation. Read 0 as o, read 1 as l, read 2 as to, etc.; for example Foo1 and Beef. Kindly eliminate vulgarities from the list before submitting it for grading.

Github: n/a

The first time I saw 0xdeadbeef at work whilst debugging, I thought I had done something terribly wrong. I was told it's often used to initialise unused memory and makes it "stand out" more when debugging.

I used an anagram solver for this one though:
And it gave me 1788 combinations...I won't list them all here but you can put: olizasgtbcdef into the textbox to see what it will generate.

Thursday, 21 July 2022

Chapter 25 // Exercise 1 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Exercise 1

If you haven't already, do the Try this exercises in this chapter.


Pg 939 Complete the program above and print out the addresses and sizes of the objects created to see if and how "holes" appear on your machine. If you have time, you might draw memory layouts likes the ones above to better visualise what's going on.

I couldn't get this one to work, or to visualise what he was showing in the book. When a message was deleted, a new node wouldn't take it's place in that freed up memory; it would go somewhere else. Sometimes it did though.

Pg 959 - Get the bits example to work and try out a few values to develop a feel for binary and hexadecimal representations. If you get confused about the representation of negative values, just try again after reading section 25.5.3.

The bits example wouldn't compile due to a narrowing conversion error. I had to add a static cast to the bitset constructor.

Pg 963 - The following example may look innocent, but it is an infinite loop:
void infinite()
{
unsigned char mx = 160; // very large
for(signed char i = 0; i < max; ++i) cout << int(i) << '\n';
}
Run it and explain why.

A signed char can be in the range of -127 to 127. An unsigned char can be 0 - 255. The signed char therefore will never reach 160 and it will wrap round causing the infinite loop.

Pg 965 - Draw out the bit patterns on a piece of paper. Using paper, then figure out what the answer would be for si=128. Then run the program to see if your machine agrees.

This one was interesting. I was expecting the signed chars to print -127 but they did -128 instead.

Pg 973 - The key was bs; what was the text?

This one took me a while as the code in the book enciphers and I kept wondering why my text file was filled with hex afterwards; turns out I should read the code more carefully.



Monday, 20 June 2022

Chapter 25 // Drill 3, 4, 5 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Drill 3

Using hexadecimal literals, define short unsigned ints with:
  • Every bit set
  • The lowest (least significant bit) set
  • The highest (most significant bit) set
  • The lowest byte set
  • The highest byte set
  • Every second bit set (and the lowest bit 1)
  • Every second bit set (and the lowest bit 0)

Chapter 25 // Drill 4

Print each as a decimal and as a hexadecimal.

Chapter 25 // Drill 5

Do 3 and 4 using bit manipulation operations (|, &, <<) and (only) the literals 1 and 0.


I cheated with drill 3 and just wrote out the binary then converted it to hex using 

5 was annoying because you can directly type out binary literals in C++14 and assign them to things. The challenge came from only using 1 and 0. Like setting the highest byte can be done with 1 << 15 but 15 isn't 1 or 0.

I honestly had no idea how to do the last 2 using only 1 and 0, so I cheated and just used direct binary strings.


Sunday, 19 June 2022

Chapter 25 // Drill 1, 2 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 25 // Drill 1

Run this:
int v = 1; for(int i = 0; i < sizeof(v)*8; ++i) { cout << v << ' '; v << =1; }

I've never seen <<= before. But shifting to the left by 1 is the "cheapest" and "fastest" way to multiply by 2. In some very low-level engine code at work, I often see >> 1 to divide by 2 instead of / 2, however it's not 1995 anymore and Visual Studio will convert divides/multiplies that are powers of 2 to an equivalent shift for you.

The last number will wrap as it's 1 over the max limit of a signed int.

Chapter 25 // Drill 2

Run that again with v declared to be an unsigned int.


.

Saturday, 18 June 2022

Chapter 24 // Exercise 12 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 12

Implement
Matrix<double> operator*(Matrix<double,2>&, Matrix<double>&);
and
Matrix<double, N> operator+(Matrix<double, N>&, Matrix<double, N>&)
If you need to, look up the mathematical definitions in a textbook.


So the first one is already supplied on page 913. Here he refers to it as a vector, but a 1 dimensional matrix is a vector.

For the second I discovered you can't use Bjarne's code to initialise a 3d matrix with a 3d array as it will cause a heap corruption. So I created a little function to use with the inbuilt apply to quickly populate the 3d matrix.

Being able to add a matrix of any incoming dimension was a bit of a head scratcher until I came across this post:

std::transform takes in an iterator to the beginning and end of your container, then uses a function object on each element. Matrix doesn't have iterators but it does supply a pointer to the beginning of the data. So I supplied transform with the raw data pointers, the size of the matrix and a new matrix to put the data into to. This way we don't have to care how many dimensions there actually are.

And with that chapter 24 is done! For once I didn't take 3 months to finish a chapter. Really looking forward to the embedded systems one (which is next) and the final chapter on C programming.

Friday, 17 June 2022

Chapter 24 // Exercise 11 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 11

Write a swap_columns() to match swap_rows() from section 24.5.3. Obviously, to do that you have to read and understand some of the existing Matrix library code. Don't worry too much about efficiency; it is not possible to get swap_columns() to run as fast as swap_rows().


I started off by modifying the swapRow function I did for vectors in exercise 7. Once that was working, I simply switched the subscripting round. Then copied that into a member function for 2d matrixes.

Thursday, 16 June 2022

Chapter 24 // Exercise 10 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 10

How random is your default_random_engine? Write a program that takes two integers n and d as inputs and calls randint(n) d times, recording the result. Output the number of draws for each of [0:n] and "eyeball" how similar the counts are. Try with low values for n and with low values for d to see if drawing only a few random numbers causes obvious biases.


I used some of the code on pg 915/916 but didn't add the normal distribution bit. Originally, the std_lib_facilities file did not seed the default random engine so it wasn't random at all. I changed that a while back and now it uses the pc time as a seed so it's almost always different. On this run, it looked pretty random? That said I just did a 5 draws with a max of 5 over and over and it started to seem pretty suspicious after while. But for a single number I need now and then, it's fine.


Wednesday, 15 June 2022

Chapter 24 // Exercise 9 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 9

Rewrite the non-member apply() functions to return a Matrix of the return type of the function applied; that is, apply(f, a) should return a Matrix<R> where R is the return type of f. Warning: The solution requires information about templates not available in this book.


Fortunately, as I attempted exercise 3, I already had a way to determine the return type of f by checking to see if it was void:
// if the return type of pFunction is not void
if constexpr (!std::is_same_v<std::invoke_result_t<F, decltype(pContainer[0])>, void>)
This uses std::invoke_result which is C++17, but the C++11 alternative is std::result_of. std::is_same is also available in C++11 so I have a feeling, the std metaprogramming library is what he was hinting at:
https://en.cppreference.com/w/cpp/meta

I used the result of invoke_result to determine the return type then create a matrix of that return type and used auto to let the function determine what it should return.

It works for one specific scenario. I still need more practice with metaprogramming to try and fix this as I was scratching my head as to why it just wouldn't deduce the type. This is definitely an exercise to come back to in the future.

Tuesday, 14 June 2022

Chapter 24 // Exercise 8 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 8

Animate the Gaussian elimination.


Honestly had no idea what he meant by this. I assumed just show the matrix being modified after each step?

Whilst doing this I had a look back at my slice function and even though it looks different to the one in Matrix.h it actually does the job! I had a google for C++ solutions on Gaussian Elimination and found this:

Which is way less code, however all that subscripting is hard to read. I prefer having the seperate function to scale, get the dot_product etc.; it's easier to read what's happening. Also, having to modify Bjarne's matrix code to work with vectors was an enjoyable challenge. I created some matrices to test with Bjarne's code from exercise 5 and this produces the same output.

I went into these 5 exercises on Gaussian elimination terrified because maths and whereas I still don't fully get what the point of it is, these exercises were a good lesson on not really needing to understand the bigger picture; just verify that the code is doing the correct thing and that I can read and understand the code.


Monday, 13 June 2022

Chapter 24 // Exercise 7 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 7

Rewrite the Gaussian elimination program without using the Matrix library; that is, use built-in arrays or vectors instead of Matrixes.


For this I initially change the
using MatrixD2 = Numeric_lib::Matrix<double, 2>;
using MatrixD1 = Numeric_lib::Matrix<double, 1>;
to
using MatrixD2 = vector<vector<double>>;
using MatrixD1 = vector<double>;
Then started going through the code and replacing what was red until it compiled. The hardest part was creating a slice for vector for the scale and add....I think my solution is working? I'm terrible at maths though and found this exercise particularly difficult.

Sunday, 12 June 2022

Chapter 24 // Exercise 6 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 6

In the Gaussian elimination example, replace the vector operations dot_product() and scale_and_add() with loops. Test, comment on the clarity of the code.


For this one I simply copied the code from the Matrix.h files. Replacing the one in the back_substitution was horrible. 

We have functions for a reason; to do tasks, remove duplicate code and make it clear what's happening without commenting.

Saturday, 11 June 2022

Chapter 24 // Exercise 5 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 5

Try the Gaussian elimination program with A == { {0 1} {1 0} } and B == { 5 6 } and watch it fail. Then, try elim_with_partial_pivot().


Ok, so after seeing this exercise I have a feeling that A is supposed to be an Identity matrix? I messed around with the program and it always worked after I left A as given above; no matter what B was. I think A is always supposed to be an identity matrix....that is if I understood what maths is fun was going on about.

EDIT - So as this post was scheduled I made this edit 10 mins after moving onto exercise 6 when I realised that my randomMatrix function was complete garbage lol. A does not need to be an identity matrix.

Friday, 10 June 2022

Chapter 24 // Exercise 4 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 4

Get the Gaussian elimination program to work; that is, complete it, get to compile, and test it with a simple program.


First I had to google what in the hell is a gaussian elimination. That didn't help. So I started writing out the code from the book... that didn't really help either.

The code compiled but when running the program, it always errored in the classical elimination bit as the pivot was always 0 on the second round of the for loop.

I guess that was the point though? I think it's always supposed to fail but I honestly have no idea. Anyway, I completed the code, got it to compile and tested it with a simple program so, exercise done I guess??

EDIT - I completed this post, scheduled it then did exercise 5. When starting exercise 6 I realised my randomMatrix generator for a 2d array was complete garbage and that's why it always crashed lol.


Thursday, 9 June 2022

Chapter 24 // Exercise 3 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 3

Expert level only (this cannot be done with the facilities described in this book): Write an apply(f, a) that can take a void(T&), a T(const T&), and their function object equivalents. Hint: Boost::bind.


I was determined to complete this exercise...I mean he basically challenged me by saying it's "Expert level only".

I bashed my head against the wall for many hours. I knew it had something to do with the return type of the function and checking for void. Eventually I posted in our works discord and template wizard Keith came to my rescue. He first suggested to ignore the bind hint and take a look at std::for_each instead.

This helped however I was still having trouble determining if the incoming function at runtime returned void or not. He then hinted at std::result_of. That is deprecated now but I managed to piece together bits from this post on how to use invoke_result:

I got this working for the T(const T&) but it would not compile for void(T&). He then told me to add constexpr to the if (function return type is void), as that would prevent the compiler from doing a compile time branch.....it WORKED.

Getting this small function to work was one hell of a high.




Wednesday, 8 June 2022

Chapter 24 // Exercise 2 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 2

Do exercise 1 again, but with function objects, rather than functions. Hint: Matrix.h contains examples.


So in the header there's already a function object called Mul_assign that you can call with apply like this:
m.apply(Mul_assign<int>(), 3) and that will triple all the elements.

Tuesday, 7 June 2022

Chapter 24 // Exercise 1 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Exercise 1

The function arguments f for a.apply(f) and apply(f,a) are different. Write a triple() function for each and use each to triple the elements of an array { 1 2 3 4 5 }. Define a single triple() function that can be used for both a.apply(triple) and apply(triple, a). Explain why it could be a bad idea to write every function to be used by apply() that way.


I read this exercise and immediately thought "what the fuck?"

After re-reading section 24.5.2 I realised that apply() basically takes in a pointer to a function and then calls that function on each element in the container. So after some messing around the difference is that a.apply() modifies the elements, apply returns a copy. 

Therefore the single triple function needs to both modify the argument and return a value. This is a bad idea as you don't always want function modifying your containers. Giving users the option is always better.




Monday, 6 June 2022

Chapter 24 // Drill 8 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Drill 8

Read six ints into a Matrix<int,2> m(2,3) and print them out.


.

Sunday, 5 June 2022

Chapter 24 // Drill 7 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Drill 7

Read ten complex<double>s from cin (yes, cin supports >>  for complex) and put them into a Matrix. Calculate and output the sum of the ten complex numbers.


Complex does have built in I/O support which is nice. Figuring out how to use cin was annoying though. I eventually discovered it here:

You need to input it as (num,num). 

Saturday, 4 June 2022

Chapter 24 // Drill 6 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Drill 6

Compute a multiplication table for [0,n) * [0, m) and represent it as a 2D Matrix. Take n and from cin and print out the table nicely (assume that m is small enough that the results fit on a line).


.

Friday, 3 June 2022

Chapter 24 // Drill 5 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Drill 5

Read ten floating-point values from input and put them into a Matrix<double>. Matrix has no push_back() so be careful to handle an attempt to enter a wrong number of doubles. Print out the Matrix.


The accompanying MatixIO.h file provides very simple I/O for 1D and 2D matrices. So
Matrix<double> a(4);
cin >> a;
cout << a;

Will read 4 whitespace-seperate doubles delimited by curly braces. For example with a 1D matrix:
{ 1.2 3.4 5.6 7.8 }

These functions will handle reading in the correct amount of numbers and throw errors if the structure isn't exact.

I also added my own method for fun.

Thursday, 2 June 2022

Chapter 24 // Drill 4 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Drill 4

Write a program that takes ints from cin and outputs the sqrt() of each int, or "no square root" if sqrt(x) is illegal for some x (i.e., check your sqrt() return values).


So the std::sqrt function is explained here:

I didn't realise it returned floats, doubles or long doubles. It returns some error handles if something goes wrong defined here:


Wednesday, 1 June 2022

Chapter 24 // Drills 1, 2, 3 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 24 // Drill 1

Print the size of a char, a short, an int, a long, a float, a double, an int*, and a double* (use sizeof, not <limits>).

Chapter 24 // Drill 2

Print out the size as reported by sizeof of Matrix<int> a(10), Matrix<int> b(100), Matrix<double> c(10), Matrix<int, 2> d(10,10), Matrix<int, 3> e(10,10,10).

Chapter 24 // Drill 3

Print out the number of elements of each of the Matrixes from 2.


Dear god, reading this chapter almost sent me to sleep several times...there's just something about matrices that bores the shit out of me.

Matrix.h is a file made up by Bjarne. You can find a copy of it in here:
or here:

The ones with 11 on them I think are for the second edition of the book??




Tuesday, 31 May 2022

[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

So after part 1, I had the bare bones of a slenderman game. In this part I wanted to flesh out the mechanics a little more and make it start to look more like a "game". My Goals for part 2 were:
  1. Replace the cubes with actual "notes"
  2. Create random spawn points for the notes
  3. Create a sprint mechanic + realistic jump
  4. Add sprint and notes to HUD widget
  5. Change it to night time
  6. Create a flashlight
  7. Create a battery mechanic
  8. Executable
1. Replace the cubes with actual "notes"
2. Create random spawn points for the notes
For this I opened up blender and made the shittest piece of paper. Took about 1 minute. Made sure to resize the plane to A4, curled the edges slightly and gave it a material slot for the front and back and then exported it to Unreal.

[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

I downloaded the note textures used in one of the slenderman games off google images and created materials from them. Then created a way for the notes to pick one of the materials at runtime. There are 8 different textures and each note is unique:

[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

I created a new blueprint which now handles the spawning of the notes and what material they get. This blueprint contains 16 locations where the notes could spawn. More can be added but only 8 locations will be picked at runtime. You can change the number of locations in the details panel in the editor.

[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

3. Create a sprint mechanic and realistic jump
Default unreal man jumps like Princess Peach; in fact it's more floating than jumping and greatly annoys me. Fixing it is quite simple though by just changing the Z Jump Velocity in the Character Movement.

The sprint mechanic is also relatively simple. When shift is held, it reduces the sprint each second and when it reaches 0 (from 100), you can no longer sprint. It takes 10 seconds to replenish fully. I achieved this by using timers instead of ticking. That way, we're not constantly checking to see if we're sprinting (or replenishing sprint value) every frame; only when we need to.

[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

4. Add sprint and notes collected to the HUD widget
Using icons from the Android library (they're free to use) I added a progress bar and text to the HUD:

[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

The progress bar does use a binding to update itself which is expensive but barely anything is ticking in this game so I didn't really care. In UE5, the progress bars now come with a default animation as well which is snazzy. The notes text is updated when a note is destroyed and the blueprint sends a message to the HUD.

5. Change to night time
This was one of the most difficult parts as lighting in Unreal Engine is unbelievably difficult. You need to change colours determined by sun, override sky colours, change the post process volume and exponential height fog....it's never ending. Also, as the scene is so dark afterwards; I duplicated BP_Sky_Sphere so I could add a tick box which would allow me to switch between day and night in real time.

In the construction script I added this mess:
[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

Which toggles between "soft day" and night:

[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

6. Adding a flashlight
For this I simply add a spot light to the character and attached it to the head socket so it moves with the character. I thought about a doing a torch you hold in your hand but couldn't be bothered with the hand animations as this is true first person so instead, the player is wearing a head torch. I added some nodes to allow the player to toggle the flashlight on and off with F.

[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

The flashlight is its own blueprint and spawns on the player as a child component. I gave it a light profile as well using one of the default UE ones so it's softer when far away from objects; but then the cone shape starts to appear when you get closer. It always annoys me in games when the flashlight is just a circle in the centre of the screen.

7. Adding a battery mechanic
This didn't take long as it was almost copy and paste on the sprint mechanic. I added some timers to the flashlight so when it's in use it begins to lose power and it updates the HUD with the new power level. I added a cylinder to game which acts as a "battery". When you pick it up it replenishes the battery power; regardless of how much power you have left. So batteries should be used wisely as you can't store them in an inventory.

8. Executable
In the gif, "slenderman" is motionless as I disabled it's "AI" for the moment whilst testing (and I forgot to remove the debug output from sprinting) but it's starting to look more like a spooky game now!

[Dev Log] Generic Slenderman Clone Part 2 // UE5 & Blueprint

In part 3, I'll actually create the forest map, add sounds like footsteps, cracking twigs and some story elements. By the end of part 3 it will look like a proper slenderman game but it still won't act like one.

Monday, 30 May 2022

Chapter 23 // Exercises 15 , 16- Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 23 // Exercise 15

Describe a pattern that cannot be expressed as a regular expression.

HTML.

Chapter 23 // Exercise 16

For experts only: Prove that the pattern found in the previous exercise really isn't a regular expression.

Sunday, 29 May 2022

Chapter 23 // Exercise 14 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 23 // Exercise 14

Write a program that, like the one in section 23.8.7, can be used to experiment with pattern matching by typing in a pattern. However, have it read a file into memory (representing a line break with the new line character, '\n'), so that you can experiment with patterns spanning line breaks. Test it and document a dozen test patterns.


So I was confused with this one. I'm not sure if he meant, "create a new file with newlines replaced by \n" or "have a file with newlines in it". In the first case, the newline will need to be put as '\\n' in the regex pattern otherwise it will just match to the characters \ n, so the slash needs escaping. But in the second you can just have it as \n and it will continue searching the next line for the pattern.

With this in mind I decided to do both. Interestingly I discovered that if you type out a regex pattern at compile time, it will add the escape to the slash. Whereas if you type it in the console at runtime, it won't.

Saturday, 28 May 2022

Chapter 23 // Exercise 13 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2019 and a modified version of the std_lib_facilities header found here.

Chapter 23 // Exercise 13

Does dot (.) match '\n'? Write a program to find out.


Using regex101.com, it shouldn't match. (.) and '\n' are completely seperate. I used regex_replace to also show how they don't match. 

A part of me though feels like this is trick question. Maybe it's not, it's one of those seemingly simple things designed to catch you out....or maybe I'm just overthinking.