21
\$\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\$
8
  • \$\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
    Commented May 12, 2011 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
    Commented May 12, 2011 at 20:55
  • 3
    \$\begingroup\$ Related on Stack Overflow: Code Golf: Running Water. One of LiraNuna's better one, I thought. \$\endgroup\$ Commented May 12, 2011 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
    Commented May 12, 2011 at 21:45
  • \$\begingroup\$ @dmckee: That one wasn't as easy as this though. \$\endgroup\$
    – Joey
    Commented May 12, 2011 at 21:45

15 Answers 15

9
\$\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\$
4
  • \$\begingroup\$ #|@ would be one char shorter \$\endgroup\$
    – YOU
    Commented May 13, 2011 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
    Commented May 13, 2011 at 7:25
  • \$\begingroup\$ @Nabb thanks, discovered something with the empty label \$\endgroup\$
    – asoundmove
    Commented May 13, 2011 at 12:36
  • \$\begingroup\$ I tried sed before, but failed \$\endgroup\$
    – Ming-Tang
    Commented May 13, 2011 at 17:45
8
\$\begingroup\$

Perl, 25

s/# +#/$_=$&;y| |@|;$_/ge
\$\endgroup\$
6
  • \$\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
    Commented May 13, 2011 at 7:25
  • \$\begingroup\$ i dont know perl language, but i can feel its power :) \$\endgroup\$
    – Ant's
    Commented May 13, 2011 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
    Commented May 13, 2011 at 23:24
  • \$\begingroup\$ Don't need the e, like I mentioned elsewhere, for the same reasons. :) \$\endgroup\$
    – Robert P
    Commented May 26, 2011 at 17:55
  • \$\begingroup\$ You can save a couple of bytes on this approach by inlining the change to $& without assigning to $_: s/# +#/$&=~y! !@!r/ge \$\endgroup\$ Commented Jul 21, 2022 at 11:57
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\$
2
  • 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
    Commented May 13, 2011 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
    Commented May 26, 2011 at 17:52
3
\$\begingroup\$

Windows PowerShell, 36 74 138

$input-replace'(?<!^ *) (?! *$)','@'
\$\endgroup\$
3
\$\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\$
2
\$\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\$
3
  • \$\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
    Commented May 13, 2011 at 6:51
  • \$\begingroup\$ According to 1.9.1 NEWS log, Kernel#getc, #gsub, #sub are deprecated. \$\endgroup\$
    – YOU
    Commented May 13, 2011 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
    Commented May 18, 2011 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\$

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

Vyxal, 20 bytes

□⟑Ġvṅḣ$₴:Ṫ\@Ḟ$¤ptJṅ,

Try it Online!

How?

□⟑Ġvṅḣ$₴:Ṫ\@Ḟ$¤ptJṅ,
□                    # All inputs wrapped in a list
 ⟑                   # Open an apply lambda, apply for each:
  Ġvṅ                # Group consecutive identical characters
     ḣ               # Head extract, push a[0], a[1:]
      $              # Swap
       ₴             # Print without a trailing newline
        :Ṫ           # Duplicate and remove the last item
          \@Ḟ        # Replace all spaces with "@"
             $       # Swap
              ¤p     # Prepend an empty string for the case that the list is empty
                t    # Last item
                 J   # Join top two things on the stack together
                  ṅ  # Join by nothing
                   , # Print with trailing newline
\$\endgroup\$
1
\$\begingroup\$

Javascript (ES6), 44 bytes

x=>x.replace(/# +#/g,s=>s.replace(/ /g,"@"))
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice answer :) You can replace (hah!) replaceAll(" ", ... with replace(/ /g,... (removing the space) to save another three bytes too! \$\endgroup\$ Commented Jul 21, 2022 at 13:46
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\$
5
  • \$\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
    Commented Mar 6, 2015 at 23:26
  • \$\begingroup\$ I'll post a normal version, but I'm not a ES6-type person. \$\endgroup\$ Commented Mar 6, 2015 at 23:58
  • \$\begingroup\$ @BobTheAwesome Why did you just suggest this edit? \$\endgroup\$
    – Tim
    Commented May 17, 2015 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\$ Commented May 18, 2015 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\$
    – Adalynn
    Commented Jul 1, 2018 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\$

APL (Dyalog Unicode), 28 bytes

'# +#'⎕R{'@'@(' '∘=)⍵.Match}

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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