You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AoC2022_Day16/main.cpp

249 lines
9.1 KiB

#include <vector>
#include <string>
#include <map>
#include <iostream>
#include <math.h>
#include <fstream>
struct Room{
std::vector<std::string>connections;
std::map<std::string,int>paths;
int flowValue=0;
std::string name="";
friend std::ostream&operator<<(std::ostream&out,Room&rhs){
out<<"Valve "<<rhs.name<<": Flow Rate - "<<rhs.flowValue<<" (Connects to: ";
for (int i=0;i<rhs.connections.size();i++){
std::string conn=rhs.connections[i];
if (i!=0){
out<<",";
}
out<<conn;
}
out<<")";
return out;
}
};
std::map<std::string,Room>rooms;
std::vector<std::string>targetRooms;
int maxFlow=0;
int iterations=0;
int branchesRemaining=0;
void printArr(){
int minutesRemaining1=26;
int minutesRemaining2=26;
std::string currentPos="AA";
std::string path1="AA";
std::string currentPos2="AA";
std::string path2="AA";
std::vector<std::string> movePlan1;
std::vector<std::string> movePlan2;
int moveAmt1=0; //How many steps left to move.
int moveAmt2=0; //How many steps left to move.
int currentMarker1=0;
int currentMarker2=0;
int flowRate=0;
int flowTotal=0;
for (int i=0;i<targetRooms.size();i++){
std::string valve=targetRooms[i];
if (i&1){
movePlan2.push_back(valve);
} else {
movePlan1.push_back(valve);
}
//std::cout<<a[i]<<" ";
}
moveAmt1=rooms[currentPos].paths[movePlan1[currentMarker1]];
moveAmt2=rooms[currentPos2].paths[movePlan2[currentMarker2]];
std::cout<<"Current Position 1:"<<currentPos<<std::endl;
std::cout<<"Current Position 2:"<<currentPos2<<std::endl;
std::cout<<" Flow Total:"<<flowTotal<<std::endl;
for (int i=0;i<26;i++){
std::cout<<"Minute "<<i+1<<std::endl;
flowTotal+=flowRate;
std::cout<<" Flow: "<<flowTotal<<std::endl;
std::cout<<" Flow Rate: "<<flowRate<<std::endl;
if (moveAmt1>0){
std::cout<<" Moving to "<<movePlan1[currentMarker1]<<" in "<<moveAmt1<<" steps"<<std::endl;
} else {
if (moveAmt1==0){
//We open the valve. Then move to the next one.
currentPos=movePlan1[currentMarker1];
path1+="->"+currentPos;
std::cout<<" Path1: "<<path1<<std::endl;
flowRate+=rooms[movePlan1[currentMarker1++]].flowValue;
//flowTotal+=rooms[movePlan1[currentMarker1++]].flowValue;
std::cout<<" Flow rate is now "<<flowRate<<std::endl;
if (currentMarker1<movePlan1.size()){
moveAmt1=rooms[currentPos].paths[movePlan1[currentMarker1]]+1;
std::cout<<" Reached destination. Next: "<<movePlan1[currentMarker1]<<" in "<<moveAmt1<<" steps"<<std::endl;
}
}
}
if (moveAmt2>0){
std::cout<<" Moving to "<<movePlan2[currentMarker2]<<" in "<<moveAmt2<<" steps"<<std::endl;
} else {
if (moveAmt2==0){
//We open the valve. Then move to the next one.
currentPos2=movePlan2[currentMarker2];
path2+="->"+currentPos2;
std::cout<<" Path2: "<<path2<<std::endl;
flowRate+=rooms[movePlan2[currentMarker2++]].flowValue;
//flowTotal+=rooms[movePlan2[currentMarker2++]].flowValue;
std::cout<<" Flow rate is now "<<flowRate<<std::endl;
if (currentMarker2<movePlan2.size()){
moveAmt2=rooms[currentPos2].paths[movePlan2[currentMarker2]]+1;
std::cout<<" Reached destination. Next: "<<movePlan2[currentMarker2]<<" in "<<moveAmt2<<" steps"<<std::endl;
}
}
}
moveAmt1--;
moveAmt2--;
}
std::cout<<"Final Flow Total: "<<flowTotal<<std::endl;
if (flowTotal>maxFlow){
maxFlow=flowTotal;
std::cout<<"New max flow is "<<maxFlow<<std::endl;
}
}
void printArr2(std::vector<std::string> arr){
for (int i=0;i<arr.size();i++){
if (i!=0){
std::cout<<" ";
}
std::cout<<arr[i];
}
std::cout<<std::endl;
}
void permutation(std::vector<std::string>&arr,int size){
if (size==1){
printArr();
return;
}
for (int i=0;i<size;i++){
permutation(arr,size-1);
if (i<size-1){
if (size%2==1){
std::swap(arr[0],arr[size-1]);
} else {
std::swap(arr[i],arr[size-1]);
}
}
}
}
int findRoute(std::string start,std::string end,std::map<std::string,bool>visited,int dist){
visited[start]=true;
int distance=INFINITY;
Room r=rooms[start];
for (int i=0;i<r.connections.size();i++){
if (r.connections[i]==end){
return dist+1;
}
}
for (int i=0;i<r.connections.size();i++){
if (visited.find(r.connections[i])==visited.end()){
int result=findRoute(r.connections[i],end,visited,dist+1);
if (result<distance){
distance=result;
}
}
}
return distance;
}
void explore(std::string currentRoom,std::map<std::string,bool>visitedvalves,int flowRate,int minute,int flowTotal,std::string journey,std::string flowTotals){
//std::cout<<"Exploring "<<currentRoom<<" Time Passed: "<<minute<<". Flow Rate: "<<flowRate<<", Flow Total: "<<flowTotal<<" Journey: "<<journey<<" Totals:"<<flowTotals<<std::endl;
visitedvalves[currentRoom]=true;
int previousFlowTotal=flowTotal;
std::string prevFlowTotal=flowTotals;
for (int i=minute;i<30;i++){
flowTotal+=flowRate;
flowTotals+="->"+std::to_string(flowTotal);
}
if (flowTotal>maxFlow){
maxFlow=flowTotal;
std::cout<<"New max found: "<<maxFlow<<std::endl;
}
//std::cout<<" Maxed Out: "<<currentRoom<<" Time Passed: "<<minute<<". Flow Rate: "<<flowRate<<", Flow Total: "<<flowTotal<<" Journey: "<<journey<<" Totals:"<<flowTotals<<std::endl;
flowTotals=prevFlowTotal;
flowTotal=previousFlowTotal;
for (std::map<std::string,Room>::iterator it=rooms.begin();it!=rooms.end();++it){
if (visitedvalves.find(it->first)==visitedvalves.end()&&rooms[it->first].flowValue>0){
//We haven't tried going here yet.
if (minute+rooms[currentRoom].paths[it->first]<30){
for (int i=0;i<rooms[currentRoom].paths[it->first];i++){
flowTotal+=flowRate;
flowTotals+="->"+std::to_string(flowTotal);
}
explore(it->first,visitedvalves,flowRate,minute+rooms[currentRoom].paths[it->first],flowTotal,journey+"->"+it->first,flowTotals);
flowTotal+=flowRate;
flowTotals+="->"+std::to_string(flowTotal);
explore(it->first,visitedvalves,flowRate+rooms[it->first].flowValue,minute+rooms[currentRoom].paths[it->first]+1,flowTotal,journey+"->"+it->first,flowTotals);
flowTotal=previousFlowTotal;
flowTotals=prevFlowTotal;
}
}
}
}
int main()
{
std::ifstream file("input");
while (file.good()){
std::string line;
std::getline(file,line);
std::cout<<line<<std::endl;
if (line.length()>0){
int flowRate=std::atoi(line.substr(line.find('=')+1,line.find(';')-line.find('=')-1).c_str());
std::cout<<"Flow Rate: "<<flowRate<<std::endl;
std::string valveName=line.substr(line.find(' ')+1,2);
std::cout<<"Valve "<<valveName<<std::endl;
int marker=line.find(',');
Room newRoom;
newRoom.name=valveName;
newRoom.flowValue=flowRate;
if (flowRate>0){
targetRooms.push_back(valveName);
}
while (marker!=std::string::npos){
std::string roomName=line.substr(marker-2,2);
std::cout<<"Connection w/"<<roomName<<" found"<<std::endl;
marker=line.find(',',marker+1);
newRoom.connections.push_back(roomName);
}
std::string roomName=line.substr(line.size()-2,2);
std::cout<<"Connection w/"<<roomName<<" found"<<std::endl;
newRoom.connections.push_back(roomName);
rooms[valveName]=newRoom;
std::cout<<rooms[valveName]<<std::endl;
}
}
std::cout<<"Preparing distance cache..."<<std::endl;
for (std::map<std::string,Room>::iterator it=rooms.begin();it!=rooms.end();++it){
for (std::map<std::string,Room>::iterator it2=rooms.begin();it2!=rooms.end();++it2){
if (it->first==it2->first){
rooms[it->first].paths[it2->first]=0;
//std::cout<<it->first<<"->"<<it2->first<<": 0"<<std::endl;
} else {
rooms[it->first].paths[it2->first]=findRoute(it->first,it2->first,{},0);
//std::cout<<it->first<<"->"<<it2->first<<": "<<rooms[it->first].paths[it2->first]<<std::endl;
}
}
}
permutation(targetRooms,targetRooms.size());
return 0;
}