How much water is left?

Here in California, we're in a drought so we need to know how much water we have left so we can conserve as much water as possible.

Because water is limited supply, your code will need to be as short as possible.

Examples

|   |
|   |
|~~~|
|___|

Output: 0.5

|~~~~~|
|     |
|     |
|_____|

Output: 1

|  |
|__|

Output: 0 (or bonus)


Specification

The input will consist solely of all of: |_ ~ and newlines. All above the ~'s are considered air; _, spaces below ~, and ~ itself are considered water. The percent of water left is computer by water / (air + water). Your output needs to be accurate to 4 decimal places (unless you go for the percent bonus). The input will always be rectangular. The ~ will only be on one line, if on any. The input may optionally also have a trailing line feed if you'd like.

Bonus

If you go for both bonuses the -15% bonus is applied before the -35 bonus

-35 byte Bonus: If your code prints "This drought goat out of hand", instead of 0 when the Output is 0

-15% Bonus: If you output a percent.

To do this, you would shift the decimal place two places to the left, trim leading zeros, and add a % to the end. Trailing zeros (max 2) are allows as long as they don't affect the value. 0.5 -> any of: 50.00% 50% 50.0%

• "Because water is limited supply, your code will need to be as short as possible." uhhh okay, makes sense... I guess? Dec 20, 2015 at 20:07
• @Fatalize: It's not common knowledge outside the state, but fluidic logic-based computers are extremely popular in California. I hear they're trying to see if they can work out an almond-based alternative these days. Dec 20, 2015 at 20:25
• @JohnE that probably explains why there is a drought there now Dec 20, 2015 at 20:50
• You guys know that fluidic computers don't use up water, right? Just like electric computers don't cause electron shortages. Dec 21, 2015 at 10:17
• Is this : |~~~| (no underscore) valid input? Dec 21, 2015 at 10:27

Pyth - 174645 52 * .85 - 35 = 9.2 bytes

Filters the input (With the new # filter meta-op!) for a line with ~ in it, then indexes that to the input, and then divides that by the length of the input. If there are none with ~, it errors, and triggers the except clause of .x and prints the string.

.x+*100-1cxK.zh@#\~KlK\%." u(C$éáPãbÉãç*îÂe[W  Python 3, 37 bytes lambda x:1-(x+'|~').find('|~')/len(x)  No bonuses. Takes an input string with newlines, including a trailing newline. Let's look at why the formula works. The fraction of water is the complement of the fraction of air, which we'll derive. frac_water = 1 - frac_air  Numbering the rows 0, 1, 2, ..., we have frac_air = water_row_index / num_rows  The same is true if both are multiplied by the width of each row, counting newlines, which simplify to expressions in the number of characters. frac_air = (width * water_row_index) / (width * num_rows) = water_row_start_char_index / num_chars  The water row start is found by searching the input string x for |~, and the number of chars is just the length. frac_air = x.find('|~') / len(x)  Finally, in order to make no-water inputs work, we append a fictional water row start |~ to the end before searching, which makes it look like the water level is 0. The bonuses seemed not worth it. The best I got on the string one is 73-35=38: lambda x:['This drought goat out of hand',1-x.find('|~')/len(x)]['~'in x]  CJam, 191716 58 * 0.85 - 35 = 14.3 bytes q'|-_'~#_)\@,d/1\m100*s'%+"This drought goat out of hand"?  Try it online This version gets both bonuses. The input must have a trailing newline for this solution to work. Thanks to @Martin Büttner for saving 2 bytes. Explanation: q Get input. '|- Remove left/right wall, so that position of first ~ in remaining string corresponds to the water level. _ Make a copy. '~# Find ~ character. _) Make copy of find result, and increment it. This is 0 if the ~ was not found, and will be used for the bonus condition. \ Swap original find result to top. @, Rotate copy of remaining input to top, and get its length. d Convert to double to get float division. / Divide the two values. Since the position of the ~ was indexed from the top, this is 1 minus the desired result. 1\m Subtract value from 1, to get the actual result. 100* Multiply by 100 to get percent. s Convert to string. '%+ Append % sign. "This drought goat out of hand" Push bonus zero string. ? Ternary operator to pick calculated result or zero string.  JavaScript (ES6), 45 (94 -15% -35) As an anonymous function. Using template strings, there is a newline that is significant and included in the byte count Edit 1 byte saved thx @user81655 p=>p.split .map((r,i)=>r>'|~'?p=i:q=~i)&&q-p?(1+p/q)*100+'%':'This drought goat out of hand'  Less golfed p=>( p.split('\n') // split in rows .map((r,i)=> // execute for each row r>'|~' // look for the water top ? p=i // position of water top in p : q=~i // if not water top, set current position (-i-1) in q ), // at the end,if water top not found, p still contains the input string q-p // subtracting the input string I get NaN (that is a falsy value) ? (1+p/q)*100+'%' // calc % taking into account the negative sign of q : 'This drought goat out of hand' )  Test snippet F=p=>p.split\n.map((r,i)=>r>'|~'?p=i:q=~i)&&q-p?(1+p/q)*100+'%':'This drought goat out of hand' function Update() { var w=+W.value, h=+H.value, t=+T.value, b=Array(h).fill().map((r,i)=>'|'+(i==h-1?'_':i==t?'~':' ').repeat(w)+'|').join\n O.textContent = b+'\n\n'+F(b) } Update() <table> <tr><td>Width</td><td><input id=W type=number value=4 oninput='Update()'></td></tr> <tr><td>Height</td><td><input id=H type=number value=4 oninput='Update()'></td></tr> <tr><td>~~~ at row</td><td><input id=T type=number value=2 oninput='Update()'></td></tr> </table> <pre id=O></pre> • Beautiful test snippet and great code as always! One suggestion: You could replace p=~i with p=i, &&-p with &&p-q and 1+~p to 1+p to save 1 byte. Dec 21, 2015 at 12:43 • @user81655 nice suggestion, thanks Dec 21, 2015 at 14:16 Par, 57 * 85% - 35 = 13.45 bytes This drought goat out of handr√″T┐↑⌐'~˦↑↔~÷Zx²*'%↔╡\z_g  Explanation This dr...d ## 'This drought goat out of hand' r ## Read entire input √ ## Split by newlines ″ ## Duplicate T ## Transpose ┐↑ ## Second element of each line ⌐ ## Reverse '~˦ ## First index of '~' ↑ ## Plus one ↔ ## Swap ~÷ ## Divide by size Z ## Assign to z x²* ## Multiply by 100 '%↔╡ ## Append '%' \ ## Array of string and number z_g ## If z=0, then string; else, number  Perl, 70 - 15% - 35 = 24.5 bytes includes +1 for -p $S[$w|=/~/]++}{$_=$w?100*$S[1]/$..'%':'This drought goat out of hand'  With comments: $S[ $w |= /~/ ]++ #$w=0 for air, 1 for having seen water; count element
}{                                  # -n/-p: end the while(<>){ and begin END block
$_ =$w                             # assign output for -p
? 100 * $S[1] /$. . '%'          # $. is$INPUT_LINE_NUMBER
:'This drought goat out of hand'  # costs 35 aswell, but is effectively more after -15%


• 26+1 byte version, no bonus: 27

$S[$w|=/~/]++}{$_=$S[1]/$.  • 34+1 byte version, with 15% bonus: 29.75 $S[$w|=/~/]++}{$_=100*$S[1]/$..'%'

• 61+1 byte version, with -35 bonus: 27

$S[$w|=/~/]++}{$_=$w?$S[1]/$.:'This drought goat out of hand'

• 69+1 byte version, both bonuses: 24.50

$S[$w|=/~/]++}{$_=$w?100*$S[1]/$..'%':'This drought goat out of hand'


Javascript, 59.3

I hope extra decimal places are OK. Assumes no trailing newline.

drought=
// code
a=>(b=-1,e=a.split
.map((c,d)=>b=c[1]=='~'?d:b).length,++b?(e-b+1)*100/e+"%":"This drought goat out of hand")

// I/O
var i = document.getElementById("i");
var o = document.getElementById("o");
i.onchange = i.onkeyup = function(){
o.textContent = drought(i.value);
};

// explanation
inputStr=>(
containerDepth =    // if the current line has a tilde, set tildePosition, otherwise
// keep current tildePosition
inputStr.split\n.map((line, pos)=> tildePosition = line[1]=='~' ? pos : tildePosition)
.length,          // assign number of lines (container depth) to containerDepth
++tildePosition     // if it's still -1, print the message, otherwise print percent
?(containerDepth-tildePosition+1)*100/containerDepth+"%"
:"This drought goat out of hand")
<textarea id="i"></textarea>
<p id="o"></p>

l=sum.(>>[1])
f i|s<-lines i=l(snd$break(elem '~')s)/l s  Usage example: f "| |\n|~~|\n| |\n|__|" -> 0.75. l is a custom length function, which is necessary, because the build in length returns integer values, but we need floating point values for the division (there's genericLength which also provides this feature, but it's longer, let alone the required import Data.List). f splits the input i into lines (-> s) and then into a pair where the first element is a list with all the lines up to (and excluding) the first one with a ~ in it. The second element is a list with the rest of the lines. The result is the length of the second element divided by the length of s. The bonuses don't pay off. Python is verbose! Python: 98.45 bytes (157 * 0.85) - 35 = 98.45 bytes This version reads from stdin, and collects both bonuses: import sys r=[x[1]for x in sys.stdin.read().split('\n|')] o="This drought goat out of hand"if'~'not in r else"%g%%"%(100-100.0*r.index('~')/len(r)) print(o)  • 66 without any bonuses: import sys;r=[x[1]for x in sys.stdin];print(1-r.index('~')/len(r)) Dec 21, 2015 at 6:59 • Nice! That gets tripped up by the optional trailing newline though, doesn't it? Also, is it Python 3-only because of the division operator? Dec 21, 2015 at 11:31 • The optional trailing newline is up to you to include. As for the division, yeah, but you're already treating print like a function so I assumed you were using Python 3. Dec 21, 2015 at 16:47 Awk, 72 characters - 15% - 35 = 26.2 /~/{w=NR}END{print w?(NR-w+1)/NR*100"%":"This drought goat out of hand"}  Sample run: (Initial 1; only used in these sample runs to display the “human readable” tank.) bash-4.3$ awk '1;/~/{w=NR}END{print w?(NR-w+1)/NR*100"%":"This drought goat out of hand"}' <<< $'| |\n| |\n| |\n|_|' | | | | | | |_| This drought goat out of hand bash-4.3$ awk '1;/~/{w=NR}END{print w?(NR-w+1)/NR*100"%":"This drought goat out of hand"}' <<< $'| |\n| |\n|~|\n|_|' | | | | |~| |_| 50%  PHP, 92 characters - 15% - 35 = 43.2 (88 characters in two blocks of code + 4 characters command line options.) $argn[1]>z&&$w=+$argi;

echo$w?100*($argi-$w+1)/$argi."%":"This drought goat out of hand";


Assumes error_reporting is set to default.

(Not a big deal, just wished to use the -R and -E once. Now only -B left.)

Sample run:

(Initial echo"$argn\n"; only used in these sample runs to display the “human readable” tank.) bash-4.3$ php -R 'echo"$argn\n";$argn[1]>z&&$w=+$argi;' -E 'echo$w?100*($argi-$w+1)/$argi."%":"This drought goat out of hand";' <<< $'| |\n| |\n| |\n|_|' | | | | | | |_| This drought goat out of hand bash-4.3$ php -R 'echo"$argn\n";$argn[1]>z&&$w=+$argi;' -E 'echo$w?100*($argi-$w+1)/$argi."%":"This drought goat out of hand";' <<< $'| |\n| |\n|~|\n|_|' | | | | |~| |_| 50%  QBIC - 116 - 15% = 98.6 bytes {input S$:S$=MID$(S$,2,1):I=I+1:IF y<1 then x=I y=y+instr(S$,"~"):IF instr(S$,"_")>0 THEN ?(1-(x-y)/I)*100;"%":END}  I've created QBIC to make QBasic more competitive, but it still needs several improvements. As of now, there are no shortcuts for error trapping, THEN (which is a pretty big oversight on my part) and input$. They will be added shortly.

I couldn't hit the 0 bonus, too costly... I did manage to print percentages.

Sample in/output:

? |  |
? |  |
? |~~|
? |__|
50 %


The program reads the input interactively. When it detects the bottom of the lake (_) it prints the percentage and quits. Tested for full containers and empty ones as well.

Edit: To show how QBIC has been expanded during the last year, here's the same program written for the current interpreter:

{_?A=$MID$|(A,2,1)#~|#_| i=i+1~j<1|k=i]j=j+instr(A,B)~instr(A,C)|?(1-(k-j)/i)*100,@%|_X


87 bytes, printing percentages, is a score of 74.