#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
using namespace std; 

string insertCommas(long value){
	string s = to_string(value);
	int n = s.length() - 3;
	int end = (value >= 0) ? 0 : 1; // support for negative numbers
	while (n > 0) {
		s.insert(n, ","); // insert the comma into the string at position n
		n -= 3; //go to the left 3 places
	}
	return s;
}

int main() {
	/* 
	The Apollo program cost the US federal government $25.8 billion from 1960 to 1973, 
	which is equivalent to about $318 billion in 2023 dollars.
	*/

	double dollarThickness = 0.10922; // .0043in in mm
	unsigned long km_to_moon = 384400; //roughly
	unsigned long km_to_mm = 1000000;  // 1000^2

	/*
	Multiplying two unsigned int values in C++ and storing the result in an unsigned long 
	can still cause an intermediate overflow during the multiplication if unsigned int and 
	the temporary calculation are evaluated at 32 bits before being converted/promoted.

	unsigned int is 32 bits and its product exceeds std::numeric_limits<unsigned int>::max(), 
	the multiplication overflows and wraps around modulo 2^32 first.

	KEY TAKEAWAYS:
	Promotion happens AFTER the multiplication.

	If you wanted to multiply two unsigned ints and you believe that the result could overflow,
	you can do this:
	
	unsigned long result = static_cast<unsigned long>(a) * static_cast<unsigned long>(b);
	*/
	unsigned long mm_to_moon = km_to_mm * km_to_moon;

	cout << "km to the moon: " << km_to_moon << endl;
	cout << "km to mm: " << km_to_mm << endl;
	cout << "mm to the moon: " << mm_to_moon << endl;
	double x = ceil(mm_to_moon / dollarThickness);
	cout << "dollars to the moon: " << setprecision(0) << fixed << "\t\t" << x << endl;
	unsigned long y = x;
	cout << "Unformatted result (long): " << "\t" << y << endl;
	cout << insertCommas(y) << " Dollars piled to the moon!\n";
	return 0;
}
