// ZipExample.cpp : Rangarajan Krishnamoorthy, Nov 12, 2026
//
#include <vector>
#include <string>
#include <ranges>
#include <tuple>
#include <iostream>
#include <print>
#include <list>
#include <set>

void example1()
{
	std::vector<std::string> cities{"Houston", "Chennai", "New York", "Berlin"};
	std::vector<float> population{2.4, 7, 8.6, 3.7 }; // In millions (approx)

	for(auto [city, population] : std::views::zip(cities, population))
		std::println("{} -> {}", city, population);
}

void example2()
{
	std::list<int> a{ 10, 20, 30, 40 }; // 4 elements
	std::set<float> b{ 1.25, 2.5, 3.75 }; // 3 elements
	std::vector<char> c{ 'a', 'b', 'c', 'd', 'e' }; // 5 elements

	for(auto [x, y, z] : std::views::zip(a, b, c))
		std::println("{}, {}, {}", x, y, z);
}

void example3()
{
	std::vector<int> elems1{ 100, 200 };
	std::vector<int> elems2{ 99, 999 };

	auto zipview = std::views::zip(elems1, elems2);

	// Is the type a 'reference'?
	std::cout << std::boolalpha << std::same_as<std::ranges::range_reference_t<decltype(zipview)>, 
																	std::tuple<int&, int&>> << "\n";

	// Change the values via zipview
	for (auto [x, y] : zipview) {
		x += 5; y -= 4;
	}

	// Print the values of zipview
	std::cout << "\nZipview values\n";
	for (auto [x, y] : zipview) {
		std::cout << x << ", " << y << std::endl;
	}

	// Print the original vectors
	std::cout << "\nOriginal vectors\n";
	for (int i = 0; i < elems1.size(); ++i) {
		std::cout << elems1[i] << ", " << elems2[i] << std::endl;
	}
}

void example4()
{
	std::array qty{ 23, 35, 60 };
	std::array cost{ 100, 50 }; // Third element missing

	// Uses only the first two elements
	auto totals = std::views::zip_transform([](int q, int c) {return q * c;}, qty, cost);

	for (auto t : totals)
		std::println("{}", t);
}

int main()
{
	//example1();
	//example2();
	//example3();
	example4();
	return 0;
}