Fill in the lakes

19

1

Given the topography of land in ASCII picture format, figure out where lakes would go and fill them in. Assume an infinite amount of rain.

example

input

         #               
         ##              
      # ####             
#    #########           
##  ###########          
## #############   ####  
## ##############  ##### 
################# #######
#########################
#########################

output

         #               
         ##              
      #@####             
#@@@@#########           
##@@###########          
##@#############@@@####  
##@##############@@##### 
#################@#######
#########################
#########################

The input will contain only spaces and # marks. Each line will be the same length. The output should be the identical # pattern with spaces where water would accumulate filled in with @ marks.

The bottom input row will always be all # marks. There will be no holes or overhangs in the land. Shortest code wins.

Keith Randall

Posted 2011-05-12T20:43:24.543

Reputation: 19 865

This seems a bit easy. I think we should also have to display the number of lake units @ that were filled in. – mellamokb – 2011-05-12T20:53:26.927

1@mellamokb: This would be roughly a ([char[]]"$a"-eq'@').Count here. Not that much too add. Agreed on this being a little too easy, though. Doesn't fall into the realm of what I'd downvote, though. – Joey – 2011-05-12T20:55:41.900

3

Related on Stack Overflow: Code Golf: Running Water. One of LiraNuna's better one, I thought.

– dmckee --- ex-moderator kitten – 2011-05-12T21:41:20.033

1So do we also have to handle underground caverns, which may have air above the water level like the Running Water puzzle? That makes things a little more challenging and I think should definitely be an example use case. – mellamokb – 2011-05-12T21:45:51.200

@dmckee: That one wasn't as easy as this though. – Joey – 2011-05-12T21:45:58.110

@mellamokb: I think we agreed some time ago that the questions from SO are not to be replicated here. Mostly because there are already solutions there. – Joey – 2011-05-12T21:48:22.617

@joey: No. The possibility of the caves seems to rule our a simple regexp solution to the LiraNuna one. – dmckee --- ex-moderator kitten – 2011-05-12T21:52:43.297

Since # and @ are both massive characters, I suggest using . instead of @, which gives better pictures, IMHO. – user unknown – 2011-05-13T13:52:18.367

Answers

8

sed -r, 27 24 (27 with -r)

24 (27):

:;s/(#|@) ( *#)/\1@\2/;t

27 (30):

:e;s/([#@]) ( *#)/\1@\2/;te

Competes with the better of the two perl solutions

asoundmove

Posted 2011-05-12T20:43:24.543

Reputation: 358

#|@ would be one char shorter – YOU – 2011-05-13T06:34:13.387

2You should add 3 to the count for the -r flag. You can cut off two from removing the es, and another from S.Mark's suggestion to get back to 27 though. – Nabb – 2011-05-13T07:25:55.323

@Nabb thanks, discovered something with the empty label – asoundmove – 2011-05-13T12:36:37.573

I tried sed before, but failed – Ming-Tang – 2011-05-13T17:45:05.713

@Keith, thanks for the award. – asoundmove – 2011-05-21T05:09:49.720

7

Perl, 25

s/# +#/$_=$&;y| |@|;$_/ge

Ming-Tang

Posted 2011-05-12T20:43:24.543

Reputation: 5 383

I added a character count. Please look whether it's actually correct, as it might need to include some interpreter flags (-p maybe?). – Joey – 2011-05-13T07:25:29.473

i dont know perl language, but i can feel its power :) – Ant's – 2011-05-13T13:33:26.763

Actually it needs -pe to function on my box, so that should be an additional 4 chars. Or does the e not count and thus only 3 additional chars required? – asoundmove – 2011-05-13T23:24:45.363

Don't need the e, like I mentioned elsewhere, for the same reasons. :) – Robert P – 2011-05-26T17:55:52.900

6

Perl (>= v5.9.5), 24 chars

Run with perl -p:

1while s/#.*\K (?=\S)/@/

This requires Perl 5.9.5 or later to use the special escape \K.

yibe

Posted 2011-05-12T20:43:24.543

Reputation: 161

1Except that if Nabb is correct, you need to count -p as 3 chars, bringing your total to 27. And it actually requires -pe. I don't know the full rules about flags, so not sure the e counts. – asoundmove – 2011-05-13T23:27:04.490

Wouldn't actually need the e, if you simply hit enter and type it in afterwards, or put the code in a file and run it. So -e isn't really needed. :) – Robert P – 2011-05-26T17:52:52.727

3

Windows PowerShell, 36 74 138

$input-replace'(?<!^ *) (?! *$)','@'

Joey

Posted 2011-05-12T20:43:24.543

Reputation: 12 260

2

Retina, 10 bytes

Retina is (much) newer than this challenge. But this solution is too neat not to post it:

T` `@`#.*#

Try it online.

This is simply a transliteration stage which replaces spaces with @, but the operation is restricted to matches of #.*#, i.e. characters which are surrounded by land on both sides.

Martin Ender

Posted 2011-05-12T20:43:24.543

Reputation: 184 808

1

05AB1E, 17 16 bytes

|εγć?D¨ð'@:sθJJ,

Try it online.

Explanation:

|            # Take all input-lines as list
 ε           # For each line:
  γ          #  Split the line into chunks of consecutive equal characters
             #   i.e. " ##   # " → [' ','##','   ','#',' ']
   ć         #  Split into head and the rest of the list
             #   i.e. [' ','##','   ','#',' '] → ['##','   ','#',' '] and ' '
    ?        #  Print this head
   D         #  Duplicate the rest of the list
    ¨        #  Remove the last element
             #   i.e. ['##','   ','#',' '] → ['##','   ','#']
     ð'@:    #  Replace every space with a "@"
             #   i.e. ['##','   ','#'] → ['##','@@@','#']
     sθ      #  Swap so the duplicated list is at the top, and take the last item as is
             #   i.e. ['##','   ','#',' '] → ' '
         JJ  #  Join the lists and individual items in the list together to a single string
             #   i.e. ['##','@@@','#'] and ' ' → "##@@@# "
           , #  Print with trailing new-line

Kevin Cruijssen

Posted 2011-05-12T20:43:24.543

Reputation: 67 575

1

Ruby 1.8, 30 characters

#!ruby -p
gsub(/# +#/){$&.tr" ","@"}

If anyone has an idea why this doesn't work in Ruby 1.9 (tested with 1.9.2p0 and 1.9.2p204), even though the documentation says it should work, let me know!

Ventero

Posted 2011-05-12T20:43:24.543

Reputation: 9 842

That's really weird, adding in $_=$_. to the start of the second line makes it work in 1.9.2 so it's something to do with Kernel.gsub. Rubinius also fails without explicitly adding $_. – Nemo157 – 2011-05-13T06:51:09.470

According to 1.9.1 NEWS log, Kernel#getc, #gsub, #sub are deprecated. – YOU – 2011-05-13T07:25:32.233

1I think you can count this as 30 (27 + 3 for needing the -p flag). The hash-bash and name of the interpreter doesn't count. – Caleb – 2011-05-18T10:55:44.297

1

Python, 95 92 bytes

for s in S.split('\n'):b=s.find('#');e=s.rfind('#');print s[:b]+s[b:e].replace(' ','@')+s[e:]

0b1t

Posted 2011-05-12T20:43:24.543

Reputation: 91

0

Jelly, 15 bytes

Ỵ”@ẹ”#ṂrṀḟƲ$¦€Y

Try it online!

Erik the Outgolfer

Posted 2011-05-12T20:43:24.543

Reputation: 38 134

0

Pip, 15 bytes

aR:`#.*#`_TRs'@

Takes input as a multiline string via command-line argument: Try it online! (Alternately, specify the -rn flags and change the first a to g, and you can give input via stdin: Try it online!)

Same idea as the Retina answer: replace every match of the regex #.*# with the result of transliterating space to @ in the match. Pip can't match Retina's terseness for a pure regex problem--but it's not everyday that you can tie with Jelly, after all.

DLosc

Posted 2011-05-12T20:43:24.543

Reputation: 21 213

0

Python, 108 106 92 bytes

import re
n=1
while n: S,n=re.subn('# +#',lambda m:'#'+'@'*len(m.group(0)[2:])+'#',S)
print S

0b1t

Posted 2011-05-12T20:43:24.543

Reputation: 91

0

Javascript, 107 bytes

var f=function(x){return x.replace(/# +#/g, function(x){return "#"+new Array(x.length-1).join("@")+"#";})};

Ungolfed:

var f = function(x) {
    return x.replace(/# +#/g, function(x){
        return "#" + new Array(x.length - 1).join("@") + "#";
    })
};

BobTheAwesome

Posted 2011-05-12T20:43:24.543

Reputation: 509

I recommend that you (1) post a normally formatted version of your answer so it is easier to read and follow along and (2) look into to ES6... it could save you a lot of characters with your functions. – SirPython – 2015-03-06T23:26:30.223

I'll post a normal version, but I'm not a ES6-type person. – BobTheAwesome – 2015-03-06T23:58:35.447

@BobTheAwesome Why did you just suggest this edit?

– Tim – 2015-05-17T20:02:48.463

Oh goodness, I was attempting to fix the test-case error but I have this extension enabled in chrome, if you know xkcd. Sorry about that.

– BobTheAwesome – 2015-05-18T00:07:51.323

Besides the ES6 stuff: you don't need the space after the comma, you don't need the space after the second return, and you can remove the two semicolons, and it can just be function f(x)... or f=function(x)... – Zacharý – 2018-07-01T15:37:18.117