views:

564

answers:

12

Given a list of assorted length words, what is the best way to find the maximum length of any words?

For example, the following should return 6

findMaxLen("a,set,of,random,words")


Of course, it's fairly trivial to do this...

<cffunction name="findMaxLen" returntype="Numeric">
    <cfset var CurMax = 0 />
    <cfset var CurItem = 0 />
    <cfloop index="CurItem" list="#Arguments[1]#">
     <cfif Len(CurItem) GT CurMax >
      <cfset CurMax = Len(CurItem)/>
     </cfif>
    </cfloop>
    <cfreturn CurMax />
</cffunction>


Or, a little shorter...

<cffunction name="findMaxLen" returntype="Numeric">
    <cfset var CurMax = 0 />
    <cfset var CurItem = 0 />
    <cfloop index="CurItem" list="#Arguments[1]#">
     <cfset CurMax = Max( CurMax , Len(CurItem) ) />
    </cfloop>
    <cfreturn CurMax />
</cffunction>


But is there a better way - something more efficient?

Perhaps some Java method? Converting to array and sorting by item length? Counting the biggest gap between commas?


In practical terms, either of the above two examples will work fine for my current need, and this isn't for something that is performance critical, so I don't need an answer to this, but I thought it would still be interesting to see what people might come up with...

+11  A: 

Count the distance between commas.

I don't think anything could be faster than that; it's O(n), and you have to look at each character at least once anyway (to see if it's a comma).

int FindLongestWord(char* str)
{
   char* lastComma = str - 1;
   int longest = 0;
   int length;
   char* pCheckChar;

   for(pCheckChar = str; *pCheckChar; pCheckChar++)
   {
      if(*pCheckChar == ',')
      {
         length = pCheckChar - lastComma - 1;
         if(length > longest)
         {
            longest = length;
         }

         lastComma = pCheckChar;
      }
   }

   // Check to see if the last word is the longest
   length = pCheckChar - lastComma - 1;
   if(length > longest)
   {
      longest = length;
   }

   return longest;
}

or I suppose you could just say

"a,set,of,random,words".Split(',').Max(w=>w.Length);

if we're playing games... ;]

Daniel LeCheminant
@sfossen: why, can't you do it yourself? ;-)
David Zaslavsky
please email me teh codes at [email protected]
Zombies
I could, but I'm not the one wanting the answer accepted.
sfossen
I could do it too, but I'm not wanting my answer accepted either. But, really, I could. Honest.
Beska
small error, lastComma is only updated on longest match. should be below the 2nd if.
sfossen
+1 for good answer and code.
sfossen
@sfossen: Great catch :]
Daniel LeCheminant
A: 

I did see the code golf tag - here is 54 characters in Python:

len(max("a,set,of,random,words".split(","), key=len))
Andrew Hare
Try max(map(len,"a,set,of,random,words".split(",")))52
recursive
Didn't necessarily mean it in least characters sense, but fair enough. :)Could you save a char by dropping the space before key?
Peter Boughton
Actually, @recursive, that's 48 characters. :-)
Patrick McElhaney
@recursive - you beat me - very nice!
Andrew Hare
+1  A: 

Seeing as there's a code-golf tag, here's 52 characters in C#

"a,set,of,random,words".Split(',').Max(w=>w.Length);
Greg Beech
I guess we both thought to drop the `String.` at the same time!
Daniel LeCheminant
+1  A: 

And here's the 'short' CFML way - 72 chars...

Len(ArrayMax("a,set,of,random,words".replaceAll('[^,]','1').split(',')))

Another version, 78 chars but handles huge strings (see comments)...

Len(ListLast(ListSort("a,set,of,random,words".replaceAll('[^,]','1'),'text')))
Peter Boughton
72, if you use "set" instead of "series"
Georg
Peter Boughton
I know nothing about CFML; Does that work for strings of any length? (e.g. a 1000 length string with no commas) I'm wondering if ArrayMax actually does the conversion from the 111s to a numeric data type...
Daniel LeCheminant
You're correct - ArrayMax gives the maximum number, so it is converting each string into a number, and is failing somewhere between 300 and 400 long.A similar List-based sorting version (added above) works with large values though, if very slowly - does 10,000,006 in approx 6.6 seconds.
Peter Boughton
(For comparison, the same 10M are processed in ~60-125ms by the two original functions in the question)
Peter Boughton
@Peter: Ok; I thought it looked too good to be true :]
Daniel LeCheminant
@Peter: I wonder if the "between 300 and 400" is the limit of a 64-bit double (goes to about 1.8e308) ...
Daniel LeCheminant
I've just narrowed it down, 309 works but 310 fails.
Peter Boughton
@Peter: So is the method actually returning the correct "longest word", or is it the length of the string representation of a double? (i.e. Is it returning 309 as the length longest word, or the length of the string "1.000e309")
Daniel LeCheminant
Yes, it returns the correct value upto 309, (but returns 1 for 310 and over).That's the length of the longest word. The whole string is actually 358/359 chars and can be made longer with no problems once the longest word doesn't exceed 309.
Peter Boughton
This is the source string I'm testing that with:- I'm using this: "a,set,of,random,words,with,#RepeatString('a',309)#,really,long,one,in,it"
Peter Boughton
A: 

In java without string extra functions. (just a pseudo linked list :P) Give max as 0 in the begining

   int find(LinkedList strings, int max) {
      int i;
      String s=(String)strings.element();
      for(i=0;s.charAt(i)!='\0';i++);
      if(strings.hasNext())
         return find(strings.Next(),(i>max?i:max));
      return max;
    }

Edit: Just noticed now it's given a String of words not a list of strings, well never mind stays here the same :)

fmsf
Java doesn't have null-terminated strings; charAt will throw an IndexOutOfBoundsException instead. Try going up to s.length() instead.
Michael Myers
I didn't want to use string functions then it would loose the fun of it, then it's a bit mixed with c
fmsf
+2  A: 

In Perl (assuming we have a variable $max in which the answer is to be stored):

(length $1 > $max) && ($max = length $1) while "a,set,of,random,words" =~ /(\w+)/g;

Or:

(length $_ > $max) && ($max = length $_) foreach split /,/, "a,set,of,random,words";

Or:

$max = length((sort { length $b <=> length $a } split /,/, "a,set,of,random,words")[0]);

TMTOWTDI, after all.

EDIT: I forgot about the Core Modules!

use List::Util 'reduce';
$max = length reduce { length $a > length $b ? $a : $b } split /,/, "a,set,of,random,words";

...which somehow manages to be longer than the other ones. Oh well!

EDIT 2: I just remembered map():

use List::Util 'max';
$max = max map length, split /,/, "a,set,of,random,words";

That's more like what I'm looking for.

EDIT 3: And just for completeness:

($max) = sort { $b <=> $a } map length, split /,/, "a,set,of,random,words";
Chris Lutz
I'd just like to note that there are probably better ways to do these, but I thought I'd go ahead and get them out there.
Chris Lutz
A: 

If you are not worried about readability... ;)

String longest(String...ss){String _="";for(String s:ss)if(_.length()<s.length())_=s;return _;}
Peter Lawrey
A: 

i guess it depends on what efficient means. if it means the least amount of characters in the code written, that is one thing. if it means, least amount of memory or fastest executing, that is another.

for fastest executing i'll take the loop.

dbasnett
A: 

in vc++

int findMaxLen(const char *s)
{
    const char c = ',';
    int a = 0, b = 0;
    while(*s)
    {
     while(*s && *s++ != c)b++;
     if(b > a)a=b;
     b = 0;
    }
    return a;
}
Tolgahan Albayrak
A: 

In J

Assume list of boxed strings(L):

{.\:~>#&.>L

An example using a CSV file:

{.\:~;>#&.>readcsv'test.csv'
geocar
Shorter: >./@:(#@>) For example: >./@:(#@>)'Hello';'world!'
ephemient
A: 

In scala (55 chars):

",set,of,random,words".split(",").:\(0)(_.length max _)
Chi
A: 

Clojure: 49 bytes.

(def l #(reduce max(for[x(.split%%2)](count x))))

Legible version:

(defn longest [astr sep]
  (reduce max
    (for [word (.split astr sep)]
      (count word))))

I'm still learning the language, so I'd love to hear any ways to improve it.

nilamo