Retina, 293 + 15 = 308 314 385 bytes
;`\s
_
;`\\
/
;`.+
o$0iio
;+`(o(?=/.*(i)|L.*(ii)|V.*(io)|_)|i(?=/.*(io)|L.*(o)|_.*(ii)|V.*(i))).
$1$2$3$4$5$6$7$8
;`o
<empty>
;`ii$
#:0123456789
;+`^(?=i)(i*)\1{9}(?=#.*(0)|i#.*(1)|ii#.*(2)|iii#.*(3)|iiii#.*(4)|iiiii#.*(5)|iiiiii#.*(6)|iiiiiii#.*(7)|iiiiiiii#.*(8)|iiiiiiiii#.*(9))
$1#$2$3$4$5$6$7$8$9$10$11
:.*|\D
<empty>
Each line goes in a separate file, so I've added 13 to the byte count. Alternatively, you can put that all in a single file as is and use the -s
flag. The <empty>
stand for actually empty files or lines.
Unfortunately, I need 187 bytes just to convert the result from unary to decimal. I guess I really should implement this some time soon.
Explanation
Retina is a regex-based language (which I wrote exactly for being able to do stuff like this with regex). Each pair of files/lines defines a replacement stage, with the first line being the pattern and the second line the replacement string. Patterns can be preceded by a `
-delimited configuration string, which may contain the usual regex modifiers, as well as some Retina-specific options. For the above program, the relevant options are ;
, which suppresses output of that stage and +
, which applies the replacement in a loop until the result stops changing.
The idea of the solution is to count each line separately, because we can always decide by the characters already encountered whether we're inside or outside the polygon. This also means I can join the entire thing into a single line, because going the beginning and end of a line are always outside the polygon. We can also note that _
and space are completely identical for a line sweep algorithm, as well as \
and /
. So as a first step I replace all newlines and spaces by _
and all \
by /
to simplify some code later on.
I'm keeping track of the current inside/outside state with the characters i
and o
, while also using the i
s to tally the area. To do so I start by prepending an o
to the joined line to mark that we're outside the polygon. I'm also adding an iio
to the very end of the input, which I'll use as a lookup to generate new characters.
Then, the first large replacement simply replaces an i
or o
followed by one of /V_L
with the next set of characters, thereby flooding and tallying the entire thing. The replacement table looks as follows, where the columns correspond to the last character in that line and the rows to the next character (where S
is for space and <>
for an empty string). I've included all characters of the input to show the equivalences I've already made use of:
i o
/ io i
\ io i
L o ii
V i io
_ ii <>
S ii <>
Note that the final character then always indicates whether after the character we're inside or outside the polygon, while the number of i
s corresponds to the area that needs to be added to the polygon. As an example here are the results of the first four iterations on the last example input (this was generated by an old version which actually flooded each line separately, but the principle is still the same):
o /V\
o / \___
o L _/
o/\/ /V
oL__ _/
o V
o /V\
o / \___
o L _/
oi\/ /V
oii__ _/
o V
o /V\
o/ \___
oL _/
oiio/ /V
oiiii_ _/
o V
o/V\
oi \___
oii _/
oiioi /V
oiiiiii _/
oV
oiV\
oiii \___
oiiii _/
oiioiii /V
oiiiiiiii_/
oio
Lastly, I just get rid of all the o
s and the line breaks by removing everything that matches [^i]
, and the remainder is the decimal-to-unary conversion which is rather boring.
^
intentionally? \$\endgroup\$