17
\$\begingroup\$

Given a multi-line string as input containing characters "|", "_" and " " (space), count the number of cells it contains.

A cell is the following structure of 3 characters by 2 lines:

 _
|_|

That is, an underscore on one line (the characters to its right and left don’t matter), and "|_|" right below it.

Two cells can share the same characters. For example, there are 3 cells here:

 _
|_|_
|_|_|

Inputs and outputs

  • You can assume that the input string will only contain the following characters: "|", "_", " ", and "\n".

  • You may take a list of strings as input, or a list of lists of chars, instead of a multi-line string.

  • You may assume that there are at least 2 lines and 3 chars per line.

  • You may pad each line with spaces so that all lines have the same length.

Test cases

Input                               Output

 _
|_|                                 1

___
|_|                                 1

   
|_|                                 0

 _  _  __ __
|_|  _|  _|_||                      2


 _
|_|_
|_|_|                               3

 _
| |_
|_|_|                               1

 _
|_|_
|___|                               1

 _ _
|_|_|
|_|_|                               4

Scoring

This is , so the shortest answer in bytes wins.

\$\endgroup\$
7
  • \$\begingroup\$ Can we assume the input has at least 2 rows and 3 columns? \$\endgroup\$
    – Adám
    Jul 20, 2022 at 7:56
  • \$\begingroup\$ @Adám Yes, edited the challenge. \$\endgroup\$
    – Fatalize
    Jul 20, 2022 at 7:58
  • \$\begingroup\$ Can the input be taken as an array? e.g. ["_","\n",...] \$\endgroup\$
    – oeuf
    Jul 20, 2022 at 9:16
  • \$\begingroup\$ @oeuf sure, Mr Egg. \$\endgroup\$
    – Fatalize
    Jul 20, 2022 at 9:50
  • 1
    \$\begingroup\$ May we have a trailing newline in the input? For example, " _ \n|_|\n" for input #1. \$\endgroup\$
    – chunes
    Jul 20, 2022 at 10:10

14 Answers 14

10
\$\begingroup\$

05AB1E, 18 16 14 13 bytes

Ç°·üö7%J»232¢

Try it online!

Explanation

Ç          convert each character to its ASCII code
°          map each number to 10**x
·          times two
üö         for each consecutive pair of rows, convert the number as a number in 
           a base of the next number
7%         modulo 7
J          join each row into a string of numbers
»          join the rows together with a newline
232        push the string "232" (pushing it as a compressed number doesn't work due to a bug)
¢          and count how many times it appears in the string of digits
Characters ASCII codes 2 * 10^first number converted from base-2*10^second number, mod 7
32, 32 4
_ 32, 95 4
| 32, 124 2
_ 95, 32 4
_ _ 95, 95 3
_ | 95, 124 2
| 124, 32 1
| _ 124, 95 1
| | 124, 124 2
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Pretty annoying that this bug still hasn't been fixed and that § is necessary here. :/ But nice approach regardless! \$\endgroup\$ Jul 20, 2022 at 10:24
8
\$\begingroup\$

APL (Dyalog Unicode), 23 bytes

Anonymous tacit prefix function. Takes character matrix as argument.

≢∘⍸{'_||_'≡2↓,¯1⌽⍵}⌺2 3

Try it online!

{}⌺2 3 on each 2-by-3 submatrix:
   _
  |_|

¯1⌽⍵ rotate the columns cyclically one step to the left
   _
  ||_

, ravel (flatten)
   _||_

2↓ drop the first two elements
  _||_

'_||_'≡ does the string match?

≢∘⍸ count the indices where true

\$\endgroup\$
1
  • \$\begingroup\$ @Fatalize Thanks. Fixed. \$\endgroup\$
    – Adám
    Jul 20, 2022 at 10:38
7
\$\begingroup\$

Python 3, 69 bytes

lambda a:sum(c+a[n+a.find('\n'):][:3]=='_|_|'for n,c in enumerate(a))

Try it online!

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

Factor + math.unicode, 66 bytes

[| s | "_"s "|_|"s [ start-all* ] 2bi@ 10 s index v-n ∩ length ]

Attempt This Online!

Input is a multiline string padded with spaces so each line is the same length. This answer relies on there being a trailing newline in the input; if that is not allowed, let me know and I will change my answer.

It finds the starting indices of (possibly overlapping) subsequences "_" and "|_|", subtracts the index of the first newline from the "|_|" indices, takes the intersection between the two sequences of indices, and returns the length of that.

\$\endgroup\$
3
\$\begingroup\$

05AB1E, 21 20 bytes

€ü3øεü2ε€ÁJ„_|ºÅ¿]˜O

Input as a right-padded list of lines.

-1 byte using the rotate approach from @Adám's APL (Dyalog Unicode) answer

Try it online or verify all test cases.

€ÁJ„_|ºÅ¿]˜O could alternatively be ćÅs«]˜„|_2×¢ for the same byte-count:
Try it online or verify all test cases.

Explanation:

€                 # Map over each inner string of the (implicit) input-list:
 ü3               #  Create overlapping triplets
   ø              # Zip/transpose; swapping rows/columns
    ε             # Map over each inner list:
     ü2           #  Create overlapping pairs
       ε          #  Map over each pair of strings:
        €         #   Map over each string:
         Á        #    Rotate its characters once towards the right
          J       #   Join the two strings together
           „_|    #   Push string "_|"
              º   #   Mirror it to "_||_"
               Å¿ #   Check if the string ends with "_||_"
    ]             # Close the nested maps
     ˜            # Flatten the list of pairs
      O           # Sum
                  # (which is output implicitly as result)
        ć         #   Extract head ([a,b] to [b] and a with `a` on top)
         Ås       #   Pop this head, and leave just its middle character
           «      #   Append it to the string in the remainder-list
    ]             # Close the nested maps
     ˜            # Flatten the list of list of wrapped strings
      „|_         # Push string "|_"
         2×       # Double it to "|_|_"
           ¢      # Count how many "|_|_" are in the list
                  # (which is output implicitly as result)
\$\endgroup\$
3
\$\begingroup\$

Retina 0.8.2, 37 bytes

&`(?<=(.)*)._.*¶(?<-1>.)*(?(1)^)\|_\|

Try it online! Link is to test suite that takes double-spaced test cases. Explanation: The lookbehind calculates the column that the left | should be in, then the arbitrary character above it is matched, then a _, then a .NET balancing group is used to advance the match to the corresponding column on the next line, then then |_| is matched. The & stage modifier is used to allow the matches to overlap.

\$\endgroup\$
3
\$\begingroup\$

x86-64 machine code, 31 bytes

31 F6 6A FF 59 B0 0A F2 AE AE 8B 57 FD 8A 14 0F 81 FA 5F 7C 5F 7C 75 02 FF C6 AE 76 ED 96 C3

Try it online!

Following the standard calling convention for Unix-like systems (from the System V AMD64 ABI), this takes the address of a null-terminated byte string in RDI, and returns the number of cells in EAX. This requires the lines to be padded to the same length.

In assembly:

f:  xor esi, esi        # Set ESI to 0. ESI will count the cells.
    push -1; pop rcx    # Set RCX to -1.
    mov al, '\n'        # Set AL to the ASCII code of the line feed.
    repne scasb         # Repeatedly compare AL with a byte from the string,
                        #  advancing the pointer each time, until they match.
                        #  Also count down RCX each time.  This consumes the first line
                        #  and makes RCX -(linelength+1), with linelength including \n.
    scasb               # Make one more comparison, advancing RDI once more.
r:  mov edx, [rdi-3]    # Load bytes from addresses RDI-3 to RDI into EDX.
    mov dl, [rdi+rcx]   # Replace the first of those bytes with one at address RDI+RCX,
                        #  the position in the previous line above the third byte.
    cmp edx, '_' | '|'<<8 | '_'<<16 | '|'<<24   # Compare EDX with the cell's bytes.
    jne s               # Jump to skip if they are not equal.
    inc esi             # (If equal) Add 1 to ESI.
s:  scasb               # Compare AL with a byte from the string; advance the pointer.
    jbe r               # Jump back, to repeat, if AL ≤ that byte (false only for 0).
    xchg esi, eax       # Switch the total from ESI into EAX.
    ret                 # Return.
\$\endgroup\$
3
\$\begingroup\$

Vyxal, 19 17 bytes

C6+¨pe11%ṅ⁋3l⁺↔SO

Try it online or verify test cases.

-2 bytes thanks to Command Master

\$\endgroup\$
1
  • \$\begingroup\$ another approach I found which might work better in Vyxal - \$ (6+a)^{6+b} \mod 11 \$ with a, b char codes, and then you look for 121 \$\endgroup\$ Jul 21, 2022 at 18:19
2
\$\begingroup\$

J, 30 bytes

[:+/@,2 3('._.\|_\|'rxE,);._3]

Attempt This Online!

+1 thanks to Neil for spotting a subtle bug

  • 2 3...;._3] Looks at all 2 x 3 squares
  • ('._.\|_\|'rxE,) Checks if the flatten regex matches the required pattern
  • [:+/@, Sums the matches
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You need a leading . in your regex otherwise it will match __|/_||. \$\endgroup\$
    – Neil
    Jul 20, 2022 at 9:58
2
\$\begingroup\$

Ruby, 78 bytes

->l{a,*l=l;g=0;l.sum{|b|w=a.chars.count{"#{b[g,3]}#{a[g+=1]}"=="|_|_"};a=b;w}}

Try it online!

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

lin, 54 bytes

2`xp"`,*3`xp \; `'"`', \+ `/
`,* `flat `_`"._.\|_\|"?t

Try it here! Takes a list of equal-sized space-padded strings.

For testing purposes, the code below auto-converts a space-padded multiline string:

\@..
 _  _  __ __  
|_|  _|  _|_||
@ >ls ; outln
2`xp"`,*3`xp \; `'"`', \+ `/
`,* `flat `_`"._.\|_\|"?t

Explanation

Prettified code:

2`xp ( `,* 3`xp \; `' ) `', \+ `/
`,* `flat `_` "._.\|_\|"?t
  • 2`xp (...) `', pairwise flatmap...
    • `,* 3`xp \; `' zip and triplet-wise map...
      • `,* `flat `_` zip, flatten, convert to string
      • "._.\|_\|"?t check if matches regex /._.\|_\|/
  • \+ `/ sum
\$\endgroup\$
2
\$\begingroup\$

MATL, 21 20 bytes

Ji6\^[aJa;0J0]_Z+4=z

Input is a 2-dimensional char array (rows should be righty-padded with spaces so that they have the same length).

Try it online! Or verify all test cases (this displays each input together with output, for convenience).

How it works

Modulo 6 is applied to (the ASCII code of) the chars in the input, which gives 5 for _, 4 for | and 2 for . Element-wise exponentiation with the imaginary unit j respectively gives j, 1 and -1.

Two-dimensional convolution is then used to detect the desired pattern, using the matrix [-1, j, -1; 0, j, 0] as kernel (note that convolution flips the kernel in both directions). The pattern is detected whenever the convolution gives exactly 4. Thus the final result is the number of times that 4 appears in the convolution output.

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

Charcoal, 28 bytes

WS⊞υιIΣEυ∧κLΦ⌕Aι|_|⁼_§§υ⊖κ⊕λ

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

WS⊞υι

Input the strings into an array.

   υ                      Array of strings
  E                       Map over strings
     κ                    Current index
    ∧                     Logical And
        ⌕A                All overlapping matches of
           |_|            Literal string `|_|`
          ι               In current string
       Φ                  Filtered where
                  υ       Array of strings
                 §        Indexed by
                    κ     Outer index
                   ⊖      Decremented
                §         Indexed by
                      λ   Current match position
                     ⊕    Incremented
              ⁼           Is equal to
               _          Literal string `_`
      L                   Take the length
 Σ                        Take the sum
I                         Cast to string
                          Implicitly print
\$\endgroup\$
0
\$\begingroup\$

Dyalog APL, 23 bytes

≢∘⍸1↓'|_|'∘⍷∧¯1⊖1⌽'_'∘=

Attempt This Online!

This is an alternative to Adám’s ⌺-based solution that is exactly as long but quite a bit faster:

      f←≢∘⍸{'_||_'≡2↓,¯1⌽⍵}⌺2 3
      g←≢∘⍸1↓'|_|'∘⍷∧¯1⊖1⌽'_'∘=
      m←(,⍨1e3)⍴' _|'[?1e6⍴3]
      'cmpx'⎕CY'dfns'
      cmpx'f m' 'g m'
  f m → 2.1E0  |    0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  g m → 4.0E¯3 | -100%                                         

The basic idea is to find where the top parts (_) and the bottom parts (|_|) of the squares are, align them, and count how many times they overlap.

We’ll use a modified version of the fifth test case as an example:

      ⎕←m←3 5⍴'__|_||_|_ |_|_|'
__|_|
|_|_ 
|_|_|

First we find where the |_|s are:

      ('|_|'∘⍷)m
0 0 1 0 0
1 0 0 0 0
1 0 1 0 0

The 1s indicate where the |_|s begin. This means that the rightmost two columns will always consist of 0s.

Then we find where the _s are:

      ('_'∘=)m
1 1 0 1 0
0 1 0 1 0
0 1 0 1 0

We need to move the 1s one step to the left and one step downwards to align them with the 1s in the |_| matrix, then AND the two matrices.

We can move the 1s one step to the left by rotating once along the last axis:

      (1⌽'_'∘=)m
1 0 1 0 1
1 0 1 0 0
1 0 1 0 0

The leftmost column wraps around to the right, creating an extra 1 in the rightmost column. Fortunately, this doesn’t matter because the corresponding column in the |_| matrix must consist of 0s, so this column will get masked out anyway.

Next we move the 1s one step downwards by doing a -1 rotate along the first axis:

      (¯1⊖1⌽'_'∘=)m
1 0 1 0 0
1 0 1 0 1
1 0 1 0 0

Now the 1s are aligned, but the bottommost row wraps around to the top, creating extra 1s in the topmost row. This is a problem because the corresponding row in the |_| matrix can contain 1s. We can fix this by dropping the topmost row after ANDing the two matrices:

      ('|_|'∘⍷∧¯1⊖1⌽'_'∘=)m
0 0 1 0 0
1 0 0 0 0
1 0 1 0 0
      (1↓'|_|'∘⍷∧¯1⊖1⌽'_'∘=)m
1 0 0 0 0
1 0 1 0 0

Finally, we count the number of 1s:

      (≢∘⍸1↓'|_|'∘⍷∧¯1⊖1⌽'_'∘=)m
3
\$\endgroup\$

Your Answer

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

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