# Fill the (possibly leaky) bowl

## Challenge:

Given an ASCII art of a (possibly leaky) bowl consisting of a random distinct non-whitespace and non-~ character, fill it completely with ~ characters. If the bowl is leaky, fill the bottom row below the bowl and a stream of liquid emerging from that, with the intended amount of ~ if the bowl would not have been leaky.

For example:

Regular bowl:

Input Output
#      # #    #   ####  
#~~~~~~# #~~~~#   ####  

Leaky bowl:

Input Output
00     00 00   00   000 0  
00     00 00   00 ~~000~0~~     ~        ~        ~   

If there wouldn't have been a leak, it could have contained eight ~. Instead, the bottom row including leak position is now filled with five ~, and the remaining three ~ are below the leak.
(Imagine the bowl standing on a table, so the five ~ at the bottom row of the bowl are on the table, and the ~ vertically below the leak are dripping off the table.)

## Challenge rules:

• The potential leak is guaranteed to be at the bottom row, and there will never be any gaps at the sides of a bowl.
• The potential leak is guaranteed to be a single character gap.
• The character used for the bowl can be any printable ASCII character, except for the ~ and whitespaces.
• The bowl can be in an irregular shape (see some of the test cases).
• The top ridges of the bowl are guaranteed to be on the same top row, and there will only be two top ridges.
• If the bottom row contains more space characters than inside the leaky bowl (see the third leaky bowl test case below), we still fill the entire bottom row of the output regardless, but there won't be any additional ~ below it.
• For the sake of this challenge, there won't be any smaller inner bowls (e.g. no doughnut-shaped bowls if we'd imagine it as 3D). So every space in the bowl will always flow towards the leak. (See the fourth leaky bowl test case below, which doesn't have #~# # as its second line.)
• There also won't be any enclosed blobs at the sides (or inside) of a bowl, not any 'stalagmites' nor 'stalactites'.
• I/O is flexible. Could be a multi-line string; a list of lines; a character matrix; etc.
• You're allowed to pad the input with trailing spaces to make the input a rectangle.
• You're allowed to have leading/trailing whitespaces and/or newlines in the output, as long as the expected result is somewhere on the screen.

Here some examples of invalid bowls based on the rules. If you have a question about a certain bowl-shape, feel free to ask in the comments.

## General rules:

• This is , so the shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
• Default Loopholes are forbidden.

## Test cases

Regular bowls:

Inputs Outputs
#      # #    #   ####  
#~~~~~~# #~~~~#   ####  
!!!        !!   !!      !      !!!   !         !!!! 
!!!~~~~~~~~!!   !!~~~~~~!      !!!~~~!         !!!! 
4   44 4 444444
4~~~44~4~444444
  B B   B   B B     BB     B B   B   BBB  
  B~B   B~~~B B~~~~~BB~~~~~B B~~~B   BBB  
sss  sss  s  s     s s  ssssssssss
sss~~sss  s~~s     s~s  ssssssssss

Leaky bowls:

Inputs Outputs
00     00 00   00   000 0  
00     00 00   00 ~~000~0~~     ~        ~        ~   
^^^        ^   ^^      ^     ^^^   ^        ^ ^ 
^^^        ^   ^^      ^     ^^^   ^~~~~~~~~^~^~         ~           ~           ~           ~           ~           ~           ~  
@@@ @@@  @ @  
@@@ @@@~~@~@~~
#   ## # #### #
#   ## # ####~#   ~    ~    ~    ~ 
xx xxx   xx   x xx  
xx xxx   xx   x~xx~~   ~    ~    ~    ~ 
2 22 2
2 22~2
• I'm not totally clear what shapes a bowl might have. For instance, might it have multiple columns going up to the top row so it has multiple compartments? What about protrusions coming out of the sides?
– xnor
Jan 12 at 14:53
• @xnor No to the first question (combination of fifth + seventh rule prevent this). And I'll clarify the second question. Jan 12 at 15:01
• @xnor I've added an additional rule about inner compartments and stalagmites/stalactites. I've also added a pastebin to give examples of invalid input-bowls. If there is a certain shape of bowl you're unsure about based on the current rules, feel free to ask again. The definition of the bowl was indeed the hardest part to define when it was in the Sandbox, so it's possible there are more edge cases I hadn't thought of yet.. Jan 12 at 15:22
• Thanks for the additional info. I'm not really sure what counts as a stalagmites/stalactite from the examples. Is the key thing that they have a mini-cup that could hold water right side up or upside down? What if the protrusion is just a diagonal line? What if it's on the inside of the bowl? I think these types of thing can matter for answers and you're going to need to come up with a comprehensive definition for valid bowls, tricky as that may be. Or, restrict the possibilities.
– xnor
Jan 12 at 15:39
• @ovs You're completed right! Fixed. Jan 13 at 11:45

# Charcoal, 76 bytes

ＷＳ⊞υι≔Ｅυ⭆ι⎇∧∧⁻…ιμ ⁻✂ιμＬι¹ ⁼ λ~λη¿⁼§η±¹⊟υη«υ≔⊟ηζ⟦⭆ζ⎇⁼ ι~ι⟧Ｅ⁻№⪫ηω~№ＫＡ~⭆ζ§ ~⁼~λ


Try it online! Link is to verbose version of code. Takes input as a rectangular list of newline-terminated strings. Explanation:

ＷＳ⊞υι≔


Input the bowl.

Ｅυ⭆ι⎇∧∧⁻…ιμ ⁻✂ιμＬι¹ ⁼ λ~λη


Try to fill the bowl with water.

¿⁼§η±¹⊟υη«


If the bowl isn't leaky, then output the filled bowl. Otherwise:

υ


Output all but the last row of the bowl.

≔⊟ηζ


Get the last row of the leaky bowl.

⟦⭆ζ⎇⁼ ι~ι⟧


Flood it and output the result.

Ｅ⁻№⪫ηω~№ＫＡ~⭆ζ§ ~⁼~λ


Count how much extra water there is and output just the hole of the last row of the leaky bowl for each extra line needed.

# Python3, 522 bytes:

from re import*
r=range
g=lambda x:[i for i in r(len(x))if i and i<len(x)-1 and findall('^(?:[^\s]|\s)\s+\$',''.join(x[i]))and any(d!=' ' for d in x[i-1][1:])and any(d!=' ' for d in x[i+1][1:])]
f=lambda x:'\n'.join(sub('(?<=[^\s])\s+(?=[^\s])',lambda x:'~'*len(x.group()),l)for l in k)if not(j:=g([*zip(*(k:=x.split('\n')))]))else'\n'.join(k[:-1]+[sub(' ','~',k[-1])]+[' '*j[0]+'~'+' '*(len(k[-1])-j[0]+1) for _ in r(sum(len(findall('(?<=[^\s])\s+(?=[^\s])',n)[0])for n in k[:-1])-k[-1].count(' ')+(k[-1].count(' ')==1))])


Try it online!

• 499 bytes by removing some spaces and creating a variable for the duplicated '(?<=[^\s])\s+(?=[^\s])' Jan 12 at 20:57
• The +(k[-1].count(' ')==1) can be removed. I made an error in that last leaky test case. Jan 13 at 11:46

# APL(Dyalog Unicode), 145 bytes SBCS

A dfn taking a character matrix.

{h w←⍴m←' '=⍵
i←{∪⍵,(⌷∘(0@h⊢m)¨n)/n←⍵~⍨,(⌽q)(-q)q∘.+⍵}⍣≡⊂q+⊃⍸m⍷⍨q←0 1
b←h⌷m
×x←⊃⍸b∧i∊⍨(h-1),¨⍳w:'~'@((h,¨⍸b),x,⍨¨h+⍳d)⊢⍵↑⍨h+d←0⌈(≢i)-+/b
'~'@i⊢⍵}


Try it on APLgolf!

Ungolfed:

Fill ← {
Height Width ← ⍴ Mask ← ' '=⍵
⍝ The initial interior piece is identified by the first occurence of <wall><no wall>
⍝ Iteratively expand the interior to the right, left and bottom
Deltas  ← (1 0)(0 ¯1)(0 1)
Volume  ← ≢ Interior ← {∪⍵,(⌷∘Fixed¨n)/n←⍵~⍨,Deltas∘.+⍵}⍣≡ Opening