//Hidden Lines work #include #include #include #include #include #include #include #include #include "HiddenLines.h" HL::HL() { //Read from CSV and construct the problem from the given lines lines = construct_HWprob(); } std::map HL::get_map() { return line_holder; } void HL::print_sol() { auto sol = get_sol(); for(auto itr = sol.begin(); itr != sol.end(); itr++){ double start_range = std::get<0>(std::get<1>(*itr)); std::string start_print = std::to_string(start_range); if(start_range == std::numeric_limits::lowest()) start_print = "-inf"; double stop_range = std::get<1>(std::get<1>(*itr)); std::string stop_print = std::to_string(stop_range); if(stop_range == std::numeric_limits::max()) stop_print = "inf"; std::cout << "Line ID " << std::get<0>(*itr) << " visible from x=" << start_print << " to x=" << stop_print << std::endl; } } //Divide and Conquer Strategy using recursive call to divide ls and merge using merge() std::vector HL::gen_sol(std::vector& ls){ HL inst = *this; auto line_holder = inst.get_map(); if (ls.size() > 2){ //Create left and right half sets int split = ceil(ls.size()/2); std::vector lh; std::vector rh; //No index access for sets auto end_itr = ls.begin(); std::advance(end_itr, split); for(auto itr = ls.begin(); itr != end_itr; itr++){ lh.push_back(*itr); } for(auto itr = end_itr; itr != ls.end(); itr++){ rh.push_back(*itr); } std::cout << "Left half is size " << lh.size() << " and right half is size " << rh.size() << std::endl; //Recursive call auto merged = merge(inst.gen_sol(lh), inst.gen_sol(rh)); for (auto itr = merged.begin(); itr != merged.end(); itr++){ Line l1 = *itr; sol.push_back(std::make_pair(l1.get_id(), std::make_pair(l1.get_vis_start(), l1.get_vis_end()))); } //Cleanup Solution /* std::set>> new_sol; for(std::set>>::iterator itr = sol.begin(); itr != sol.end(); itr++){ auto start_range = std::get<0>(std::get<1>(*itr)); auto stop_range = std::get<1>(std::get<1>(*itr)); double my_slope = std::get<1>(*line_holder.find(std::get<0>(*itr))).get_slope(); int my_id = std::get<0>(*itr); if(start_range == stop_range) continue; //Handle overlaps std::set>>::iterator it = std::find_if(sol.begin(), sol.end(), [start_range, my_id](const std::pair>& p ) { return (std::get<0>(std::get<1>(p)) == start_range && std::get<0>(p) != my_id); }); if (it != sol.end()){ double stored_stop = std::get<1>(std::get<1>(*it)); double stored_slope = std::get<1>(*line_holder.find(std::get<0>(*it))).get_slope(); int stored_id = std::get<0>(*it); std::cout << "Matched" << std::endl; //Change lines' vis starts and ends if (my_slope < stored_slope){ std::get<1>(*line_holder.find(std::get<0>(*itr))).set_vis_start(start_range); std::get<1>(*line_holder.find(std::get<0>(*itr))).set_vis_end(stored_stop); new_sol.insert(std::make_pair(my_id, std::make_pair(start_range, stored_stop))); std::get<1>(*line_holder.find(std::get<0>(*it))).set_vis_start(stored_stop); std::get<1>(*line_holder.find(std::get<0>(*it))).set_vis_end(stop_range); new_sol.insert(std::make_pair(stored_id, std::make_pair(stored_stop, stop_range))); } else{ std::get<1>(*line_holder.find(std::get<0>(*it))).set_vis_start(start_range); std::get<1>(*line_holder.find(std::get<0>(*it))).set_vis_end(stored_stop); new_sol.insert(std::make_pair(stored_id, std::make_pair(start_range, stored_stop))); std::get<1>(*line_holder.find(std::get<0>(*itr))).set_vis_start(stored_stop); std::get<1>(*line_holder.find(std::get<0>(*itr))).set_vis_end(stop_range); new_sol.insert(std::make_pair(my_id, std::make_pair(stored_stop, stop_range))); } } else{ new_sol.insert(*itr); } } inst.set_sol(new_sol); */ return merged; } //Set with 2 lines is a base case: both are visible at +-inf respectively, and intersection is where they change //visibility else if (ls.size() == 2){ Line l1 = *(ls.begin()); Line l2 = *(ls.end()); double isec = (l2.get_ycept() - l1.get_ycept())/(l1.get_slope() - l2.get_slope()); if (l1.get_slope() < l2.get_slope()){ l1.set_vis_end(isec); l2.set_vis_start(isec); } else{ l2.set_vis_end(isec); l1.set_vis_start(isec); } //Insert partial solutions sol.push_back(std::make_pair(l1.get_id(), std::make_pair(l1.get_vis_start(), l1.get_vis_end()))); sol.push_back(std::make_pair(l2.get_id(), std::make_pair(l2.get_vis_start(), l2.get_vis_end()))); return ls; } //Set with 1 line: Just return else{ return ls; } } std::vector HL::construct_HWprob(){ //Set to hold all our Lines std::set sorted_lines; std::vector lines; //Hold our doubles from each line std::vector tmp_data; std::ifstream data("../data/data.csv"); if(data.is_open()){ std::string csvline; //Throw header row away std::getline(data, csvline); while(std::getline(data, csvline, ',')){ if(!csvline.empty()){ tmp_data.emplace_back(std::stod(csvline)); } } } //Close file data.close(); while(!tmp_data.empty()){ double slope = *tmp_data.begin(); tmp_data.erase(tmp_data.begin()); if(tmp_data.empty()){ std::cout << "Error in CSV file: Number of slope entries does not match the number of y-intercept entries. "; std::cout << "Please correct the CSV file and try again." << std::endl; exit(-1); } double ycept = *tmp_data.begin(); tmp_data.erase(tmp_data.begin()); Line newline = Line(slope, ycept); newline.set_id(); sorted_lines.insert(newline); lines.push_back(newline); auto line_holder = get_map(); //line_holder[newline.get_id()] = newline; line_holder.insert(std::pair (newline.get_id(), newline)); } //Set most neg slope to start range of -inf, and most pos to stop of inf Line lend = *lines.end(); Line lbegin = *lines.begin(); lend.set_vis_end(std::numeric_limits::max()); lbegin.set_vis_start(std::numeric_limits::lowest()); std::string lend_stop = std::to_string(lend.get_vis_end()); std::string lbegin_start = std::to_string(lbegin.get_vis_start()); if(lend.get_vis_end() == std::numeric_limits::max()) lend_stop = "inf"; if(lbegin.get_vis_start() == std::numeric_limits::lowest()) lbegin_start = "-inf"; std::cout << "---------------Sorted Lines by slope:---------------" << std::endl; for(Line line : sorted_lines) { std::cout << "Line " << line.get_id() << " has slope " << line.get_slope() << " and a y-intercept of " << line.get_ycept() << std::endl; std::cout << "Line " << line.get_id() << " visible from x=" << line.get_vis_start() << " to x=" <