14
\$\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\$
5
  • 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\$ Aug 9, 2020 at 15:57
  • 5
    \$\begingroup\$ Why does not the regex for alphanumeric words accept numbers? \$\endgroup\$ Aug 9, 2020 at 16:13
  • \$\begingroup\$ @mypronounismonicareinstate, the alphanumeric was a typo, edited it. \$\endgroup\$
    – vrintle
    Aug 9, 2020 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, 2020 at 20:03
  • \$\begingroup\$ @LuisMendo, made them optional now. \$\endgroup\$
    – vrintle
    Aug 10, 2020 at 2:07

22 Answers 22

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 ʒĀ}.

\$\endgroup\$
3
  • \$\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\$ Aug 20, 2020 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, 2020 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\$ Aug 20, 2020 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: {⊃⍵[⍒+/¨⍵⍷¨⊂⍵]}.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You can replace (819⌶) with ⎕C in 18.0, though TIO isn't updated yet. \$\endgroup\$
    – Bubbler
    Aug 10, 2020 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!

\$\endgroup\$
5
  • \$\begingroup\$ Ah, you made a separate range. Nice. \$\endgroup\$
    – Razetime
    Aug 10, 2020 at 2:15
  • \$\begingroup\$ -2 bytes, used scan. \$\endgroup\$
    – vrintle
    Aug 10, 2020 at 4:27
  • 1
    \$\begingroup\$ Squeezed off another 6 bytes \$\endgroup\$
    – vrintle
    Aug 10, 2020 at 5:47
  • \$\begingroup\$ 58 bytes by squeezing another 4 bytes off Rahul Verma's latest version. \$\endgroup\$
    – Dingus
    Sep 4, 2020 at 1:57
  • \$\begingroup\$ nice golf. I'll put it in. \$\endgroup\$
    – Razetime
    Sep 4, 2020 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.
\$\endgroup\$
4
  • 1
    \$\begingroup\$ 70 bytes; it's a shame that "\\W+" wouldn't work since it includes _ \$\endgroup\$
    – Giuseppe
    Aug 10, 2020 at 17:06
  • 1
    \$\begingroup\$ actually, is the 0-9 needed since a word consists only of [a-zA-Z]+? \$\endgroup\$
    – Giuseppe
    Aug 10, 2020 at 17:18
  • \$\begingroup\$ 1) Thanks! I obviously need a bit of practice at regexes! \$\endgroup\$ Aug 10, 2020 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\$ Aug 10, 2020 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!

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

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

\$\endgroup\$
2
  • \$\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\$ Aug 10, 2020 at 20:00
  • \$\begingroup\$ Also, not that it matters, but I think \Pl should be equivalent to [^A-Za-z]> \$\endgroup\$ Aug 10, 2020 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
\$\endgroup\$
0
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.

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

\$\endgroup\$
5
  • \$\begingroup\$ Also, you could just write import re and re.match. Result: -3 bytes. \$\endgroup\$
    – vrintle
    Aug 10, 2020 at 5:52
  • \$\begingroup\$ @DLosc isalpha() returns True for some non-English characters as well. Check out the 4th example. \$\endgroup\$ Aug 10, 2020 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, 2020 at 10:20
  • \$\begingroup\$ And a for-loop is more fitting here: Try it online! \$\endgroup\$
    – ovs
    Aug 10, 2020 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, 2020 at 1:04
2
\$\begingroup\$

Husk, 12 8 bytes

►=mLmf√w

Try it online!

Previous answer was badly optimized.(-4 bytes)

From Zgarb:

► has a second mode. If you give it a binary function f, it returns an element x that maximizes the number of elements y for which fxy holds.

So ►= is a 2-byte max by frequency.

Explanation

►=fImLmf√ġK√
         ġK√ group string on non alphabet-characters.
       f√    filter out non-alphabet characters
      m      map that to each word ↑
    mL       Length of each word
  fI         filter out zeroes (empty string length)
►=           max by frequency
\$\endgroup\$
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

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

\$\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
};
\$\endgroup\$
3
  • 1
    \$\begingroup\$ 115 bytes \$\endgroup\$ Aug 10, 2020 at 15:51
  • \$\begingroup\$ @OlivierGrégoire That's a really cool approach! Do you want to make your own answer? \$\endgroup\$
    – user
    Aug 10, 2020 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\$ Aug 10, 2020 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
}
\$\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!

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

\$\endgroup\$
2
  • 3
    \$\begingroup\$ -5 bytes by using python 3.8's assignment expr \$\endgroup\$ Aug 10, 2020 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, 2020 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.

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

\$\endgroup\$
0
\$\begingroup\$

Factor + math.unicode, 57 bytes

[ [ Letter? ¬ ] split-when harvest [ length ] map mode ]

Try it online!

Split on non-letters, harvest (remove) any vestigial empty strings, get the length of each word, and take the mode.

\$\endgroup\$

Your Answer

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

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