Day 11: Cosmic Expansion
I initially looked at this puzzle yesterday morning, and was like nope, don't have time for this today, so have managed to solve part one today on day 12.
The problem seemed a bit challenging to me because I wasn't completely sure how I could loop through the space whilst simultaneously growing it, but realised I could do this quite well by recording the growth offset and factoring that in. I had problems though in that I initally grew the space vertically before horizontally, and there was a bug I couldn't figure out, and didn't have time to. I resolved it by switching the order to grow horizontally first.
The next part to analyse the distances between galaxies went smoothly and quickly. Looking at part two and it's an interesting challenge. Not sure of a solution straight away and no time now!
I have brute forced many of the solutions to these puzzles, but I wasn't going to do that with the one million times bigger expanses of space for part two. No, no. I thought of a solution on the flight to London and have implemented it now. I liked this puzzle.
I had a lot of trouble with my original array being mutated when I was trying to copy it, and I realised I don't understand how this works in JS properly. Advice online to copy rather than reference was not working, even the ones that were supposed to be supported with vanilla JS, so I will have to look into this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
const inputToUse = realInput;
const inputLines = inputToUse.split(/\n/);
// console.log('inputLines',inputLines);
const spaceMap = [];
inputLines.forEach(function(line,i){
const cleanLine = line.trim();
const spaceRow = [];
const chars = cleanLine.split('');
chars.forEach(function(char, i){
spaceRow.push(char);
});
spaceMap.push(spaceRow);
});
// console.log('spaceMap',spaceMap);
// we now have spaceMap
// console.log('spaceMap.length', spaceMap.length);
const expandedSpaceMap = spaceMap.slice();
// console.log('expandedSpaceMap',expandedSpaceMap);
// ! Check map vertically. If a whole column is empty, space expands (another empty column)
const vertExpanseBoundaries = [];
const mapWidth = expandedSpaceMap[0].length
var horzExpandOffset = 0;
// for each column
for( var i=0; i<mapWidth; i++ ) {
// console.log(`checking column ${i} with offset ${horzExpandOffset}; column ${i+horzExpandOffset}`);
const columnVals = [];
// for each row
for( var j=0; j<expandedSpaceMap.length; j++ ) {
const node = expandedSpaceMap[j][i+horzExpandOffset];
columnVals.push(node);
}
// console.log(`vals in column ${i}`,columnVals);
const colCharSet = new Set(columnVals);
const uniqueCharCount = colCharSet.size;
if( uniqueCharCount === 1 && Array.from(colCharSet)[0] === '.' ) {
// console.log('this col is empty space');
const splicePoint = i + horzExpandOffset;
// console.log('splicePoint',splicePoint);
// for each row
for( var k=0; k<expandedSpaceMap.length; k++ ) {
expandedSpaceMap[k].splice(i + horzExpandOffset,0,'.');
}
horzExpandOffset = horzExpandOffset + 1;
// console.log('prog expanded expandedSpaceMap',expandedSpaceMap);
vertExpanseBoundaries.push(i);
}
}
// console.log('horz expanded expandedSpaceMap',expandedSpaceMap);
// ! Check map horizontally. If a whole row is empty, space expands (another empty row)
const horzExpanseBoundaries = [];
const rowCount = expandedSpaceMap.length
var vertExpandOffset = 0;
// for each row
for( var i=0; i<rowCount; i++ ) {
const row = expandedSpaceMap[i+vertExpandOffset];
// for each node
const rowCharSet = new Set(row);
const uniqueCharCount = rowCharSet.size;
if( uniqueCharCount === 1 ) {
const char = Array.from(rowCharSet)[0];
if( char === '.' ) {
// this row is empty space
const splicePoint = i+vertExpandOffset;
expandedSpaceMap.splice(splicePoint,0,row);
vertExpandOffset = vertExpandOffset + 1;
horzExpanseBoundaries.push(i);
}
}
}
// console.log('expandedSpaceMap',expandedSpaceMap);
// we now have completely expanded space map
const galaxies = [];
expandedSpaceMap.forEach(function(row, i){
row.forEach(function(node,j) {
const value = node;
if( value == '#' ) {
const obj = {
value:value,
y:i,
x:j
}
galaxies.push(obj);
}
});
});
// console.log('galaxies',galaxies);
// we now have a list of galaxies
const shortestPaths = [];
galaxies.forEach(function(galaxy,i){
// compare the galaxy with following galaxies
for( var j=i+1; j<galaxies.length; j++ ) {
const neighbour = galaxies[j];
// console.log(`compare galaxy ${i}`, galaxy, `with neighbour ${j}`, neighbour);
const largestY = Math.max(galaxy.y, neighbour.y);
const smallestY = Math.min(galaxy.y, neighbour.y);
const yDistance = largestY - smallestY;
const largestX = Math.max(galaxy.x, neighbour.x);
const smallestX = Math.min(galaxy.x, neighbour.x);
const xDistance = largestX - smallestX;
const distance = yDistance + xDistance;
shortestPaths.push(distance);
}
});
// console.log('shortestPaths',shortestPaths);
var sumOfPaths = 0;
shortestPaths.forEach(function(path){
sumOfPaths = sumOfPaths + path;
});
console.log('sumOfPaths',sumOfPaths);
// ––––––––––––––––––––––
// ! pt 2 – the expanse
// console.log('vertExpanseBoundaries',vertExpanseBoundaries);
// console.log('horzExpanseBoundaries',horzExpanseBoundaries);
// console.log('expanseBoundariesCrossed',expanseBoundariesCrossed);
const origMap = []; // I am having real trouble with the original mutating
inputLines.forEach(function(line,i){
const cleanLine = line.trim();
const spaceRow = [];
const chars = cleanLine.split('');
chars.forEach(function(char, i){
spaceRow.push(char);
});
origMap.push(spaceRow);
});
// console.log('origMap',origMap);
const oldGalaxies = [];
origMap.forEach(function(row,i){
row.forEach(function(node,j) {
const value = node;
if( value == '#' ) {
const obj = {
value:value,
y:i,
x:j
}
oldGalaxies.push(obj);
}
});
});
// console.log('oldGalaxies',oldGalaxies);
const shortestPathsExcludingExpanse = [];
var expanseBoundariesCrossed = 0;
oldGalaxies.forEach(function(galaxy,i){
// compare the galaxy with following galaxies
for( var j=i+1; j<oldGalaxies.length; j++ ) {
const neighbour = oldGalaxies[j];
// console.log(`compare galaxy ${i}`, galaxy, `with neighbour ${j}`, neighbour);
const largestY = Math.max(galaxy.y, neighbour.y);
const smallestY = Math.min(galaxy.y, neighbour.y);
const yDistance = largestY - smallestY;
const largestX = Math.max(galaxy.x, neighbour.x);
const smallestX = Math.min(galaxy.x, neighbour.x);
const xDistance = largestX - smallestX;
var boundariesCrossedThisJourney = 0;
vertExpanseBoundaries.forEach(function(boundary){
// console.log('analysing boundary',boundary);
if( smallestX < boundary && largestX > boundary ) {
// we crossed a vertical boundary
boundariesCrossedThisJourney = boundariesCrossedThisJourney + 1;
}
});
horzExpanseBoundaries.forEach(function(boundary){
// console.log('analysing boundary',boundary);
// console.log('smallestY',smallestY);
// console.log('largestY',largestY);
if( smallestY < boundary && largestY > boundary ) {
// we crossed a horizontal boundary
boundariesCrossedThisJourney = boundariesCrossedThisJourney + 1;
}
});
expanseBoundariesCrossed = expanseBoundariesCrossed + boundariesCrossedThisJourney;
const distance = yDistance + xDistance - boundariesCrossedThisJourney;
shortestPathsExcludingExpanse.push(distance);
}
});
// console.log('shortestPathsExcludingExpanse',shortestPathsExcludingExpanse);
console.log('expanseBoundariesCrossed',expanseBoundariesCrossed);
const expanseDistanceCovered = parseFloat(`${expanseBoundariesCrossed}000000`);
console.log('expanseDistanceCovered',expanseDistanceCovered);
var distanceCoveredWithExpanse = 0;
shortestPathsExcludingExpanse.forEach(function(distance){
distanceCoveredWithExpanse = distanceCoveredWithExpanse + distance;
});
console.log('total distance covered without expanse',distanceCoveredWithExpanse);
distanceCoveredWithExpanse = distanceCoveredWithExpanse + expanseDistanceCovered;
console.log('distanceCoveredWithExpanse',distanceCoveredWithExpanse);