| Bytes | Lang | Time | Link |
|---|---|---|---|
| 008 | Vyxal | 241116T005055Z | emanresu |
| 036 | Haskell + hgl | 241120T185245Z | Wheat Wi |
| nan | Scala 3 | 241116T033427Z | 138 Aspe |
| 189 | C# .NET Core | 241118T223647Z | Pepik |
| 070 | APL+WIN | 241120T114624Z | Graham |
| 124 | C++ clang | 241118T182557Z | ioveri |
| 022 | Pip r | 241119T192347Z | DLosc |
| 030 | Uiua | 241119T030549Z | ErikDaPa |
| 050 | Perl 5 F | 241115T210837Z | Xcali |
| 012 | 05AB1E | 241118T085917Z | Kevin Cr |
| 079 | Python + NumPy | 241116T073709Z | Albert.L |
| 016 | Japt | 241115T173018Z | Shaggy |
| 092 | Ruby | 241115T172048Z | Jordan |
| 094 | R | 241117T045504Z | Eonema |
| 079 | Ruby | 241117T004341Z | Level Ri |
| 069 | JavaScript ES6 | 241115T211329Z | Arnauld |
| 122 | Python | 241115T181150Z | movatica |
| 026 | Charcoal | 241115T170848Z | Neil |
| 018 | K ngn/k | 241115T224747Z | ovs |
| 014 | Jelly | 241115T171040Z | Jonathan |
| 097 | Retina | 241115T170507Z | Neil |
Vyxal, 8 bytes
C<v¦+3Ḋ∑
I/O as a matrix of charcodes. Inspired by ovs's K answer (and then backported to that to save two bytes)
∑ # Over each line, sum the results of
C< # For each number, check if it's not a space
C # by checking if if casting it to a char
< # results in a larger value - ' ' < '3', '<'/'>' > '6'
v¦ # Take the cumulative sum of these
+ # Add to the original charcodes
3Ḋ # And check if it's divisible by 3
As to why this works, here's an example:
- Given
><>><> <><([62 60 62 62 60 62 32 60 62 60 32 32]) - Mask of nonspaces i.e. fish characters:
[1 1 1 1 1 1 0 1 1 1 0 0] - Cumulative sum of that:
[1 2 3 4 5 6 6 7 8 9 9 9](modulo 3:[1 2 0 1 2 0 0 1 2 0 0 0])- First char of fish -> 1 (modulo 3), second char -> 2, last char -> 0, space -> 0
- input charcodes modulo 3:
[2 0 2 2 0 2 2 0 2 0 2 2]>-> 2,<-> 0,-> 2
- Add these together:
[0 2 2 0 2 2 2 1 1 0 2 2](modulo 3). The only way this will result in a 0 is if:- a
1from the first char of a fish is added to a 2 from a>i.e. tail of rightwards fish - a
0from the last char of a fish is added to a 0 from a<i.e. tail of a leftwards fish
- a
- Check divisibility by 3:
[1 0 0 1 0 0 0 0 0 1 0 0]i.e. fish positions
Haskell + hgl, 36 bytes
ca"1"<<tx<m(gkY$rX">{1_<>|<><{1_|.")
Explanation
rX">{1_<>|<><{1_|."regex to replace the tails with1s.txtransposeca"1"count the number of1s in each row (previously columns).
No parser, 37 38 bytes
cn by3<<tx<m(zwp^.m Or~<cna" "<<pxx)
Explanation
pxxget non-empty prefixescna" "count the number of non-spaces in each prefix.m Orconvert characters of the original list to code points.zwpadd pairwise to the original list of code points.mmap over each rowtxtransposecn by3count the number of entries in each row divisible by 3.
Parser no regex, 47 bytes
ca"1"<<tx<m(gkY$on(hh=#+)cx3"><><>< ""1000010")
Reflection
This is ok. I'm a little disappointed by the fact the parser-no-regex version is so much longer than the no parser version when the shortest solution is the regex version. I want parsers to be more efficient than they are. It would even help regex parser answers. I don't really have a way to fix the thing I am frustrated with, but I have some thoughts in general:
There should be a combined version ofTurns out I already implemented this but forgot to export it. Very unlucky. Would have saved 3 bytes.gkY<rX. There's one forgky<rXalready, I just got a bit unlucky.- Map and then transpose seems to be a common operation for some reason. Should add a built-in for it.
pMandhdshould be combinedWris great for making lists of strings, unless you want a space in one of the strings. Then the alternative isLn, but newlines cost two bytes to write in strings. There should be an alternative that splits on some other character, and if I have any foresight I will make two of them.- There should be builtins for converting to and from binary
Strings. It would be cheaper to make"1000010"if I had one. - There should be a combined version of
m Or. - There should be a function for cumulatively counting the number of values.
Scala 3, 178 161 bytes
Saved 17 bytes thanks to @corvus_192
Golfed version. Attempt This Online!
s=>{val z=s split "\n"flatMap(l=>"><>|<><".r.findAllMatchIn(l)map(m=>m.start+(if(m.matched=="<><")2 else 0)));if(z.isEmpty)z else(0to z.max)map(i=>z.count(i==))}
Ungolfed version. Attempt This Online!
import scala.util.matching.Regex
object Main {
def main(args: Array[String]): Unit = {
val inputString = """ ><> ><> ><> ><> ><>
<>< <>< ><> <>< ><>
><> ><> ><><>< ><>><> <><
><> ><> <>< ><> <><
><> ><> ><> ><> ><>
><> <><<>< ><> <><><> ><> ><>
><> ><> ><> ><> <><
><> ><> <>< <>< ><> ><>"""
val positions = findPatternPositions(inputString)
val result = countPositions(positions)
val outputString = result.mkString("")
println(outputString)
}
def findPatternPositions(s: String): List[Int] = {
val pattern = "><>|<><".r
s.split("\n").flatMap { line =>
pattern.findAllMatchIn(line).map { m =>
m.start + (if (m.matched == "<><") 2 else 0)
}
}.toList
}
def countPositions(positions: List[Int]): List[Int] = {
if (positions.isEmpty) List()
else {
val maxPosition = positions.max
(0 to maxPosition).map { i =>
positions.count(_ == i)
}.toList
}
}
}
C# (.NET Core), 189 bytes
int[]c(string f){var p=f.Split('\n');var t=new int[p.Max(s=>s.Length)];foreach(var x in p)for(int m=0;m<2;m++)foreach(Match n in Regex.Matches(x,m>0?"<><":"><>"))t[n.Index+m*2]++;return t;}
Full code:
using System;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
string r = "<>< ><> ><>><>" + Environment.NewLine +
" <>< <>< ><> ><>" + Environment.NewLine +
" <>< <><" + Environment.NewLine;
int[] c (string f)
{
var p = f.Split('\n');
int m = 0;
foreach (var x in p)
m = Math.Max(m, x.Length);
var t = new int[m];
foreach (var x in p)
{
foreach (Match n in Regex.Matches(x, "<><"))
t[n.Index + 2]++;
foreach (Match n in Regex.Matches(x, "><>"))
t[n.Index]++;
}
return t;
}
Console.WriteLine(string.Join(",", c(r)));
}
}
```
APL+WIN, 70 bytes
Prompts for school as a 2 dimension array.
m←((i←(⍴i)÷3),3)⍴i←(n←v≠' ')/v←,j←⎕⋄+⌿(⍴j)⍴n\,(m[;1]='>'),0,m[;,3]='<'
C++ (clang), 191 124 bytes
[](auto&r,auto&v){for(auto&s:r)for(int i=0;i+2<s.size();i++)v.resize(max(v.size(),s.size())),s[i]>59?v[i+62-s[i]]++,i+=2:0;}
Reduction thanks to jdt and ceilingcat
Pip -r, 22 bytes
$+^gR`\S`*3{'<Q@a?Rhh}
Takes input from stdin; requires it to be padded to a rectangle with spaces. Attempt This Online!
Explanation
$+^gR`\S`*3{'<Q@a?Rhh}
g ; List of lines of stdin (-r flag)
R ; In each line, replace
`\S`*3 ; regex match of three non-space characters (guaranteed
; to be a fish because only well-formed fish are present)
{ } ; with this callback function:
'<Q@a? ; If the fish starts with <
Rh ; Reverse of h (001)
h ; Else, h (100)
^ ; Split into a 2D matrix of characters
$+ ; Sum (treating spaces as 0s)
Uiua, 30 bytes
+@0/+⬚0⊜(=-:@>◿3+2\+≠@ .)⊸≠@\n
Try it online!, inspired by ovs's K solution
Explanation:
+@0/+⬚0⊜(=-:@>◿3+2\+≠@ .)⊸≠@\n
⊜( )⊸≠@\n => split string by newlines
≠@ => non-whitespace indexes
+2\+ => accumulative addition starting at 2
◿3 => modulo 3
-:@> => subtract 62 (>)
= . => compare with original row
⬚0 => fill 0s if needed
+@0/+ => row addition and then stringify (optional)
05AB1E, 12 bytes
ðÊ€ηOIÇ+3ÖøO
Similar as a bunch of other answers.
Takes the input as a list of lists of characters, including trailing spaces to make all lines the same length.
Try it online or verify all test cases.
Explanation:
ðÊ # Check for each inner-most character in the (implicit) input-matrix
# that it's NOT equal to a space " "
€η # Take the prefixes of each inner list of 0s/1s
O # Sum each inner-most prefix
I # Push the input-matrix again
Ç # Convert each character to its codepoint-integer
+ # Vectorized add the values at the same positions
3Ö # Check for each whether it's divisible by 3
ø # Zip/transpose; swapping rows/columns
O # Sum each inner list (the columns before the zip) together
# (after which the resulting list of sums is output implicitly)
Python + NumPy, 79 bytes
lambda s:sum((cumsum((X:=c_[s].view("i4")%-8)<0,1)+X)%3>1,0)
from numpy import*
Takes a list of rows which are strings.
Or
Python + NumPy, 77 bytes (@emanresu A)
assuming input lines are equal length.
lambda s:sum((cumsum((X:=c_[s].view("i4"))>32,1)+X)%3<1,0)
from numpy import*
How?
Using numpy is convenient here, because the array constructor pads strings to equal length (with zeros, so normally you wouldn't necessarily notice). The view cast to integer does roughly the same as ord in standard python; it also reveals the padding.
Japt, 24 21 16 bytes
Takes input as a 2D array of codepoints.
Ëí+DËgHÃå+ÃÕËxv3
Ëí+DËgHÃå+ÃÕËxv3 :Implicit input of 2D array of codepoints
Ë :Map each D
î+ : Interleave with, reducing each pair by addition
DË : Map D
g : Sign of difference with
H : 32
à : End map
å+ : Cumulatively reduce by addition
à :End map
Õ :Transpose
Ë :Map
x : Reduce by addition of
v3 : Divisible by 3?
Ruby, 92 bytes
Takes an array of lines as input.
->a{h=Hash.new 0
a.map{_1.scan(/(><>)|<></){h[$`.size+($1?0:2)]+=1}}
(0...a[0].size).map &h}
R, 95 94 bytes
-1 thanks to pajonk
\(x)Reduce(\(v,m)v+`[<-`(!1:max(nchar(x)),(m*attr(m,"m"))[-1,],1),gregexec("<>(<)|(>)<>",x),0)
Ungolfed:
\(x) {
Reduce(
# for each vector of fish tail indices, increment the correct slots in the output
# vector
\(v,m) {
v +
# assigning 1's to the indices of fish tails in a vector of zeroes
# (this works because the assignment form of [] silently returns the new vector
`[<-`(
0*1:max(nchar(x)),
# multiply match indices by match lengths so that zero-length matches
# aren't included, and exclude row 1 (total match)
# (this works since assigning to index 0 leaves the vector unchanged)
(m*attr(m,"m"))[-1,],
1
)
},
# find the fish tails and return a list of integer vectors, where each vector is
# the indices of the fish tails
gregexec("<>(<)|(>)<>",x),
# initial value for `Reduce`
0
)
}
Ruby, 83 79 bytes
->s{a=[c=x=0]*w=s=~/\n/
s.bytes{|i|c+=i/60
i>10?a[(i-62+x+=1)%w]+=c%3/2:x=0}
a}
Function that takes a newline separated string as an argument and returns an array.
Assumes there is no line longer than the first line.
c is a count of the number of < and > (characters over ascii 60) found. When we are at the middle character of a fish c%3 reaches its max value of 2. The direction of the character (ascii 60 or 62) points toward the tail, and the appropriate adjacent column a[x+1] or a[x-1] is incremented.
The magic constant might be expected to be -61, based on the average of 60 and 62, but another 1 must be subtracted to compensate for the increment of x.
JavaScript (ES6), 69 bytes
-2 thanks to @l4m2
Expects an array of arrays of characters (which may be of different lengths). Returns an array of integers.
a=>a.map(r=>r.map((c,i)=>b[i]=~~b[i]+(c=="<>"[a=c+3|-~a%3])),b=[])&&b
Commented
a => // a[] = input array
a.map(r => // for each row r[] in a[]:
r.map((c, i) => // for each character c at position i in r[]:
b[i] = // update b[i]:
~~b[i] + ( // coerce it to an integer in case it's still undefined
c == "<>"[ // test whether c is a fish tail:
a = // update a:
c + 3 | // this gives 3 if c is a space (which forces the
// test to fail and resets a to 3) or NaN otherwise
-~a % 3 // computes (a + 1) mod 3; if the result is 2, this
// is the middle part of the fish (never a tail)
] // end of lookup
) //
), // end of inner map()
b = [] // start with b = []
) && b // end of outer map(); return b[]
Python, 142 126 122 bytes
lambda s:[*map([m.start()+2*(m[0]<'>')for r in s for m in re.finditer(r'\S..',r)].count,range(max(map(len,s))))]
import re
- Input: list of strings
- Output: list of integers
Charcoal, 40 35 28 26 bytes
WSP⭆ι⁺¬﹪⁺℅κL⁻…ι⊕λ ³Σ⊟KD⊕λ→
Try it online! Link is to verbose version of code. Takes input as a list of newline-terminated strings. Explanation: Now inspired by @Ausername's version of @ovs' answer.
WS
Loop through each row of fish.
P⭆ι⁺¬﹪⁺℅κL⁻…ι⊕λ ³Σ⊟KD⊕λ→
For each character, count the number of non-spaces so far including the current character, add on the current character's ordinal, and check whether the result is divisible by 3. If so, then increment the appropriate digit of the result, otherwise replace blanks with zeros. Replace the current result with the new computed values. (Unfortunately Charcoal has no way of adding the values in two arrays to each other so it has to peek each digit of the result in turn.)
K (ngn/k), 18 bytes
+/{x=62-3!2+\~^x}'
{ }' / for each row:
x=62-3!2+\~^x / mark the tails
+/ / add the rows to get column count
/ example: "><>><> <>< "
~^x / is not null (not space)
/ 1 1 1 1 1 1 0 1 1 1 0 0
2+\ / cumulative sums, starting at 2
/ 3 4 5 6 7 8 8 9 10 11 11 11
3! / modulo 3. maps each fish to 0 1 2
/ 0 1 2 0 1 2 2 0 1 2 2 2
62- / subtract from 62 (>). Maps each fish to ">=<"
/ ">=<>=<<>=<<<"
x= / character-wise equal to original row
/ 1 0 0 1 0 0 0 0 0 1 0 0
Jelly, 14 bytes
>⁶Ä3ḍk⁸Ġ€F=2)S
A monadic Link that accepts a list of lists of < > characters and yields a list of the column-wise tail counts.
How?
Partition each row after either the right-hand side of each fish (whether a head or a tail) or a space character like so:
><> ><><><
00111000111111 <- greater than space?
00123333456789 <- cumulative sums
11001111001001 <- is divisible by three?
ww[f]www[f][f][] <- identified "parts" (by partitioning after 1s)
shown here as: water (w);
fish ([f]); and
a trailing empty list ([])
Then identify the "tails" of each "part" using the group-indices-by-value monad, Ġ:
| Part Type | Part | Ġ(Part) | flatten(Ġ(Part))=2? |
|---|---|---|---|
[f] |
"<><" |
[[1,3],[2]] |
[0,0,1] |
[f] |
"><>" |
[[2],[1,3]] |
[1,0,0] |
w |
" " |
[[1]] |
[0] |
[] |
"" |
[] |
[] |
>⁶Ä3ḍk⁸Ġ€F=2)S - Link: list of lists of characters, School
) - for each (Row of the School):
>⁶ - {Row} greater than the space character? (vectorises)
Ä - cumulative sums of {that}
3ḍ - three divides {that}? (vectorises)
k⁸ - partition the Row after truthy indices of {that}
Ġ€ - group the indices of each of {those} by their values
F - flatten {that}
=2 - {that} equals two? (vectorises)
S - sum {that} (column-wise)
Retina, 97 bytes
N$^`
$.&
(\S)(\S)\1
$2
<
1
>
1
+`(?<=^(.)*)(.)((.*¶)+(?<-1>.)*)1(?(1)^)
$.(_$2*)$3
0
0G`
Try it online! Explanation:
N$^`
$.&
Sort the rows in descending order of length.
(\S)(\S)\1
$2
Chop the heads and tails off all the fish.
<
1
>
1
Place 1s where the tails used to be.
+`(?<=^(.)*)(.)((.*¶)+(?<-1>.)*)1(?(1)^)
$.(_$2*)$3
Accumulate the column totals.
0
Replace any remaining spaces with zeros.
0G`
Keep just the totals.