Categories
Posts in this category
- Current State of Exceptions in Rakudo and Perl 6
- Meet DBIish, a Perl 6 Database Interface
- Perl 6 Hackathon in Oslo: Be Prepared!
- Perl 6 Hackathon in Oslo: Report From The First Day
- Perl 6 Hackathon in Oslo: Report From The Second Day
- Rakudo Hack: Dynamic Export Lists
- SQLite support for DBIish
- Upcoming Perl 6 Hackathon in Oslo, Norway
- A shiny perl6.org site
- Creating an entry point for newcomers
- An offer for software developers: free IRC logging
- Sprixel, a 6 compiler powered by JavaScript
- Announcing try.rakudo.org, an interactive Perl 6 shell in your browser
- Another perl6.org iteration
- Blackjack and Perl 6
- Why I commit Crud to the Perl 6 Test Suite
- This Week's Contribution to Perl 6 Week 5: Implement Str.trans
- This Week's Contribution to Perl 6
- This Week's Contribution to Perl 6 Week 8: Implement $*ARGFILES for Rakudo
- This Week's Contribution to Perl 6 Week 6: Improve Book markup
- This Week's Contribution to Perl 6 Week 2: Fix up a test
- This Week's Contribution to Perl 6 Week 9: Implement Hash.pick for Rakudo
- This Week's Contribution to Perl 6 Week 11: Improve an error message for Hyper Operators
- This Week's Contribution to Perl 6 - Lottery Intermission
- This Week's Contribution to Perl 6 Week 3: Write supporting code for the MAIN sub
- This Week's Contribution to Perl 6 Week 1: A website for proto
- This Week's Contribution to Perl 6 Week 4: Implement :samecase for .subst
- This Week's Contribution to Perl 6 Week 10: Implement samespace for Rakudo
- This Week's Contribution to Perl 6 Week 7: Implement try.rakudo.org
- What is the "Cool" class in Perl 6?
- Report from the Perl 6 Hackathon in Copenhagen
- Custom operators in Rakudo
- A Perl 6 Date Module
- Defined Behaviour with Undefined Values
- Dissecting the "Starry obfu"
- The case for distributed version control systems
- Perl 6: Failing Softly with Unthrown Exceptions
- Perl 6 Compiler Feature Matrix
- The first Perl 6 module on CPAN
- A Foray into Perl 5 land
- Gabor: Keep going
- First Grant Report: Structured Error Messages
- Second Grant Report: Structured Error Messages
- Third Grant Report: Structured Error Messages
- Fourth Grant Report: Structured Error Messages
- Google Summer of Code Mentor Recap
- How core is core?
- How fast is Rakudo's "nom" branch?
- Building a Huffman Tree With Rakudo
- Immutable Sigils and Context
- Is Perl 6 really Perl?
- Mini-Challenge: Write Your Prisoner's Dilemma Strategy
- List.classify
- Longest Palindrome by Regex
- Perl 6: Lost in Wonderland
- Lots of momentum in the Perl 6 community
- Monetize Perl 6?
- Musing and the future of feather and the Pugs repository
- Musings on Rakudo's spectest chart
- My first executable from Perl 6
- My first YAPC - YAPC::EU 2010 in Pisa
- Trying to implement new operators - failed
- Programming Languages Are Not Zero Sum
- Perl 6 notes from February 2011
- Notes from the YAPC::EU 2010 Rakudo hackathon
- Let's build an object
- Perl 6 is optimized for fun
- How to get a parse tree for a Perl 6 Program
- Pascal's Triangle in Perl 6
- Perl 6 in 2009
- Perl 6 in 2010
- Perl 6 in 2011 - A Retrospection
- Perl 6 ticket life cycle
- The Perl Survey and Perl 6
- The Perl 6 Advent Calendar
- Perl 6 Questions on Perlmonks
- Physical modeling with Math::Model and Perl 6
- How to Plot a Segment of a Circle with SVG
- Results from the Prisoner's Dilemma Challenge
- Protected Attributes Make No Sense
- Publicity for Perl 6
- PVC - Perl 6 Vocabulary Coach
- Fixing Rakudo Memory Leaks
- Rakudo architectural overview
- Rakudo Rocks
- Rakudo "star" announced
- My personal "I want a PONIE" wish list for Rakudo Star
- Rakudo's rough edges
- Rats and other pets
- The Real World Strikes Back - or why you shouldn't forbid stuff just because you think it's wrong
- Releasing Rakudo made easy
- Set Phasers to Stun!
- Starry Perl 6 obfu
- Recent Perl 6 Developments August 2008
- The State of Regex Modifiers in Rakudo
- Strings and Buffers
- Subroutines vs. Methods - Differences and Commonalities
- A SVG plotting adventure
- A Syntax Highlighter for Perl 6
- Test Suite Reorganization: How to move tests
- The Happiness of Design Convergence
- Thoughts on masak's Perl 6 Coding Contest
- The Three-Fold Function of the Smart Match Operator
- Perl 6 Tidings from September and October 2008
- Perl 6 Tidings for November 2008
- Perl 6 Tidings from December 2008
- Perl 6 Tidings from January 2009
- Perl 6 Tidings from February 2009
- Perl 6 Tidings from March 2009
- Perl 6 Tidings from April 2009
- Perl 6 Tidings from May 2009
- Perl 6 Tidings from May 2009 (second iteration)
- Perl 6 Tidings from June 2009
- Perl 6 Tidings from August 2009
- Perl 6 Tidings from October 2009
- Timeline for a syntax change in Perl 6
- Visualizing match trees
- Want to write shiny SVG graphics with Perl 6? Port Scruffy!
- We write a Perl 6 book for you
- When we reach 100% we did something wrong
- Where Rakudo Lives Now
- Why Rakudo needs NQP
- Why was the Perl 6 Advent Calendar such a Success?
- What you can write in Perl 6 today
- Why you don't need the Y combinator in Perl 6
- You are good enough!
Sat, 09 Oct 2010
Longest Palindrome by Regex
Permanent link
A few hours ago colomon blogged a Perl 6 solution to the longest palindrome programming challenge. It was a bit slow.
An all-regex solution looks like this:
for $string.match(:g, /(\w+) \w? <{ $0.flip }> /) { # process palindrome match here # filter out the longest match }
It's also very slow, and it's very wasteful. So, can there be a hybrid between manual search a regex?
The regex engine is quite fast, and using it to find the center of a palindrome is a good starting point. From there on we can can move to both sides, and compare character by character if moving away from the match still results in a palindrome:
my $s = 'Fourscoreandsevenyearsagoourfaathers...'; my $solution; my $longest = 0; for $s.match(:g, /(\w)\w?$0/) { # $_ now holds a Match object, my $left = .from - 1; my $right = .to; # go to left and right while palindromic while $s.substr($left, 1) eq $s.substr($right, 1) { $left--; $right++; } # we move a bit too far $left++; $right; # and we're only interested in the longest # palindromic substring my $len = $right - $left; if $len > $longest { $solution = $s.substr($left, $right - $left); $longest = $len; } } say $solution;
This now runs in under 1.5 seconds on the 1169 characters long example input string.
Comments / Trackbacks:
Trackback URL:
/blog-en/perl-6/longest-palindrome-regex.trackback
There are typos in that input string.
Tim Bollman wrote
Slight Problems
Due to how the regex engine works, your script has minor problems with finding the center of things that can be considered a palindrome with many centers. For example, use 'abbbbc'. Your script will use 'bbb' as the longest palindrome because of two regex engine particulars. The first is that your regex treats the second part as part of the match, so the next match will start at the end of the current one. Thus your program will try only 'a' 'bbb' 'bc'. When it next tries to match, the remaining string is just 'bc' which doesn't match. In perl5, you could update this using the pos function, I don't know how to do so in perl6. The second is that the perl regex will only give you back one of the two posibilities for a given position if there are two. In this case, it's always the three character version because it's longer than two. This should be more accurate although it doesn't get to use the regex engine.
for 0 .. $s.chars - 2 -> $left
{
if $s.substr($left, 1) eq $s.substr($left + 1, 1) {
my $right = $left + 1;
# do palindrome match
}
if $s.substr($left, 1) eq $s.substr($left + 2, 1) {
my $right = $left + 2;
# do palindrome match
}
}
Klausens wrote
I also wrote a regexp-less version, mainly because i felt 1,5sek a very long time for parsing over a quite short text.
After my script returned the right password I still found several bugs in my code.
The text in the challenge is choosen quite unlucky in my opinion if several buggy scripts anyway return the right result.
Tim Bollman wrote
@Klausens
The 1.5 seconds isn't a statement on the speed of regular expressions, it's a statement on the current speed of Rakudo (not that this should dissuade you from trying perl6, it's awesome). If anything, the regular expression would probably be very slightly faster than the regexp-less version in perl because the regexp given to it should be pretty easy to optimize and presumably the number of potential palindromes is low compared to the number of characters in the string. For comparison, the literal translation of this code into perl5 runs in under a millisecond.
At least for the bugs I gave here, the reason they weren't uncovered in the challenge was because they are very hard to trigger. The challenge creators would have had to create the text specifically to trigger on this if they wanted to catch regexp solutions, because not only does it require the behavior to trigger, it requires it to trigger on the longest palindrome.
Tim Bollman wrote
Regex Improvements
You should be able to change the regex to /(\w)\w$0 | (\w)$0+/ and have it work in all cases (assuming the match re-position issue is handled). Perl5 would require you to say the second character in the first match was not equal to the first character (and to change the $0's to \1 and \2), but Perl6 doesn't need this because it has longest token matching.
Essentially, if there's a sequence of more than one of a letter, you know that you have to pick all of them or else the letter you didn't pick won't match up when you do the extension loop.
It additionally changes the reposition logic from left + 1 to being right - 1 unless it's a 2 character match in which case it's right so you don't infinite loop.
Tim Bollman wrote
Regex Improvements
You should be able to change the regex to /(\w)\w$0 | (\w)$0+/ and have it work in all cases (assuming the match re-position issue is handled). Perl5 would require you to say the second character in the first match was not equal to the first character (and to change the $0's to \1 and \2), but Perl6 doesn't need this because it has longest token matching.
Essentially, if there's a sequence of more than one of a letter, you know that you have to pick all of them or else the letter you didn't pick won't match up when you do the extension loop.
It additionally changes the reposition logic from left + 1 to being right - 1 unless it's a 2 character match in which case it's right so you don't infinite loop.
Moritz wrote
Overlapping match
Tim, you're absolutely right. I should add the :overlap modifier to the regex, which should make it work again.
Write a comment
The comments on this blog post have been disabled; the comment form below will not work.