15
\$\begingroup\$

Given an ASCII-art shape made of the characters /\|_, your challenge is to return the number of sides it has.

A side is a straight line of one of those, for example:

\
 \
  \

 /
/

|
|
|
|

_____

Are all sides.

For example, this shape:

  ___
 /   \
/_____\

Has four sides. You can assume the input will be a single valid, closed shape - that is, things like this:

/
 _
/ \

 \
/

/_\
\_/
 _   _
/_\ /_\

Will not occur, and the shape will never touch itself, so this is invalid:

  /\/\
 / /\ \
/ /__\ \
|______|

Testcases:

 /\
/__\ -> 3

 ________
/        \
|_________\  -> 5

___
|_| -> 4

/\/\/\/\/\
|________| -> 13

 _   _
| |_| |
|  _  | -> 12
|_| |_|
          
         /\
        /  \
   /\  /    \    /\
  /  \/      \  /  \
 /            \/    \
/____________________\ -> 7

   _
  / |
 _| |
/___/ -> 8
\$\endgroup\$
1
  • \$\begingroup\$ 10/10 testcases, especially the last one \$\endgroup\$
    – okie
    Jan 18 at 3:00

4 Answers 4

7
\$\begingroup\$

J, 49 bytes

-1 thanks to Jonah

This answer has 6 sides.

[:+/@,i.@4(1==-{&(0 1,1,.i:1)@[|.!.0=)"{'_/|\'&i.

Try it online!

  • '_/|\'&i. Map walls to 0…4.
  • i.@4 For each possible wall …
  • |.!.0= shift the corresponding bitmap …
  • {&(0 1,1,.i:1)@[ into the direction the wall points to.
  • 1==- Subtract this from the original bitmap and keep the 1s.
  • [:+/@, Count the 1s.

Example for the _-lines in

____
|__|   original
 ____
 |__|  shifted by 1 into a direction _ points to

X....  spots where _ is in the original image,
.X...  but not in the shifted one.

Two Xs, thus two _-lines.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Very clever solution! Might want to add a picture of a shape before and after expansion, to show off the key central idea visually. \$\endgroup\$
    – Jonah
    Jan 18 at 1:43
  • \$\begingroup\$ @Jonah thanks & done! \$\endgroup\$
    – xash
    Jan 18 at 1:53
  • 1
    \$\begingroup\$ 0>. -> 1= seems to work for -1 \$\endgroup\$
    – Jonah
    Jan 18 at 3:02
3
\$\begingroup\$

Retina 0.8.2, 94 bytes

(?<=(.)*)(\|(?=.*¶(?<-1>.)*\|)|\\(?=.*¶(?<-1>.)*.\\)|/(?=.*¶(?<-1>.)*(?<-1>/)))(?(1)^)
 
_+|\S

Try it online! Link includes test suite that takes double-spaced test cases. Explanation:

(?<=(.)*)(\|(?=.*¶(?<-1>.)*\|)|\\(?=.*¶(?<-1>.)*.\\)|/(?=.*¶(?<-1>.)*(?<-1>/)))(?(1)^)
 

Match any of |, \ or / with the corresponding symbol on the next line, but indented to line up with it and replace it with a space. (This is slightly golfier than using negative lookaheads.)

_+|\S

Count any remaining non-whitespace, except a run of _ only counts as one side.

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 42 bytes

WS⊞υι≔⪫υ⸿θPθFθ⎇№⁺ ⊟KD²✳⊕|⌕/|\ι⁴ιψι≔LKAθ⎚Iθ

Try it online! Link is to verbose version of code. Takes input as a list of newline-terminated strings. Explanation:

WS⊞υι

Input the list of strings.

≔⪫υ⸿θ

Join them with carriage returns.

Pθ

Print the result to the canvas without moving the cursor.

Fθ

Loop over each character.

⎇№⁺ ⊟KD²✳⊕|⌕/|\ι⁴ιψι

If the character is a space or equal to the adjacent character in the appropriate direction (E, SE, S or SW as appropriate), then erase it, otherwise reprint it.

≔LKAθ

Count the number of remaining characters on the canvas.

⎚Iθ

Clear the canvas and output the result.

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

Python3, 598 bytes:

import re
def f(b,c,l,s=[]):
 k=0
 for u,v in{'/':[[-1,1],[1,-1]],'\\':[[1,1],[-1,-1]]}[l]:
  if(x:=c[0]+u)>=0 and(y:=c[1]+v)>=0 and(x,y)not in s:
   try:
    if b[x][y]==l:k=1;yield from f(b,(x,y),l,s+[(x,y)])
   except:1
 if k==0:yield tuple(sorted(s))
def g(b):
 b=[*filter(None,b.split('\n'))]
 e=enumerate;S=set;R=sum;L=len
 t=[((x,y),j) for x,a in e(b)for y,j in e(a)if j=='/'or j=='\\']
 n={m for i in t for m in f(b,i[0],i[-1],[i[0]])}
 return R(not any(S(i)&S(j)==S(i)and L(j)>L(i)for j in n)for i in n)+R(L(re.findall('_+',i))for i in b)+R(L(re.findall('\|+',''.join(i)))for i in zip(*b))

Very simple algorithm: find the number of diagonal edges (using f), and then the number of horizontal and vertical edges (using re.findall)

Try it online!

\$\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.