17
\$\begingroup\$

This is my pet emoji, Billy:

-_-

Emojis don't like to be in the rain, so Billy is sad... Let's draw him an umbrella to make him feel better!

  /\
 /  \
/    \

  -_-

This is good, he is entirely covered by his umbrella! Here is an example where only part of him is covered:

  /\
 /  \
/    \

     -_-

In this case, sections 2 and 3 of his body are exposed to the rain.

Umbrellas come in many shapes and sizes, but they're always made up from a series of ascending slashes / followed by a series of descending backslashes \. For example, these are all valid umbrellas:

  /\
 /  \
/    \

/\

    /\
   /  \
  /    \
 /      \
/        \

And these are not:

/   \

\/

  \
 / \
/   \

 0\
/  \

//\\
/  \

You need to determine which parts of my emoji are exposed to the rain.

Clarifications

  • Your program (or function) will take a 2d string as input. This can be in whatever format is most convenient or natural to your language. An array of strings, an array of arrays of characters, a string with newlines in it etc.

  • You must output which sections of the emoji are exposed to the rain. This can be zero-indexed or one-indexed, as long as you make this clear. Output can be in any reasonable format. If the entire emoji is protected from the rain, output nothing (or an empty array).

  • You can assume that all inputs will have a valid umbrella, and the same emoji: -_-. The emoji will always be on the last line of the input, however their might be several empty lines between the umbrella and the emoji.

  • Everything that isn't part of the umbrella or the emoji will be a space character or newline.

  • The input will be padded with spaces so that the length of each line is the same.

Standard loopholes apply, and the shortest answer in bytes wins!

Test IO:

All of the sample cases will use one-indexing.

  /\
 /  \
/    \

  -_-

Outputs: []

----------------

   /\
  /  \

     -_-

Outputs: [2, 3]

----------------

    /\
   -_-

Outputs: [1]

----------------

     /\
    /  \
   /    \
  /      \
 /        \
/          \




               -_-

Outputs: [1, 2, 3]
\$\endgroup\$
  • 2
    \$\begingroup\$ Can we output the parts of the emoji that are in the rain? i.e. ["_","-"]. \$\endgroup\$ – Rɪᴋᴇʀ Jun 11 '16 at 14:35
  • \$\begingroup\$ If our language supports strings, can we still accept a 2D array of characters? For example, Array in JavaScript has different functions available to it than String does. \$\endgroup\$ – Patrick Roberts Jun 14 '16 at 17:09
  • \$\begingroup\$ @PatrickRoberts Yes, that is acceptable. \$\endgroup\$ – DJMcMayhem Jun 14 '16 at 17:14
  • \$\begingroup\$ @EᴀsᴛᴇʀʟʏIʀᴋ No, you should output the numbers. \$\endgroup\$ – DJMcMayhem Jun 14 '16 at 17:15
  • 1
    \$\begingroup\$ I think you mean emoticon. Dry emoji would be 🔥 (or ☂️ I suppose) \$\endgroup\$ – NH. May 9 at 19:01

11 Answers 11

8
\$\begingroup\$

05AB1E, 18 17 15 bytes

Code:

|…-_-123:)ø€J€ï

Explanation:

|                  # Take all input as a list of strings.
 …-_-              # 3-char string, which results into "-_-".
     123:)         # Replace "-_-" with 123.
          ø        # Zip, resulting into the columns of the 2D array.
           €J      # Join each of them.
             ە    # For each, convert to integer. If this is not possible, it will ignore
                     the result.
                   # Implicitly output the array.

Uses the CP-1252 encoding. Try it online! (make sure to pad all lines with spaces to the same length..

\$\endgroup\$
5
\$\begingroup\$

JavaScript (ES6), 95 bytes

a=>[...a[n=0]].map((_,i)=>a.map(s=>(c=s[i])>"-"&c<"_"?p=1:n+=!++c,p=0)|p<!c&&o.push(n),o=[])&&o

Input should be an array of strings, with each line padded with spaces to form a square. Output is an array of 1-indexed numbers.

Explanation

var solution =

a=>
  [...a[n=0]].map((_,i)=>  // n = current index of emoji, for each column i of input
    a.map(s=>              // for each line s
      (c=s[i])             // c = character in column
      >"-"&c<"_"?p=1       // p = 1 if column is protected from rain
      :n+=!++c,            // increment n if emoji character found, c = 1 if last line
                           // contained a space in the current column
      p=0
    )
    |p<!c&&o.push(n),      // if the emoji is not protected in the current column
    o=[]
  )
  &&o
<textarea id="input" rows="6" cols="40">   /\   
  /  \  
        
     -_-</textarea><br />
<button onclick="result.textContent=solution(input.value.split('\n'))">Go</button>
<pre id="result"></pre>

\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 92 bytes

a=>a.map(s=>s.replace(/\S/g,(c,i)=>c>'-'&c<'_'?u[i]=3:++n&u[i]||r.push(n)),n=0,u=[],r=[])&&r

Accepts a ragged array of lines and returns a 1-indexed result. Explanation:

a=>a.map(               Loop through all lines
 s=>s.replace(/\S/g,    Loop through all non-whitepsace
  (c,i)=>c>'-'&c<'_'    If it's part of the umbrella
   ?u[i]=3              Mark that column as dry
   :++n&                Add 1 to the emoji index
     u[i]||             If the column is not dry
      r.push(n)         Add the emoji index to the result
  ),n=0,u=[],r=[]       Initialise variables
 )&&r                   Return result
\$\endgroup\$
3
\$\begingroup\$

Java 8 lambda, 241 218 201 191 185 184 (or 161) characters

Because ya know, also Java needs dry emojis.

import java.util.*;f->{int e,i=e=-1,c,l=f.length-1;while(++e<f[l].length&&f[l][e]!=45);List p=new Stack();l:for(;++i<3;){for(char[]r:f)if((c=r[e+i])==47|c==92)continue l;p.add(i);}return p;}

It returns an ArrayList a HashSet a Stack containing the parts of the emoji which are exposed to the rain (indexing starts at 0). The whole thing unwrapped:

import java.util.*;

public class Q82668 {
    static List isEmojiDryRevE(char[][] fieldToCheck) {
        int emojiStart, i = emojiStart = -1, j, rows = fieldToCheck.length - 1;

        while (++emojiStart < fieldToCheck[rows].length && fieldToCheck[rows][emojiStart] != 45)
            ;

        List parts = new Stack();
        emojiLoop: for (; ++i < 3;) {
            for (j = -1; ++j < rows;) {
                if (fieldToCheck[j][emojiStart + i] > 46) {
                    // umbrella part found
                    continue emojiLoop;
                }
            }
            // no umbrella part found
            parts.add(i);
        }
        return parts;
    }
}

Updates

I did some basic golfing. This includes putting the declarations together, compare with the ascii values to save some characters and shorten the loops.

Thanks to @user902383 for pointing out my dump mistake using ArrayLists instead of just Lists. I replaced the ArrayLists/Lists with HashSets/Sets which saves some more characters. Also thanks for his tip to use a foreach loop in the inner loop! Through that change I am able to create a variable for the index of the last grid row which shortens it a bit more. Overall 17 characters have been saved!

@KevinCruijssen suggested to remove the generics in the initialization, I went one step further: Remove all the generics. This saves another 10 characters.

I switched back from the foreach loop to the for loop. This makes it possible to skip comparing the last line which in turn allows me to shorten the comparison of the ascii values. In this context only '/', '\' and '_' have an ascii value over 46. If we don't check the last line we can use a > 46 check instead to checks for the actual value.

Thanks again to @user902383 for showing me that I use a lambda and can use List+Stack instead of Set+HashSet to shave off another character.


String returning version

@user902383 pointed out I can instead just create a String with the digits. This sounds very cheaty but others seem to solve it this way so here is a shorter version using a String return:

f->{int e,i=e=-1,c,r=f.length-1;while(++e<f[r].length&&f[r][e]!=45);String p="";l:for(;++i<3;){for(char[]o:f)if((c=o[e+i])==47|c ==92)continue l;p+=i;}return p;}

Ungolfed:

public class Q82668 {
    public static String isEmojiDryRevD(char[][] fieldToCheck) {
        int emojiStart, i = emojiStart = -1, c, rows = fieldToCheck.length - 1;

        while (++emojiStart < fieldToCheck[rows].length && fieldToCheck[rows][emojiStart] != 45)
            ;

        String parts = "";
        emojiLoop: for (; ++i < 3;) {
            for (char[] row : fieldToCheck) {
                if ((c = row[emojiStart + i]) == 47 | c == 92) {
                    // umbrella part found
                    continue emojiLoop;
                }
            }
            // no umbrella part found
            parts += i;
        }
        return parts;
    }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ you broke rule number 1 always program to an interface, if you use List instead ArrayList you can save 5 bytes \$\endgroup\$ – user902383 Jun 14 '16 at 13:20
  • 1
    \$\begingroup\$ I think inner for loop could be replaced by foreach loop which should give you additional couple of bytes \$\endgroup\$ – user902383 Jun 14 '16 at 13:51
  • 1
    \$\begingroup\$ Not entirely sure, but =new HashSet<>(); can most likely be golfed to =new HashSet();. \$\endgroup\$ – Kevin Cruijssen Jun 14 '16 at 14:52
  • 1
    \$\begingroup\$ @Frozn Why wouldn't it be allowed? I know the compiler produces a warning, which happens a lot during code-golfing. What I'm not sure of is if your code still works the same, haven't tested it. If it does, than removing the <> saves you 2 bytes. :) \$\endgroup\$ – Kevin Cruijssen Jun 14 '16 at 15:00
  • 2
    \$\begingroup\$ @Frozn you would be right in good old java, but now we have lambda, and in lambda notation you don't specify type. hence you have Set(3) HashSet(7) against List(4) and Stack(5). \$\endgroup\$ – user902383 Jun 14 '16 at 15:50
3
\$\begingroup\$

V, 20 19 bytes (non-competing)

G^R123?/
f\GddHÍó

Alternate, competing version (21 bytes):

G^R123?/
f\òjòddHÍó

Try it online! (Note, tryitonline.net uses a slightly old version of V. To compensate for this, it uses this slightly longer version)

Explanation:

G^          "Move to the first non-whitespace character on the last column
  R123<esc> "Replace the emojii with '123'

?/          "Move backwards to the last '/' character
  <C-v>     "Start a blockwise selection
       f\G  "Move the selection to the next '\', and then to the last line
d           "Delete the block selection
 dH         "Delete the umbrella

This alone produces the correct result in 17 bytes. However, it also creates some extra whitespace. I don't mind it, but I don't want to give myself an unfair advantage, so I'm adding two bytes:

Íó          "Remove all whitespace
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 117 112 bytes

s=>s.map(r=>r.map((c,i)=>~'-_'[o='indexOf'](c)&&!s.some(a=>~'/\\'[o](a[i]))?i-r[o]('-'):-1)).pop().filter(n=>~n)

Accepts a ragged array of strings arrays of characters, and returns 0-indexed results.

s=>s.map(     // for each row
  r=>         // row
    r.map(    // for each character
      (c,i)=> // character, index
        ~'-_'[o='indexOf'](c) // if character is part of emoji
        &&                    // and
        !s.some(              // none of the rows have umbrella in this column
          a=>~'/\\'[o](a[i])
        )
        ? // then return 0-index of emoji
          i-r[o]('-')
        : // else return -1
          -1
  )
)
.pop()         // get last element of string array
.filter(n=>~n) // filter out -1s

Demo

f=s=>s.map(r=>r.map((c,i)=>~'-_'[x='indexOf'](c)&&!s.some(a=>~'/\\'[x](a[i]))?i-r[x]('-'):-1)).pop().filter(n=>~n)
i.oninput=()=>o.value=f(i.value.split`\n`.map(r=>r.split``))
i.oninput()
<textarea rows=6 cols=20 id=i>
   /\
  /  \

     -_-</textarea>
<br/>
<input readonly id=o>

\$\endgroup\$
  • \$\begingroup\$ I like your comments! \$\endgroup\$ – sintax Jun 15 '16 at 21:17
2
\$\begingroup\$

Retina, 56 bytes

Byte count assumes ISO 8859-1 encoding.

m`(?<!(?(2)!)^(?<-2>.)*\S(.*¶)+(.)*).(?<=([-_]+))|\D
$.3

Try it online!

This is a single substitution stage, where the regex matches one of the emoji characters, provided that there's a non-space character (i.e. a / or \) somewhere above in the same horizontal position, and then we capture the number of emoji characters up to that point. This match is replaced with the length of that last capture, which gives us the index of this unsheltered emoji character. The regex also contains a |\D to match everything else which gets replaced with nothing at all, so we remove all the other characters.

\$\endgroup\$
  • \$\begingroup\$ Can you explain more how this regex looks above the emoji characters? \$\endgroup\$ – sintax Jun 16 '16 at 19:58
  • 1
    \$\begingroup\$ @sintax It uses balancing groups to count the characters preceding it on its own line. This measures its horizontal position. Then after I've matched the / or \, I'm popping from that group again while matching the stuff preceding that, and then make sure I've completely depleted the group. This basically ensures that the horizontal position of the emoji and the roof character match. \$\endgroup\$ – Martin Ender Jun 16 '16 at 21:35
1
\$\begingroup\$

Pyth, 27 23 bytes

0-indexed.

-m.xsd;.T:R"-_-"s`M3.zd

Try it online!

Explanation

-m.xsd;.T:R"-_-"s`M3.zd

                    .z   all lines of input, as a list
         :R"-_-"s`M3     replace "-_-" by "012" 
                         "012" is generated by s`M3
       .T                transpose, return all columns
                         The sample input becomes:
                           0
                           1
                          /2
                         / 
                         \ 
                         \
 m   d                   for each line:
  .xs                        attempt to convert to integer.
      ;                      if errors, replace to space
-                     d  remove all spaces

History

27 bytes: sM:#"^ *\d"0.T:R"-_-"s`M3.z (Try it online!)

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

Matlab, 43 bytes

@(x)find(sum((x(:,x(end,:)~=' '))~=' ')==1)

This code finds column positions of non-space characters in the final row of the input, sums the number of non-space characters in those columns, and finds where there's only one such character (the emoji's character, un-shielded by umbrella!). This code only returns proper results for well-formed umbrellas (it assumes any character above our emoji is part of a well-formed umbrella).

Here is a bit of utility code for writing test cases and checking my work:

ws = @(x) repmat(' ',1,x);  %  for making strings of spaces
% for writing three-storey umbrellas over an emoji located left-edge at position x
thrht = @(x) strvcat([ws(3) '/\' ws(3); ws(2) '/  \' ws(2); ws(1) '/' ws(4) '\' ws(1); ws(8)], [ws(x-1) '-_-']);
twht = @(x) strvcat([ws(3) '/\' ws(3); ws(2) '/  \' ws(2); ws(8)], [ws(x-1) '-_-']);

Running x = thrht(7) gives

x =

   /\    
  /  \   
 /    \  

      -_-

Or x = twht(0) gives

x =

   /\   
  /  \  

 -_-     
\$\endgroup\$
0
\$\begingroup\$

APL, 31 bytes

{(⍳3)∩,(~∨⌿⍵∊'/\')/+\+\'-_-'⍷⍵}

This takes a character matrix as input.

Tests:

      t1 t2 t3 t4
┌──────┬────────┬──────┬─────────────────┐
│  /\  │   /\   │    /\│     /\          │
│ /  \ │  /  \  │   -_-│    /  \         │
│/    \│        │      │   /    \        │
│      │     -_-│      │  /      \       │
│  -_- │        │      │ /        \      │
│      │        │      │/          \     │
│      │        │      │                 │
│      │        │      │                 │
│      │        │      │                 │
│      │        │      │                 │
│      │        │      │              -_-│
└──────┴────────┴──────┴─────────────────┘
      {(⍳3)∩,(~∨⌿⍵∊'/\')/+\+\'-_-'⍷⍵} ¨ t1 t2 t3 t4
┌┬───┬─┬─────┐
││2 3│1│1 2 3│
└┴───┴─┴─────┘

Explanation:

  • '-_-'⍷⍵: in a matrix of zeroes the size of the input, mark the position of the beginning of '-_-' in the input with a 1.
  • +\+\: Running sum over rows. The first one makes 0 0 0 1 0 0 ... into 0 0 0 1 1 1 ..., the second one then makes it into 0 0 0 1 2 3 ....
  • ⍵∊'/\': mark all occurrences of '/' and '\' in the input with 1s.
  • ∨⌿: or over columns. This marks with an 1 all positions on the last row that are covered by the umbrella.
  • ~: not, because we need the opposite
  • (...)/...: Select all uncovered columns from the running sum matrix from earlier
  • ,: Get a list of all values in the resulting matrix.
  • (⍳3)∩: Intersection between that and 1 2 3 (this gets rid of any selected 0s or higher values, which would be spaces).
\$\endgroup\$
0
\$\begingroup\$

Python 2, 114 111 bytes

def f(a):c=a.find("\n")+1;r=a.rfind;g=lambda i:([i],[])[r("\\")%c>=r("-")%c-2+i>=r("/")%c];print g(0)+g(1)+g(2)

Uses 0 based indexing.

Try it here.

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