13
\$\begingroup\$

The task is simple. You are given a string with alphabetical words (say "Hello world, this are tests"). You have to return the mode of the lengths of words in the string. In this case, output is 5, as it's the most often length of words in the string.

Definition of an alphabetical word (for this challenge): a string that consists of a-zA-Z only.

Sample I/O:

Constraints: Input has atleast one word, and a unique mode. Max. length is provided in last test case. Also, the string would be a single line, no newline chars.

(In = Out format)

"Hello world, this are tests"                     =  5
"Hello    world, this... are tests"               =  5
"I"                                               =  1
"Let's box (ง︡'-'︠)ง"                               =  3
"Writing some ✍(◔◡◔) program"                   =  7
"the-the-the-then"                                =  3
"Gooooooooogle is an app"                         =  2
"()<>a+/sentence$#@(@with::many---_symbols{}|~~"  =  4
"anot_her test actually"                          =  4

The unicode tests are optional.

1000 words string = 5 (Password: PXuCdMj5u65vwst)

This is a , so fewest bytes will win!

\$\endgroup\$
  • 4
    \$\begingroup\$ I don't understand the "hidden test" - who are you hiding it from? Why isn't the answer for it included in the question? \$\endgroup\$ – the default. Aug 9 at 15:57
  • 5
    \$\begingroup\$ Why does not the regex for alphanumeric words accept numbers? \$\endgroup\$ – the default. Aug 9 at 16:13
  • \$\begingroup\$ @mypronounismonicareinstate, the alphanumeric was a typo, edited it. \$\endgroup\$ – Vrintle Aug 9 at 17:08
  • 6
    \$\begingroup\$ Do we really need to handle Unicode chars? It doesn't seem to add anything to the challenge, and it leaves some languages out \$\endgroup\$ – Luis Mendo Aug 9 at 20:03
  • \$\begingroup\$ @LuisMendo, made them optional now. \$\endgroup\$ – Vrintle Aug 10 at 2:07

20 Answers 20

6
\$\begingroup\$

05AB1E, 10 9 7 bytes

-1 byte inspired by Jonathan Allans Jelly answer.
-2 bytes thanks to Kevin Cruijssen!

Input is a list of characters.

aγO0K.M

Try it online!

Commented:

aγO0K.M     implicit input       ["a","b"," ","c","d"," ","e","."]

a           is_alpha (vectorizes)[1, 1, 0, 0, 1, 1, 0, 1, 0]
 γ          split into chunks of equal elements
              [[1, 1], [0, 0], [1, 1], [0], [1], [0]]
  O         sum the lists        [2, 0, 2, 0, 1, 0]
   0K       remove 0's
     .M     mode                 2

            implicit output      2

a is implemented as Regex.match?(~r/^[a-zA-Z]+$/, to_string(x)), which should be equivalent to the challenge specification.

I feel like there has to be a shorter way to remove 0s from a list than ʒĀ}.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ There indeed is a shorter way to remove 0s: 0K. ;) Also, you can save 1 more byte by taking the input as a list of characters, so the isn't necessary anymore. \$\endgroup\$ – Kevin Cruijssen Aug 20 at 8:25
  • \$\begingroup\$ @KevinCruijssen thanks a lot. I searched the wiki for remove, delete and filter, but without didn't cross my mind. \$\endgroup\$ – ovs Aug 20 at 11:00
  • \$\begingroup\$ Yeah, the descriptions of the builtins are sometimes a bit counter-intuitive to search for unfortunately. :/ I had the same issue for the longest time at first. Luckily I now know almost all builtins out of the top of my head, give or take a few, since I golf so much in 05AB1E. \$\endgroup\$ – Kevin Cruijssen Aug 20 at 12:09
5
+100
\$\begingroup\$

APL (Dyalog Unicode), 30 bytes

{⍵[⊃⍒+/∘.=⍨⍵]}≢¨⊆⍨⎕A∊⍨1(819⌶)⎕

Try it online!

{⍵[⊃⍒+/∘.=⍨⍵]}≢¨⊆⍨⎕A∊⍨1(819⌶)⎕ ⍝ Full program
1(819⌶)⎕ ⍝ Uppercase the input
⎕A∊⍨     ⍝ Test if each character is a capital letter
⊆⍨       ⍝ Group the letters together
≢¨       ⍝ Length of each word
{⍵[⊃⍒+/∘.=⍨⍵]} ⍝ Mode

The mode dfn is by ngn. My approach was similar but one byte longer: {⊃⍵[⍒+/¨⍵⍷¨⊂⍵]}.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ You can replace (819⌶) with ⎕C in 18.0, though TIO isn't updated yet. \$\endgroup\$ – Bubbler Aug 10 at 3:49
5
\$\begingroup\$

Ruby, 70 68 58 bytes

->s{(s=s.scan(/[a-z]+/i).map &:size).max_by{|y|s.count y}}

Try it online!

-20 bytes from Dingus.

-2 bytes from Rahul Verma.

-10 bytes from Dingus(again) by removing a variable.

Ruby, 90 bytes

->a{a.split(/\W+/).map(&:size).inject(Hash.new(0)){|h,v|h[v]+=1;h}.sort_by{|k,v|v}[-1][0]}

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Ah, you made a separate range. Nice. \$\endgroup\$ – Razetime Aug 10 at 2:15
  • \$\begingroup\$ -2 bytes, used scan. \$\endgroup\$ – Vrintle Aug 10 at 4:27
  • 1
    \$\begingroup\$ Squeezed off another 6 bytes \$\endgroup\$ – Vrintle Aug 10 at 5:47
  • \$\begingroup\$ 58 bytes by squeezing another 4 bytes off Rahul Verma's latest version. \$\endgroup\$ – Dingus Sep 4 at 1:57
  • \$\begingroup\$ nice golf. I'll put it in. \$\endgroup\$ – Razetime Sep 4 at 2:35
4
\$\begingroup\$

R, 79 67 bytes

Edit: -9 and then -3 more bytes thanks to Giuseppe

names(sort(-table(nchar(el(strsplit(scan(,''),"[^a-zA-Z]+"))))))[1]

Try it online!

Commented:

names(              # Get the names (=values) of...
  sort(-            # the descending (-) frequencies of...
    table(          # the table of values of...
     (w=nchar(      # the number of characters of...
       strsplit(scan(,''),
                    # the input, grouped by splitting on...
       "[^a-zA-Z0-9]")[[1]]))
                    # non-alphanumeric characters...
     [w>0]          # ignoring zero-length groups.
    )               
  )
)[1]                # Output the first name, which is
                    # the most-frequent number of characters
                    # per group.
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ 70 bytes; it's a shame that "\\W+" wouldn't work since it includes _ \$\endgroup\$ – Giuseppe Aug 10 at 17:06
  • 1
    \$\begingroup\$ actually, is the 0-9 needed since a word consists only of [a-zA-Z]+? \$\endgroup\$ – Giuseppe Aug 10 at 17:18
  • \$\begingroup\$ 1) Thanks! I obviously need a bit of practice at regexes! \$\endgroup\$ – Dominic van Essen Aug 10 at 17:29
  • 1
    \$\begingroup\$ 2) Not any more. The question originally specified 'alphanumeric', but I notice that it's now been edited to 'alphabetic' so you're right. \$\endgroup\$ – Dominic van Essen Aug 10 at 17:29
3
\$\begingroup\$

JavaScript (ES6), 66 bytes

s=>s.replace(o=/[a-z]+/gi,w=>o[s]>(o[n=w.length]=-~o[n])?0:s=n)&&s

Try it online!

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Retina 0.8.2, 43 bytes

M!i`[a-z]+
%M`.
O#`
O#^$`(.+)(¶\1)*
$#2
1G`

Try it online! Link includes test cases. Explanation:

M!i`[a-z]+

List only the words.

%M`.

Take the length of each word.

O#`

Sort the lengths numerically.

O#^$`(.+)(¶\1)*
$#2

Sort in reverse order of frequency.

1G`

Take the mode.

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Jelly, 11 bytes

e€ØẠŒg§ḟ0Æṃ

A monadic Link accepting a list of characters which yields an integer.

Try it online! Or see the test-suite.

How?

e€ØẠŒg§ḟ0Æṃ - Link: S
  ØẠ        - alphabetic characters
 €          - for each (c in S)
e           -   (c) exists in (S)?
    Œg      - group runs of equal elements (1s or 0s)
      §     - sums
        0   - zero
       ḟ    - filter discard
         Æṃ - mode
| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Perl 5 -pF'[^A-Za-z]+', 51 bytes

map$k{y///c}++,@F;$_=(sort{$k{$b}-$k{$a}}keys%k)[0]

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Nice, just made pretty much the same too! You can shave a few bytes using %; as the name of the hash, using for instead of map...,... and using ($_)=<list> Try it online! \$\endgroup\$ – Dom Hastings Aug 10 at 20:00
  • \$\begingroup\$ Also, not that it matters, but I think \Pl should be equivalent to [^A-Za-z]> \$\endgroup\$ – Dom Hastings Aug 10 at 20:03
3
\$\begingroup\$

MATL, 8 bytes

3Y4XXzXM

Supports ASCII characters only. Try it online! Or verify all ASCII test cases.

How it works

3Y4   % Push predefined literal '[A-Za-z]+'
XX    % Implicit input. Regexp. Gives cell array of matched substrings
z     % Number of nonzero chars of each substring
XM    % Mode. Implicit display
| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Pip, 18 bytes

aMR:+XA#_(_NaSKav)

Try it online!

Explanation

aMR:+XA#_(_NaSKav)
                    a is 1st cmdline arg; v is -1 (implicit)
aMR:                Map a function to each regex match in a and assign the result back to a
    +XA              Regex: a letter (XA) repeated one or more times (+)
       #_            The function: length of the match
                    Now we just need to get the mode:
             SKa    Sort a using this key function:
          _Na        Count of each element in the full list a
         (      v)  Since it's now sorted from least common to most, get the last element

If Pip had a two-byte builtin for getting the mode of a list, I could do this in 10 bytes: MO#*Ya@+XA (with MO being the mode builtin). Ah well.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Python 3, 148 143 140 132 100 99 bytes

n,*c=0,
for x in input()+'1':
 if'`'<x.lower()<'{':n+=1
 elif n:c+=n,;n=0
print(max(c,key=c.count))

Try it online!

Uses regex to check if character is a letter of the English alphabet and adds the count of all consecutive alphabets to a list and finds the mode of that list.

-3 bytes thanks to Rahul Verma

-32 bytes thanks to ovs

-1 byte thanks to DLosc

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Also, you could just write import re and re.match. Result: -3 bytes. \$\endgroup\$ – Vrintle Aug 10 at 5:52
  • \$\begingroup\$ @DLosc isalpha() returns True for some non-English characters as well. Check out the 4th example. \$\endgroup\$ – Manish Kundu Aug 10 at 7:05
  • \$\begingroup\$ you can create lists with [*...], the re.match can be replaced by ''<s.pop(0).lower()<'{'` and appending to a list is shorter with +=: Try it online! \$\endgroup\$ – ovs Aug 10 at 10:20
  • \$\begingroup\$ And a for-loop is more fitting here: Try it online! \$\endgroup\$ – ovs Aug 10 at 10:23
  • \$\begingroup\$ Hm. I was going by "The unicode tests are optional," but fair enough. In any case, you can save 1 more byte using this tip: change the first line to n,*c=0, \$\endgroup\$ – DLosc Aug 11 at 1:04
1
\$\begingroup\$

Scala, 66 bytes

"[a-zA-Z]+".r.findAllIn(_).toSeq.groupBy(_.size)maxBy(_._2.size)_1

Try it in Scastie

Unfortunately, finding the mode in Scala is a bit clumsy

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Io, 141 bytes

A really awful solution... just 2 bytes shorter than the Python one. 3

method(x,x asUppercase asList map(i,if(if(i at(0),i at(0),0)isLetter,1,0))join split("0")map(size)remove(0)uniqueCount map(reverse)max at(1))

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Java (JDK), 129 bytes

Saved 10 bytes thanks to @ceilingcat!

s->{int m=0,z=s.length()+1,a[]=new int[z];for(var x:s.split("[^a-zA-Z]+"))a[x.length()]++;for(;z-->0;m=a[z]>a[m]?z:m);return m;};

Try it online!


Explanation:

s -> {
  int m=0,             //m is the index of the max element in a
      z=s.length()+1,  //z is to avoid using a.length twice
      a[]=new int[z];  //Each index corresponds to a length, and the element at that index its frequency
  for(var x : s.split("[^a-zA-Z]+")) //Fill up the pigeonholes
    a[x.length()]++;
  for(;                 //Find the index of the max element/highest frequency/mode
      z-->0;            //For every index from a.length to 0,
      m=a[z]>a[m]?z:m); //If the current element is greater than the current max frequency, change the mode length
  return m;             //Return the length with the highest frequency
};
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ 115 bytes \$\endgroup\$ – Olivier Grégoire Aug 10 at 15:51
  • \$\begingroup\$ @OlivierGrégoire That's a really cool approach! Do you want to make your own answer? \$\endgroup\$ – user Aug 10 at 19:47
  • 1
    \$\begingroup\$ Indeed, the approach is different, so I understand you don't want to use it as your own. I've posted it as my own answer. \$\endgroup\$ – Olivier Grégoire Aug 10 at 21:02
1
\$\begingroup\$

Java (JDK), 113 bytes

s->{int m=0,l=s.length(),t,L=0;for(;l>0;L=t>m?(m=t)-m+l:L)t=s.split("\\b[a-zA-Z]{"+l--+"}\\b").length;return-~L;}

Try it online!

Explanation

This basically splits the String on ascii words of all possible lengths to count them, and returns the max value of the count.

s->{
 int m=0,                                 // The maximum number of 
     l=s.length(),                        // The length of ASCII letters, going from high to low
     t,                                   // Declare a temp variable.
     L=0;                                 // Initialize the most present length to 0.
 for(                                     // Loop
      ;
      l>0;                                // On each length, going down
      L=t>m?(m=t)-m+l:L                   // If a count is higher than the max count, the new count becomes the max count and the most present length becomes the current length
     )
  t=                                     
      s.split("\\b[a-zA-Z]{"+l--+"}\\b")  // Count the number of parts between or around words of length l
                                          // Also, decrement l
       .length;                           // Store the count into t
 return-~L;                               // Return L + 1
}
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 115 113 112 bytes

-1 byte ceilingcat

m;n;w;c;l;i;f(char*s){for(m=n=l=0;s[l++];m=c>n?n=c,l:m)for(i=w=c=0;w=isalpha(s[i])?1+w:w-l?0:!++c,s[i++];);n=m;}

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Japt v2.0a0, 13 bytes

q\L f üÊñÊÌÌÊ

Try it

q\L f üÊñÊÌÌÊ     :Implicit input of string U    e.g., "()<>a+/sentence$#@(@with::many---_symbols{}|~~"
q                 :Split on
 \L               :  Regex /[^a-z]/i             ["","","","","a","","sentence","","","","","with","","many","","","","symbols","","","","",""]
    f             :Filter (remove empty strings) ["a","sentence","with","many","symbols"]
      ü           :Group & sort by
       Ê          :  Length                      [["a"],["with","many"],["symbols"],["sentence"]]
        ñ         :Sort by
         Ê        :  Length                      [["a"],["symbols"],["sentence"],["with","many"]]
          Ì       :Last element                  ["with","many"]
           Ì      :Last element                  "many"
            Ê     :Length                        4
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Python 3.8, 81 75 bytes

Thanks to Mukundan314 for 5 bytes and ovs for another 1 byte

lambda S:max(L:=[*map(len,re.findall("[a-z]+",S,2))],key=L.count)
import re

Try it online!

Anonymous function: Finds all runs of letters using regex, collects a list of the lengths of those runs, and prints the item with the maximum frequency in the list.

| improve this answer | |
\$\endgroup\$
  • 3
    \$\begingroup\$ -5 bytes by using python 3.8's assignment expr \$\endgroup\$ – Mukundan314 Aug 10 at 5:16
  • 2
    \$\begingroup\$ You can use re.findall('[a-z]+",input(),2) for -1. (2 is the value of the re.IGNORECASE flag) \$\endgroup\$ – ovs Aug 10 at 10:40
0
\$\begingroup\$

Wolfram Language (Mathematica), 48 bytes

Commonest@*StringLength@*StringCases[__?LetterQ]

Try it online! Function. Takes a string as input and returns a list of most common lengths as output. The list should only have a single number if the mode length is unique. It gives incorrect output on one of the Unicode examples, presumably due to counting as a letter.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

PHP, 101 bytes

$a=array_count_values(array_map(strlen,preg_split('/[^A-Za-z]/',$argn,0,1)));arsort($a);echo key($a);

Try it online!

Drat PHP and it's super long function names again...

| improve this answer | |
\$\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.