Find the longest musical substring

9

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.

James

Posted 2015-05-19T01:30:04.230

Reputation: 54 537

1Full programs only, no functions? – Alex A. – 2015-05-19T01:36:14.543

@AlexA yes, full program. – James – 2015-05-19T01:36:46.300

Can the output be mixed case? – nderscore – 2015-05-19T03:49:00.000

@nderscore yes, it can be. – James – 2015-05-19T04:11:48.187

Answers

4

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.

isaacg

Posted 2015-05-19T01:30:04.230

Reputation: 39 268

2

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

Doorknob

Posted 2015-05-19T01:30:04.230

Reputation: 68 138

1

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

nutki

Posted 2015-05-19T01:30:04.230

Reputation: 3 634

0

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;
            }
        }
    }
}

Ypnypn

Posted 2015-05-19T01:30:04.230

Reputation: 10 485

0

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.

Alex A.

Posted 2015-05-19T01:30:04.230

Reputation: 23 761

0

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

Kyle Kanos

Posted 2015-05-19T01:30:04.230

Reputation: 4 270

0

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

Ming-Tang

Posted 2015-05-19T01:30:04.230

Reputation: 5 383