|
|
@ -26,6 +26,14 @@ void wait(int pauseMs=0){ |
|
|
|
const int DAY = 10; |
|
|
|
const int DAY = 10; |
|
|
|
Run runInput=FILE2; |
|
|
|
Run runInput=FILE2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum Direction{ |
|
|
|
|
|
|
|
UP, |
|
|
|
|
|
|
|
RIGHT, |
|
|
|
|
|
|
|
DOWN, |
|
|
|
|
|
|
|
LEFT, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct Pipe{ |
|
|
|
struct Pipe{ |
|
|
|
bool down=false; |
|
|
|
bool down=false; |
|
|
|
bool up=false; |
|
|
|
bool up=false; |
|
|
@ -33,20 +41,214 @@ struct Pipe{ |
|
|
|
bool right=false; |
|
|
|
bool right=false; |
|
|
|
char originalChar; |
|
|
|
char originalChar; |
|
|
|
bool traversed=false; |
|
|
|
bool traversed=false; |
|
|
|
int distance=0; |
|
|
|
bool partOfLoop=false; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::vector<Pipe>>pipes; |
|
|
|
std::vector<std::vector<Pipe>>tiles; |
|
|
|
|
|
|
|
|
|
|
|
vi2d startingPipe; |
|
|
|
vi2d startingPipe; |
|
|
|
|
|
|
|
|
|
|
|
std::optional<Pipe*>GetPipe(vi2d coords){ |
|
|
|
std::optional<Pipe*>GetPipe(vi2d coords){ |
|
|
|
if(coords.x<0||coords.y<0||coords.y>=pipes.size()||coords.x>=pipes[coords.y].size())return {}; |
|
|
|
if(coords.x<0||coords.y<0||coords.y>=tiles.size()||coords.x>=tiles[coords.y].size())return {}; |
|
|
|
return &pipes[coords.y][coords.x]; |
|
|
|
return &tiles[coords.y][coords.x]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<vi2d>tilesRemaining; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MarkAndMove(vi2d&pos,Direction dir){ |
|
|
|
|
|
|
|
tiles[pos.y][pos.x].partOfLoop=true; |
|
|
|
|
|
|
|
tiles[pos.y][pos.x].traversed=true; |
|
|
|
|
|
|
|
switch(dir){ |
|
|
|
|
|
|
|
case UP:{ |
|
|
|
|
|
|
|
pos.y-=1; |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case RIGHT:{ |
|
|
|
|
|
|
|
pos.x+=1; |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case DOWN:{ |
|
|
|
|
|
|
|
pos.y+=1; |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case LEFT:{ |
|
|
|
|
|
|
|
pos.x-=1; |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
default:throw; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::vector<vi2d>pipesRemaining; |
|
|
|
void AddPipe(std::string row1,std::string row2,std::string row3,std::vector<Pipe>&upper,std::vector<Pipe>&middle,std::vector<Pipe>&lower){ |
|
|
|
|
|
|
|
auto ParseCharacter=[&](char c,std::vector<Pipe>&row){ |
|
|
|
|
|
|
|
switch(c){ |
|
|
|
|
|
|
|
case '.':{ |
|
|
|
|
|
|
|
row.push_back(Pipe{.originalChar=c}); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case '-':{ |
|
|
|
|
|
|
|
row.push_back(Pipe{.left=true,.right=true,.originalChar=c}); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case '|':{ |
|
|
|
|
|
|
|
row.push_back(Pipe{.down=true,.up=true,.originalChar=c}); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case '7':{ |
|
|
|
|
|
|
|
row.push_back(Pipe{.down=true,.left=true,.originalChar=c}); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case 'F':{ |
|
|
|
|
|
|
|
row.push_back(Pipe{.down=true,.right=true,.originalChar=c}); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case 'L':{ |
|
|
|
|
|
|
|
row.push_back(Pipe{.up=true,.right=true,.originalChar=c}); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case 'J':{ |
|
|
|
|
|
|
|
row.push_back(Pipe{.up=true,.left=true,.originalChar=c}); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
for(char&c:row1){ |
|
|
|
|
|
|
|
ParseCharacter(c,upper); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for(char&c:row2){ |
|
|
|
|
|
|
|
ParseCharacter(c,middle); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for(char&c:row3){ |
|
|
|
|
|
|
|
ParseCharacter(c,lower); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void doStuff2(){ |
|
|
|
|
|
|
|
while(true){ //lines is accessible as a global.
|
|
|
|
|
|
|
|
for(std::string&line:lines){ |
|
|
|
|
|
|
|
std::vector<Pipe>upperRow; |
|
|
|
|
|
|
|
std::vector<Pipe>middleRow; |
|
|
|
|
|
|
|
std::vector<Pipe>lowerRow; |
|
|
|
|
|
|
|
for(int i=0;i<line.length();i++){ |
|
|
|
|
|
|
|
switch(line[i]){ |
|
|
|
|
|
|
|
case '|':{ |
|
|
|
|
|
|
|
AddPipe( |
|
|
|
|
|
|
|
".|.", |
|
|
|
|
|
|
|
".|.", |
|
|
|
|
|
|
|
".|.",upperRow,middleRow,lowerRow); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case '-':{ |
|
|
|
|
|
|
|
AddPipe( |
|
|
|
|
|
|
|
"...", |
|
|
|
|
|
|
|
"---", |
|
|
|
|
|
|
|
"...",upperRow,middleRow,lowerRow); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case 'L':{ |
|
|
|
|
|
|
|
AddPipe( |
|
|
|
|
|
|
|
".L.", |
|
|
|
|
|
|
|
".LL", |
|
|
|
|
|
|
|
"...",upperRow,middleRow,lowerRow); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case 'J':{ |
|
|
|
|
|
|
|
AddPipe( |
|
|
|
|
|
|
|
".J.", |
|
|
|
|
|
|
|
"JJ.", |
|
|
|
|
|
|
|
"...",upperRow,middleRow,lowerRow); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case '7':{ |
|
|
|
|
|
|
|
AddPipe( |
|
|
|
|
|
|
|
"...", |
|
|
|
|
|
|
|
"77.", |
|
|
|
|
|
|
|
".7.",upperRow,middleRow,lowerRow); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case 'F':{ |
|
|
|
|
|
|
|
AddPipe( |
|
|
|
|
|
|
|
"...", |
|
|
|
|
|
|
|
".FF", |
|
|
|
|
|
|
|
".F.",upperRow,middleRow,lowerRow); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case '.':{ |
|
|
|
|
|
|
|
for(int j=0;j<3;j++)upperRow.push_back({.originalChar=line[i]}); |
|
|
|
|
|
|
|
for(int j=0;j<3;j++)middleRow.push_back({.originalChar=line[i]}); |
|
|
|
|
|
|
|
for(int j=0;j<3;j++)lowerRow.push_back({.originalChar=line[i]}); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
case 'S':{ |
|
|
|
|
|
|
|
startingPipe={int(upperRow.size()),int(tiles.size())}; |
|
|
|
|
|
|
|
for(int j=0;j<3;j++)upperRow.push_back({.originalChar=line[i]}); |
|
|
|
|
|
|
|
for(int j=0;j<3;j++)middleRow.push_back({.originalChar=line[i]}); |
|
|
|
|
|
|
|
for(int j=0;j<3;j++)lowerRow.push_back({.originalChar=line[i]}); |
|
|
|
|
|
|
|
}break; |
|
|
|
|
|
|
|
default:{ |
|
|
|
|
|
|
|
throw; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
tiles.push_back(upperRow); |
|
|
|
|
|
|
|
tiles.push_back(middleRow); |
|
|
|
|
|
|
|
tiles.push_back(lowerRow); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//tilesRemaining.push_back(startingPipe);
|
|
|
|
|
|
|
|
auto initialPipe=GetPipe(startingPipe); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto bottomPipe=GetPipe(startingPipe+vi2d{0,3}+vi2d{1,1}); |
|
|
|
|
|
|
|
if(bottomPipe&&bottomPipe.value()->up)initialPipe.value()->down=true; |
|
|
|
|
|
|
|
auto topPipe=GetPipe(startingPipe+vi2d{0,-3}+vi2d{1,1}); |
|
|
|
|
|
|
|
if(topPipe&&topPipe.value()->down)initialPipe.value()->up=true; |
|
|
|
|
|
|
|
auto leftPipe=GetPipe(startingPipe+vi2d{-3,0}+vi2d{1,1}); |
|
|
|
|
|
|
|
if(leftPipe&&leftPipe.value()->right)initialPipe.value()->left=true; |
|
|
|
|
|
|
|
auto rightPipe=GetPipe(startingPipe+vi2d{3,0}+vi2d{1,1}); |
|
|
|
|
|
|
|
if(rightPipe&&rightPipe.value()->left)initialPipe.value()->right=true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(int y=0;y<3;y++){ |
|
|
|
|
|
|
|
for(int x=0;x<3;x++){ |
|
|
|
|
|
|
|
vi2d coords=startingPipe+vi2d{x,y}; |
|
|
|
|
|
|
|
tiles[coords.y][coords.x].originalChar='.'; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char symbol='\0'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(initialPipe.value()->down&&initialPipe.value()->up)symbol='|'; |
|
|
|
|
|
|
|
if(initialPipe.value()->left&&initialPipe.value()->right)symbol='-'; |
|
|
|
|
|
|
|
if(initialPipe.value()->down&&initialPipe.value()->left)symbol='7'; |
|
|
|
|
|
|
|
if(initialPipe.value()->down&&initialPipe.value()->right)symbol='F'; |
|
|
|
|
|
|
|
if(initialPipe.value()->up&&initialPipe.value()->left)symbol='J'; |
|
|
|
|
|
|
|
if(initialPipe.value()->up&&initialPipe.value()->right)symbol='L'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(symbol=='\0')throw; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(initialPipe.value()->down)tiles[startingPipe.y+2][startingPipe.x+1].originalChar=symbol; |
|
|
|
|
|
|
|
if(initialPipe.value()->right)tiles[startingPipe.y+1][startingPipe.x+2].originalChar=symbol; |
|
|
|
|
|
|
|
if(initialPipe.value()->up)tiles[startingPipe.y][startingPipe.x+1].originalChar=symbol; |
|
|
|
|
|
|
|
if(initialPipe.value()->left)tiles[startingPipe.y+1][startingPipe.x].originalChar=symbol; |
|
|
|
|
|
|
|
tiles[startingPipe.y+1][startingPipe.x+1].originalChar=symbol; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vi2d currentPos=startingPipe+vi2d{1,1}; |
|
|
|
|
|
|
|
if(initialPipe.value()->down)MarkAndMove(currentPos,DOWN); |
|
|
|
|
|
|
|
else if(initialPipe.value()->right)MarkAndMove(currentPos,RIGHT); |
|
|
|
|
|
|
|
else if(initialPipe.value()->up)MarkAndMove(currentPos,UP); |
|
|
|
|
|
|
|
else if(initialPipe.value()->left)MarkAndMove(currentPos,LEFT); |
|
|
|
|
|
|
|
else throw; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while(true){ |
|
|
|
|
|
|
|
auto pipe=GetPipe(currentPos); |
|
|
|
|
|
|
|
if(pipe){ |
|
|
|
|
|
|
|
int moveCount=0; |
|
|
|
|
|
|
|
auto upPipe=GetPipe(currentPos+vi2d{0,-1}); |
|
|
|
|
|
|
|
if(upPipe&&!upPipe.value()->traversed&&upPipe.value()->originalChar!='.'){moveCount++;MarkAndMove(currentPos,UP);continue;} |
|
|
|
|
|
|
|
auto leftPipe=GetPipe(currentPos+vi2d{-1,0}); |
|
|
|
|
|
|
|
if(leftPipe&&!leftPipe.value()->traversed&&leftPipe.value()->originalChar!='.'){moveCount++;MarkAndMove(currentPos,LEFT);continue;} |
|
|
|
|
|
|
|
auto rightPipe=GetPipe(currentPos+vi2d{1,0}); |
|
|
|
|
|
|
|
if(rightPipe&&!rightPipe.value()->traversed&&rightPipe.value()->originalChar!='.'){moveCount++;MarkAndMove(currentPos,RIGHT);continue;} |
|
|
|
|
|
|
|
auto downPipe=GetPipe(currentPos+vi2d{0,1}); |
|
|
|
|
|
|
|
if(downPipe&&!downPipe.value()->traversed&&downPipe.value()->originalChar!='.'){moveCount++;MarkAndMove(currentPos,DOWN);continue;} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(moveCount>1)throw; |
|
|
|
|
|
|
|
if(moveCount==0)break; |
|
|
|
|
|
|
|
}else{ |
|
|
|
|
|
|
|
throw; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Test runs in all directions of looped pipes, see if they hit outer walls.
|
|
|
|
|
|
|
|
//If they do, starting from the wall, flood fill all adjacent tiles.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wait(0); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
//Wait for 0ms and render the screen (calls draw())
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
void doStuff(){ |
|
|
|
void doStuff(){ |
|
|
|
while(true){ //lines is accessible as a global.
|
|
|
|
while(true){ //lines is accessible as a global.
|
|
|
|
for(std::string&line:lines){ |
|
|
|
for(std::string&line:lines){ |
|
|
@ -82,7 +284,6 @@ void doStuff(){ |
|
|
|
pipes.push_back(row); |
|
|
|
pipes.push_back(row); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pipesRemaining.push_back(startingPipe); |
|
|
|
|
|
|
|
int maxDistance=0; |
|
|
|
int maxDistance=0; |
|
|
|
auto AddPipe=[&](vi2d coords,int distance){ |
|
|
|
auto AddPipe=[&](vi2d coords,int distance){ |
|
|
|
GetPipe(coords).value()->traversed=true; |
|
|
|
GetPipe(coords).value()->traversed=true; |
|
|
@ -121,19 +322,14 @@ void doStuff(){ |
|
|
|
//wait(0); //Wait for 0ms and render the screen (calls draw())
|
|
|
|
//wait(0); //Wait for 0ms and render the screen (calls draw())
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
*/ |
|
|
|
void draw(){ //Only use Sprites! If using decals, you must reference global variables!
|
|
|
|
void draw(){ //Only use Sprites! If using decals, you must reference global variables!
|
|
|
|
Clear(BLACK); |
|
|
|
Clear(BLACK); |
|
|
|
int count=0; |
|
|
|
int count=0; |
|
|
|
for(int y=0;std::vector<Pipe>&row:pipes){ |
|
|
|
for(int y=0;std::vector<Pipe>&row:tiles){ |
|
|
|
for(int x=0;Pipe&pipe:row){ |
|
|
|
for(int x=0;Pipe&pipe:row){ |
|
|
|
vi2d coords={x,y}; |
|
|
|
vi2d coords={x,y}; |
|
|
|
auto found=std::find(pipesRemaining.begin(),pipesRemaining.end(),coords); |
|
|
|
DrawString(coords*8,std::string(1,pipe.originalChar),pipe.partOfLoop?BLUE:(((x/3)+(y/3))%2==0)?YELLOW:WHITE); |
|
|
|
Pixel col=GREY; |
|
|
|
|
|
|
|
if(found!=pipesRemaining.end()){ |
|
|
|
|
|
|
|
col=YELLOW; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
DrawString(coords*8,std::to_string(pipe.distance),col); |
|
|
|
|
|
|
|
x++; |
|
|
|
x++; |
|
|
|
} |
|
|
|
} |
|
|
|
y++; |
|
|
|
y++; |
|
|
@ -166,7 +362,7 @@ public: |
|
|
|
|
|
|
|
|
|
|
|
bool OnUserUpdate(float fElapsedTime) override |
|
|
|
bool OnUserUpdate(float fElapsedTime) override |
|
|
|
{ |
|
|
|
{ |
|
|
|
static std::thread aocSolver(&AoC2023::doStuff,this); |
|
|
|
static std::thread aocSolver(&AoC2023::doStuff2,this); |
|
|
|
|
|
|
|
|
|
|
|
if(waitForRender){ |
|
|
|
if(waitForRender){ |
|
|
|
draw(); |
|
|
|
draw(); |
|
|
@ -179,7 +375,7 @@ public: |
|
|
|
int main() |
|
|
|
int main() |
|
|
|
{ |
|
|
|
{ |
|
|
|
AoC2023 game; |
|
|
|
AoC2023 game; |
|
|
|
if (game.Construct(640, 480, 2, 2)) |
|
|
|
if (game.Construct(3360,3360, 2, 2)) |
|
|
|
game.Start(); |
|
|
|
game.Start(); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|