Skip to content

Boyer-Moore algorithm updates #330

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Dec 26, 2016
Merged

Conversation

mmazzei
Copy link
Contributor

@mmazzei mmazzei commented Dec 24, 2016

This is what I did:

  • added some unit tests
  • ensure every test pass
  • added Boyer-Moore-Horspool algorithm (previously mentioned in the README but don't implemented) with tests.
  • added me in the credits section ;)

This fixes #284.

Copy link
Member

@kelvinlauKL kelvinlauKL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work 👍

Thanks for the improvements. I think the changes you've made works and looks great.

I took some time to review the rest of the codebase and I found some things that can be improved upon. I left some comments, let me know what you think of them.

Cheers!

@@ -6,7 +6,7 @@
http://www.drdobbs.com/database/faster-string-searches/184408171
*/
extension String {
func indexOf(pattern: String) -> String.Index? {
func indexOf(pattern: String, useHorspoolImprovement: Bool = false) -> String.Index? {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think index(of pattern: String, useHorspoolImprovement: Bool = false) -> Index? is a better method signature.

Since Swift 3, many methods switched over from indexOf to index(of:). String.Index is unnecessary since we're inside a String extension and the compiler can infer the type of Index.

// If no match, we can only safely skip one character ahead.
i = index(after: i)
}
else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our style guidelines prefer to have the else statement on the same line as the closing brackets for the if statement.

// Cache the length of the search pattern because we're going to
// use it a few times and it's expensive to calculate.
let patternLength = pattern.characters.count
assert(patternLength > 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we should replace these asserts with guard patternLength > 0, characters.count < patternLength else { return nil }. What do you think?

// The pattern is scanned right-to-left, so skip ahead in the string by
// the length of the pattern. (Minus 1 because startIndex already points
// at the first character in the source string.)
var i = self.index(startIndex, offsetBy: patternLength - 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary reference to self. There are a couple of these.

@mmazzei
Copy link
Contributor Author

mmazzei commented Dec 25, 2016

Thanks for the comments!

I agree with the improvements and implemented the changes.

Also updated the playground and made other minor changes (added tests, renamed useHorspoolImprovement to usingHorspoolImprovement).

The new Swift 3 style for method signatures feels more natural.

Regards!

Copy link
Member

@kelvinlauKL kelvinlauKL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good 💯

I've got a minor concern on the new guard !isEmpty else { return nil } statement. This feels redundant since the latter guard patternLength > 0, patternLength <= characters.count else { return nil } would cover that anyway.

}
func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? {
// There are no possible match in an empty string
guard !isEmpty else { return nil }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a bit redundant since the latter guard statement covers this case as well.

func indexOf(pattern: String) -> String.Index? {
func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? {
// There are no possible match in an empty string
guard !isEmpty else { return nil }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before, the latter guard statement should cover this case just as well.

@mmazzei
Copy link
Contributor Author

mmazzei commented Dec 25, 2016

You're right. Redundant validation removed. 👍

@kelvinlauKL
Copy link
Member

Merging this in! Thanks and happy Boxing Day! @mmazzei

@kelvinlauKL kelvinlauKL merged commit 1d7ae6b into kodecocodes:master Dec 26, 2016
@kelvinlauKL kelvinlauKL mentioned this pull request Dec 26, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Duplicate code in Boyer-Moore String Search.md
2 participants