Install Steam
login
|
language
简体中文 (Simplified Chinese)
繁體中文 (Traditional Chinese)
日本語 (Japanese)
한국어 (Korean)
ไทย (Thai)
Български (Bulgarian)
Čeština (Czech)
Dansk (Danish)
Deutsch (German)
Español - España (Spanish - Spain)
Español - Latinoamérica (Spanish - Latin America)
Ελληνικά (Greek)
Français (French)
Italiano (Italian)
Bahasa Indonesia (Indonesian)
Magyar (Hungarian)
Nederlands (Dutch)
Norsk (Norwegian)
Polski (Polish)
Português (Portuguese - Portugal)
Português - Brasil (Portuguese - Brazil)
Română (Romanian)
Русский (Russian)
Suomi (Finnish)
Svenska (Swedish)
Türkçe (Turkish)
Tiếng Việt (Vietnamese)
Українська (Ukrainian)
Report a translation problem
I would suggest you have another think about it before revealing the spoiler, since I do think you can come up with the solution fairly easily. Again, though - it's very inefficient.
In Python-pseudocode:
Ok, that's kind of what I came up with when I thought about it. I haven't finished writing all the code for it yet though. I'm worried I'm not going to have enough memory for the code though. I might need to use multiple program blocks and change how the program counter works.
I think that the games "hit ENTER to show water" solution preview is kind of misleading, because it is adding the volume in columns.
There is a (in my opinion) pretty clean solution hiding in plain sight - you just need to think in a different direction.
My first solution:
Determine the highest and lowest point (seems to always be 6/1, so I might as well could've turned that into a constant)
Iterate over the height data for each height between max (inclusive) and min (exclusive) and count the air between walls
That's it - no, really. Done in 5 list iterations.
Although, looking at the problem again... I'm pretty sure I can do it in one iteration as well.
1- Moving from left to right:
- Scan the data to find the highest land, count total land squares while you're doing so
- Calculate total available spots for water (16 * high - total land squares)
- Count in from left edge until you hit a high point, removing squares where water would run off
- Repeat on right edge
Steps 3 and 4 are the interesting ones, as you throw out all the water that is higher than the highest land point you've seen so far as you traverse inwards.
You only need one pass.
(pseudo-code)
The key is that the case of there being no right wall in the final region is automatically handled, since the "uncommitted" current_water remains "uncommitted" in that case.
That's so much simpler than the code I came up with.
I am filling it not row by row, but basin by basin while I am reading the input.
This is done by pushing all falling edges (height and index) onto the stack and popping them when a rising edge comes and then having fun to decide if I need that last falling edge again :D
I think it is more complex (and probably a bit slower) than the other solutions, but for a real-world scenario it could have benefit that it can calculate the current volume on the fly and you can say "If I start here, let's just go into this direction until a certain condition is met (e.g. I want to have at least x amount of water)"
So it is roughly this as pseudo code:
Oh yeah - and because I could not come up with a way to solve this with 6 registers I sometimes have to carefully push/pop an additional value, so my stack is a bit of a mess, but it works :D
for each column i saved whats the highest wall to its right, denoted I_right
and the highest wall to its right, denoted I_left
if theres no biggest wall to the right or left, then its 0.
then the output for a given column with height i should be max ( min (I_left, I_right) , 0 )
you can get the highest wall to the right, by doing a full pass from right to left and giving each the maximum height you saw till now.
symmetric with highest from the left.
in total it takes 3 passes of the number of values, and 509 ticks on my first bad 4.1K gate computer
Keep track of a left and right pointer that start at the beginning and end of the columns, and keep track of the maximum wall height on both sides. So left_pointer, left_max, right_pointer, right_max. Then just check which column, column[left] or column[right] is smaller. Increment/decrement the pointer of the smaller side, and check if the new column, column[left/right] is smaller than the previous max on that side, left_max/right_max. If it is, we can add that column of water to the total: sum += right_max/left_max - column[right/left]. If the new column is greater or equal to the previous max, reset the previous max to the current height. Continue until right_pointer <= left_pointer. With 6 registers (with the 6th being used as a RAM pointer, so really 5 usable registers), there are just enough to hold the pointers, previous max's, and sum. Although you will need to output the difference of the previous max height to current column height in the stack to then add it to the sum.
Code:
It's javascript, but it's similar to what you might use for your CPU.
It searches for peaks and then calculate amount of water between the peaks.
let r0=0,r1=0,r2=0,r3=0,r4=0,r5=0,r6=0,r7=0,r8=0,r9=0,r10=0,r11=0,r12=0,r13=0,r14=0,r15=0,r16=0;
let alu1=0,alu2=0,alu3=0,alu4=0;
/*
r9 - total amount of water
r10 - array start coord
r11 - amount of highs
r0 - index
r1 - array coord
r2 - up
r3 - left
r4 - right
r5 - high
r6 - loop high
r8 = number of current segment
r2 = a right
r3 = a high
r4 = b left
r5 = b high
r6 = loop high
r6 = column water
r7 = water level of a segment
*/
r0 = 1;
read();
scan();
if (r11 > 1) {
next();
} else {
r9 = 0;
}
console.log(r9);
// Functions:
function read() {
RAM[r0] = arr[r0 - 1];
r0++;
if (r0 >= 17) return;
read();
}
function scan() {
r2 = 1;
r0+=1;
r1 = r0;
r10 = r1;
r3 = -1;
r0 = 0;
for(;;) {
r6 = RAM[r0];
if (!(r6 <= r5)) {
r3 = r0; r3--;
r5 = r6;
r2 = 1;
}
if (!(r6 >= r5) && !(r2 === 0)) {
r4 = r0;
RAM[r1] = r3; r1++;
RAM[r1] = r4; r1++;
RAM[r1] = r5; r1++;
r2 = 0;
r11++;
}
r5 = r6;
if (r0 > 18) break;
r0++;
}
}
function next() {
if (r8 >= r11 - 1) return;
r1 = r10 + r8 * 3;
r2 = RAM[r1 + 1];
r3 = RAM[r1 + 2];
r4 = 0;
r5 = 0;
r0 = r8 + 1;
for(;;) {
r1 = r10 + r0 * 3;
r6 = RAM[r1 + 2];
if (r6 >= r3) {
r4 = RAM[r1];
r5 = r6;
r8 = r0;
break;
}
if (r6 > r5) {
r4 = RAM[r1];
r5 = r6;
r8 = r0;
}
r0++;
if (r0 >= r11) break;
}
water();
next();
}
function water() {
r7 = r3;
if (r5 < r3) {
r7 = r5;
}
r0 = r2;
for(;;) {
if (r0 > r4) break;
alu1 = RAM[r0];
r0++;
if (alu1 >= r7) continue;
r6 = r7 - alu1;
r9 += r6;
}
}