19
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ This seems a bit easy. I think we should also have to display the number of lake units @ that were filled in. \$\endgroup\$ – mellamokb May 12 '11 at 20:53
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ – Joey May 12 '11 at 20:55
  • 3
    \$\begingroup\$ Related on Stack Overflow: Code Golf: Running Water. One of LiraNuna's better one, I thought. \$\endgroup\$ – dmckee May 12 '11 at 21:41
  • 1
    \$\begingroup\$ So 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. \$\endgroup\$ – mellamokb May 12 '11 at 21:45
  • \$\begingroup\$ @dmckee: That one wasn't as easy as this though. \$\endgroup\$ – Joey May 12 '11 at 21:45

12 Answers 12

8
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ #|@ would be one char shorter \$\endgroup\$ – YOU May 13 '11 at 6:34
  • 2
    \$\begingroup\$ You 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. \$\endgroup\$ – Nabb May 13 '11 at 7:25
  • \$\begingroup\$ @Nabb thanks, discovered something with the empty label \$\endgroup\$ – asoundmove May 13 '11 at 12:36
  • \$\begingroup\$ I tried sed before, but failed \$\endgroup\$ – Ming-Tang May 13 '11 at 17:45
  • \$\begingroup\$ @Keith, thanks for the award. \$\endgroup\$ – asoundmove May 21 '11 at 5:09
7
\$\begingroup\$

Perl, 25

s/# +#/$_=$&;y| |@|;$_/ge
\$\endgroup\$
  • \$\begingroup\$ I added a character count. Please look whether it's actually correct, as it might need to include some interpreter flags (-p maybe?). \$\endgroup\$ – Joey May 13 '11 at 7:25
  • \$\begingroup\$ i dont know perl language, but i can feel its power :) \$\endgroup\$ – Ant's May 13 '11 at 13:33
  • \$\begingroup\$ 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? \$\endgroup\$ – asoundmove May 13 '11 at 23:24
  • \$\begingroup\$ Don't need the e, like I mentioned elsewhere, for the same reasons. :) \$\endgroup\$ – Robert P May 26 '11 at 17:55
6
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ Except 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. \$\endgroup\$ – asoundmove May 13 '11 at 23:27
  • \$\begingroup\$ 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. :) \$\endgroup\$ – Robert P May 26 '11 at 17:52
3
\$\begingroup\$

Windows PowerShell, 36 74 138

$input-replace'(?<!^ *) (?! *$)','@'
\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ 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 $_. \$\endgroup\$ – Nemo157 May 13 '11 at 6:51
  • \$\begingroup\$ According to 1.9.1 NEWS log, Kernel#getc, #gsub, #sub are deprecated. \$\endgroup\$ – YOU May 13 '11 at 7:25
  • 1
    \$\begingroup\$ I 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. \$\endgroup\$ – Caleb May 18 '11 at 10:55
1
\$\begingroup\$

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:]
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

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("@") + "#";
    })
};
\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – SirPython Mar 6 '15 at 23:26
  • \$\begingroup\$ I'll post a normal version, but I'm not a ES6-type person. \$\endgroup\$ – BobTheAwesome Mar 6 '15 at 23:58
  • \$\begingroup\$ @BobTheAwesome Why did you just suggest this edit? \$\endgroup\$ – Tim May 17 '15 at 20:02
  • \$\begingroup\$ 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. \$\endgroup\$ – BobTheAwesome May 18 '15 at 0:07
  • \$\begingroup\$ 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)... \$\endgroup\$ – Zacharý Jul 1 '18 at 15:37
0
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

Jelly, 15 bytes

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

Try it online!

\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.