9
\$\begingroup\$

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.

piano

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.

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

7 Answers 7

4
\$\begingroup\$

Pyth, 25 23 bytes

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

2 bytes saved thanks to @Jakube.

Demonstration. Test harness.

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

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]/)).

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

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

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;
            }
        }
    }
}
\$\endgroup\$
0
\$\begingroup\$

Perl 5 (106)

use List::Util reduce;$_=lc<>;s/[^a-z]//g;$_=reduce{length$a>length$b?$a:$b}m/[a-g]+/g;print"$_ ",0+length
\$\endgroup\$
0
\$\begingroup\$

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.

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

golflua, 84 85 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
\$\endgroup\$

Your Answer

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

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