Find the coastline

14

Your task is to find the length of the coastline of a map of islands provided in an ASCII map. The input map will consist of 1 or more # characters that indicate land, and spaces which indicate water. The coastline is considered to be any edge between land and water, including inland lakes and islands.

Your solution should be a complete program that reads in a file, a string or an array of strings, and outputs a single integer to the screen or stdout. Each input line may have leading or trailing space, and zero or more hash characters. The borders of the map are assumed to be space (water).

Lines may be of different lengths.

Examples:

Input:
##
##
Output: 8

Input:
    ###    ###
  #####     #
   ##
Output: 26

Input:
  #####
  #   #
  # # #
  #   #
  #####
Output: 36

This is code golf, so the smallest byte count wins.

Logic Knight

Posted 2016-02-05T23:56:22.610

Reputation: 6 622

Can we assume that the input is padded to a rectangle with spaces? – Martin Ender – 2016-02-06T10:14:43.007

Why a complete program? Usually functions are also allowed, and I don't see a good reason for this challenge to be restrictive. – nimi – 2016-02-06T11:22:34.780

@MartinBüttner, yes. I was hoping that the "The borders of the map are assumed to be space (water)" covered that. Let me know if I should make that clearer. – Logic Knight – 2016-02-06T12:17:23.117

@nimi, I understand your concern, but as the challenge is 12 hours old, there are 4 answers, and other people may be working on it right now, I am reluctant to change it. – Logic Knight – 2016-02-06T12:25:21.123

@CarpetPython no I mean whether we can assume that all lines of the input have the same length. – Martin Ender – 2016-02-06T12:54:03.167

@MartinBüttner, I see. I have edited the question to make this explicit. Lines may be of different lengths. – Logic Knight – 2016-02-06T14:49:40.897

Answers

14

Snails, 8 bytes

A
\#o!\#

​​​​​The A option means to count all matching paths rather which starting points a match succeeds from. \# consumes a #, o turns in a cardinal direction, and !\# is a negative assertion which succeeds if there is not a # in front of us.

feersum

Posted 2016-02-05T23:56:22.610

Reputation: 29 566

4

Pyth - 25 23 bytes

First it pads the input to a rect. Then counts the occurrences of " #" over the 4 permutations of transpositions and reversals of the input+space.

/ssm_B++;j;d;CB.t.zd" #

Try it online here.

Maltysen

Posted 2016-02-05T23:56:22.610

Reputation: 25 023

How can that detect coastlines on the edge of the input? – feersum – 2016-02-06T00:06:24.740

I pad it first, I forgot to say that. – Maltysen – 2016-02-06T00:06:56.970

3

ES6, 123 115 114 bytes

a=>a.map((s,i)=>s.replace(/#/g,(h,j)=>r+=(s[j-1]!=h)+(s[j+1]!=h)+((a[i-1]||'')[j]!=h)+((a[i+1]||'')[j]!=h)),r=0)|r

Edit: Saved 9 bytes thanks to @edc65.

Neil

Posted 2016-02-05T23:56:22.610

Reputation: 95 035

I'm uncertain about this beeing a complete program that writes to stdout or on screen. Apart from this: you should use param of the replace function. a=>['',...a,''].map((s,i,a)=>s.replace(/#/g,(_,j)=>r+=(s[j-1]!=_)+(s[j+1]!=_)+(a[i-1][j]!=_)+(a[i+1][j]!=_)),r=0)|r – edc65 – 2016-02-06T10:15:09.357

And better a=>a.map((s,i)=>s.replace(/#/g,(_,j)=>r+=(s[j-1]!=_)+(s[j+1]!=_)+((a[i-1]||'')[j]!=_)+((a[i+1]||'')[j]!=_)),r=0)|r – edc65 – 2016-02-06T10:18:40.837

@edc65 Ah, of course, I lose two bytes by having to capture the inner array value. Also, nice catch on that replace parameter. – Neil – 2016-02-06T11:00:08.977

2

MATL, 42 bytes

c2\FTFt!*Y+2*qFTFtl-4lhhbvv_2X53$Y+t0>)s2/

This accepts the input as a cell array of strings, of the form

{'#####', '#   #', '# # #', '#   #', '#####'}

It first converts the input to a 2D char array, padding with spaces, and then to a matrix of zeros and ones. 2D-convolution is then applied twice, with two different masks: first for expanding the matrix, second for detecting edges.

Try it online!

Luis Mendo

Posted 2016-02-05T23:56:22.610

Reputation: 87 464

0

Japt, 22 19 bytes

4o £UzX è"#%s|#$} x

Assumes the input is padded with spaces to form a rectangle. Test it online!

How it works

          // Implicit: U = input string, S = a space
4o £    } // Create the array [0,1,2,3], and map each item X to:
UzX       //  Rotate U by 90 degrees X times.
è"#%s|#$  //  Count the number of "#"s followed by a space, newline, or end-of-string.
x         // Sum the resulting array.

ETHproductions

Posted 2016-02-05T23:56:22.610

Reputation: 47 880