# Find the longest musical substring

A musical string is any string that can be played on a piano keyboard.

For those of us who weren't forced to learn the piano as kids, here is what the keyboard looks like.

So the string feed a dead cabbage is a musical string because every single letter corresponds to one of these nots.

Your challenge is to write a program that takes a string as input from STDIN, and finds the longest musical substring. Then your program must print the substring, and it's length. Here are some sample inputs/outputs.

Input: "FEED ME! I'm hungry!"

Output: feed 4

Input: No no no, no musistrin!

Ouput: 0

Input: "A **bad** !!!fAd82342"

Output: abadfad 7

Input: "Good golfing!"

Output: dg 2

# Rules

• Your output may be upper or lower-case, but there must be no punctuation or spaces.

• There will capitalization and punctuation in the input string, but this doesn't affect whether or not a substring is considered "musical" or not.

• There must be a space between the musical substring, and the number.

• Full programs only, no functions? – Alex A. May 19 '15 at 1:36
• @AlexA yes, full program. – James May 19 '15 at 1:36
• Can the output be mixed case? – nderscore May 19 '15 at 3:49
• @nderscore yes, it can be. – James May 19 '15 at 4:11

# Pyth, 25 23 bytes

pdJef!-T<G7+k.:@Grz0)lJ


2 bytes saved thanks to @Jakube.

Explanation:

• rz0: The input, in lowercase.
• @Grz0: Strip any non-alphabetic characters.
• .:@Grz0): Generate all substrings.
• +k.:@Grz0): Add in the empty string.
• f ... +k.:@Grz0): Filter over these strings.
• -T<G7: Filter each string for non musical characters.
• !-T<G7: Negate the result. This is True if and only if the string was musical.
• f!-T<G7+k.:@Grz0): Filter out the musical strings.
• ef!-T<G7+k.:@Grz0): Take the last such string. .: orders substrings by size, so this is also the longest musical substring.
• Jef!-T<G7+k.:@Grz0): Assign the result to J.
• pdJ: Print J, with d, space, as the ending character.
• lJ: Then, print the length of J.

# Ruby, 83 75 characters

Fairly self-explanatory.

puts"#{s=gets.gsub(/[^a-z]/i,'').split(/[^a-g]/i).max_by &:size} #{s.size}"


Takes advantage of the fact that Ruby can split strings on regex (.split(/[^a-g]/)).

# Perl, 58

#!perl -p
$\=0;map{$i++;$\="$& $i"if/[a-g]{$i}/i}(s/\W//gr)x y!!!cd


Use:

$perl ~/mus.pl <<<"FEED ME! I'm hungry!" FEED 4  or $ perl -pe'$\=0;map{$i++;$\="$& $i"if/[a-g]{$i}/i}(s/\W//gr)x y!!!cd' <<<"FEED ME! I'm hungry!"
FEED 4


# Java, 268

class Z{public static void main(String[]a){String s=new java.util.Scanner(System.in).nextLine().toLowerCase().replaceAll("[^a-z]",""),t;for(int i=s.length();i-->0;)if(!(t=s.replaceFirst("^(.*)([a-g]{"+i+"})(.*)$","$2")).equals(s)){System.out.println(t+" "+i);break;}}}


Expanded:

class Z {
public static void main(String[] a) {
String s = new java.util.Scanner(System.in).nextLine().toLowerCase().replaceAll("[^a-z]", ""), t;
for (int i = s.length(); i-- > 0;) {
if (!(t = s.replaceFirst("^(.*)([a-f]{" + i + "})(.*)$", "$2")).equals(s)) {
System.out.println(t + " " + i);
break;
}
}
}
}


use List::Util reduce;$_=lc<>;s/[^a-z]//g;$_=reduce{length$a>length$b?$a:$b}m/[a-g]+/g;print"$_ ",0+length  # R, 98 94 bytes p=strsplit(gsub("[^a-z]","",readline(),T),"[^a-gA-G]+")[[1]];m=max(n<-nchar(p));cat(p[n==m],m)  Ungolfed + explanation: # Read from STDIN and remove all non-alphabetic characters r <- gsub("[^a-z]", "", readline(), ignore.case = TRUE) # Split r into a vector of substrings on characters other than a-g p <- strsplit(r, "[^a-g]+")[[1]] # Get the number of characters in each substring n <- nchar(p) # Get the length of the longest substring m <- max(n) # Print the string and length cat(p[n == m], m)  Suggestions are welcome! Note: The output is now mixed-case, which is allowed per the OP's edit. This saved 4 bytes. # golflua, 8485 84 bytes B=I.r():g("%A",""):g("[^a-gA-G]"," ")M=0Q=""~@W B:gm("(%w+)")?#W>M M=#W Q=W$\$w(Q,M)


I first force lowercase, then strip spaces non-letter characters, then remove all non-musical letters on the input (stdin). I then scan through each remaining word and compare its length before outputting the largest and length (stdout). There's probably a shorter way to do the loop, but at the moment this is what I've got.

An ungolfed Lua code would be

Line = io.read()                                  -- read stdin
NoSpaced = Line:gsub("%A","")                     -- strip non-letter chars
MusicalLetters = NoSpaced:gsub("[^a-gA-g]", " ")  -- remove non-musical letters
WordLen = 0, LongWord = ""                        -- helpers
for words in MusicalLetters:gmatch("(%w+)") do    -- scan for longest word
if words:length() > WordLen then
WordLen = words:length()
LongWord = words
end
end
print(LongWord, WordLen)                          -- output solution