A program that prints the longest substring of s in which the letters occur in alphabetical order
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
11
down vote
favorite
Assume
s
is a string of lower case characters.
Write a program that prints the longest substring of
s
in which the letters occur in alphabetical order. For example, ifs = 'azcbobobegghakl'
, then your program should print
Longest substring in alphabetical order is: beggh
In the case of ties, print the first substring. For example, if
s = 'abcbcd'
, then your program should print
Longest substring in alphabetical order is: abc
I have been working on a edX course, MITx: 6.00.1x Introduction to Computer Science and Programming Using Python. Encountering the problem mentioned above, I set out to write a piece of code which I found to be the most disgusting to date(excluding Project Euler draft code).
Note: s
can be any input, but in my case, edX will automatically input a value for s
, so I do not need to define s
.
first=0
second=1
strang1=''
strang2=''
while second<len(s):
if second>=len(s):
break
elif s[first]<=s[second]:
strang1+=s[first:second+1]
while second<=len(s):
second+=1
if second>=len(s):
break
elif s[second]>=strang1[-1]:
strang1+=s[second]
if len(strang1)>len(strang2):
strang2=strang1
else:
if len(strang1)>len(strang2):
strang2=strang1
strang1=''
first=second-1
break
else:
if len(s[first])>len(strang2):
strang2=s[first]
first+=1
second+=1
print("Longest substring in alphabetical order is:" + strang2)
The code can accurately take on any input(if defined) and output it accurately(according to the edX's test runs). I'm looking to make my code more efficient, any suggestions? I'll accept any, fancy newfangled functions or maybe a total rework, I don't mind.
python performance beginner object-oriented python-3.x
add a comment |Â
up vote
11
down vote
favorite
Assume
s
is a string of lower case characters.
Write a program that prints the longest substring of
s
in which the letters occur in alphabetical order. For example, ifs = 'azcbobobegghakl'
, then your program should print
Longest substring in alphabetical order is: beggh
In the case of ties, print the first substring. For example, if
s = 'abcbcd'
, then your program should print
Longest substring in alphabetical order is: abc
I have been working on a edX course, MITx: 6.00.1x Introduction to Computer Science and Programming Using Python. Encountering the problem mentioned above, I set out to write a piece of code which I found to be the most disgusting to date(excluding Project Euler draft code).
Note: s
can be any input, but in my case, edX will automatically input a value for s
, so I do not need to define s
.
first=0
second=1
strang1=''
strang2=''
while second<len(s):
if second>=len(s):
break
elif s[first]<=s[second]:
strang1+=s[first:second+1]
while second<=len(s):
second+=1
if second>=len(s):
break
elif s[second]>=strang1[-1]:
strang1+=s[second]
if len(strang1)>len(strang2):
strang2=strang1
else:
if len(strang1)>len(strang2):
strang2=strang1
strang1=''
first=second-1
break
else:
if len(s[first])>len(strang2):
strang2=s[first]
first+=1
second+=1
print("Longest substring in alphabetical order is:" + strang2)
The code can accurately take on any input(if defined) and output it accurately(according to the edX's test runs). I'm looking to make my code more efficient, any suggestions? I'll accept any, fancy newfangled functions or maybe a total rework, I don't mind.
python performance beginner object-oriented python-3.x
add a comment |Â
up vote
11
down vote
favorite
up vote
11
down vote
favorite
Assume
s
is a string of lower case characters.
Write a program that prints the longest substring of
s
in which the letters occur in alphabetical order. For example, ifs = 'azcbobobegghakl'
, then your program should print
Longest substring in alphabetical order is: beggh
In the case of ties, print the first substring. For example, if
s = 'abcbcd'
, then your program should print
Longest substring in alphabetical order is: abc
I have been working on a edX course, MITx: 6.00.1x Introduction to Computer Science and Programming Using Python. Encountering the problem mentioned above, I set out to write a piece of code which I found to be the most disgusting to date(excluding Project Euler draft code).
Note: s
can be any input, but in my case, edX will automatically input a value for s
, so I do not need to define s
.
first=0
second=1
strang1=''
strang2=''
while second<len(s):
if second>=len(s):
break
elif s[first]<=s[second]:
strang1+=s[first:second+1]
while second<=len(s):
second+=1
if second>=len(s):
break
elif s[second]>=strang1[-1]:
strang1+=s[second]
if len(strang1)>len(strang2):
strang2=strang1
else:
if len(strang1)>len(strang2):
strang2=strang1
strang1=''
first=second-1
break
else:
if len(s[first])>len(strang2):
strang2=s[first]
first+=1
second+=1
print("Longest substring in alphabetical order is:" + strang2)
The code can accurately take on any input(if defined) and output it accurately(according to the edX's test runs). I'm looking to make my code more efficient, any suggestions? I'll accept any, fancy newfangled functions or maybe a total rework, I don't mind.
python performance beginner object-oriented python-3.x
Assume
s
is a string of lower case characters.
Write a program that prints the longest substring of
s
in which the letters occur in alphabetical order. For example, ifs = 'azcbobobegghakl'
, then your program should print
Longest substring in alphabetical order is: beggh
In the case of ties, print the first substring. For example, if
s = 'abcbcd'
, then your program should print
Longest substring in alphabetical order is: abc
I have been working on a edX course, MITx: 6.00.1x Introduction to Computer Science and Programming Using Python. Encountering the problem mentioned above, I set out to write a piece of code which I found to be the most disgusting to date(excluding Project Euler draft code).
Note: s
can be any input, but in my case, edX will automatically input a value for s
, so I do not need to define s
.
first=0
second=1
strang1=''
strang2=''
while second<len(s):
if second>=len(s):
break
elif s[first]<=s[second]:
strang1+=s[first:second+1]
while second<=len(s):
second+=1
if second>=len(s):
break
elif s[second]>=strang1[-1]:
strang1+=s[second]
if len(strang1)>len(strang2):
strang2=strang1
else:
if len(strang1)>len(strang2):
strang2=strang1
strang1=''
first=second-1
break
else:
if len(s[first])>len(strang2):
strang2=s[first]
first+=1
second+=1
print("Longest substring in alphabetical order is:" + strang2)
The code can accurately take on any input(if defined) and output it accurately(according to the edX's test runs). I'm looking to make my code more efficient, any suggestions? I'll accept any, fancy newfangled functions or maybe a total rework, I don't mind.
python performance beginner object-oriented python-3.x
edited May 11 at 10:39
Konrad Rudolph
4,8481431
4,8481431
asked May 11 at 6:53
Durian Jaykin
785
785
add a comment |Â
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
11
down vote
accepted
You should put this code into a function so you are able to easily test and reuse it. Also make yourself familiar with the if __name__ == '__main__':
guard.
Now, for your approach, you basically search for any substring in alphabetical order and, as you do, save the longest for future processing. You could split your code into several smaller functions to help you organize it. A generator of substrings in alphabetical order may be of a great benefit:
def alphabetical_substrings(word):
current_sequence =
last_letter = ''
for letter in word:
if letter >= last_letter:
current_sequence.append(letter)
else:
yield ''.join(current_sequence)
current_sequence =
last_letter = letter
if current_sequence:
yield ''.join(current_sequence)
Then finding the longest is as simple as using the builtin max
with a special key
argument; it has the desired behaviour of returning the first value that matches the maximal criterion:
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
Lastly the tests could look like:
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
You can also simplify the writting of the generator using the pairwise
recipe:
import itertools
def pairwise_letters(iterable):
"""Generate pairs of elements e_n, e_n+1 from iterable.
It is assumed that iterable contains characters and the last
pair will contain its last element and the empty string so as
to break alphabetical ordering.
"""
first, second = itertools.tee(iterable)
next(second, None)
yield from itertools.zip_longest(first, second, fillvalue='')
def alphabetical_substrings(word):
"""Generate the substrings of `word` that appear in alphabetical order"""
current_sequence =
for letter, next_letter in pairwise_letters(word):
current_sequence.append(letter)
if letter > next_letter:
yield ''.join(current_sequence)
current_sequence.clear()
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
1
I used to take 6.00.1x and I think that this answer is out of scope of the edX course the OP was taking. Useful nevertheless.
â svavil
May 12 at 0:14
1
@svavil I agree but itertools is flippin cool, this is pretty useful to know, as well as if name == 'main':, confusing to me at first, but with a little time I should be able to use these functions in other projects.
â Durian Jaykin
May 12 at 2:07
add a comment |Â
up vote
11
down vote
if second>=len(s):
break
This is not necessary. You have just checked that in the loop condition.
first=0
second=1
strang1=''
strang2=''
Consider renaming these variables to say what they do more clearly. Even "begin" and "end" would be clearer than "first" and second, but do not be afraid of longer variable names.
As a rule of thumb, be wary of variable names which you have numbered. They often mean either that they do sufficiently the same thing and you could simplify the code by putting them in a list and looping, or they do not do the same thing and you should name them appropriately. (As is the case here)
strang1+=s[second]
if len(strang1)>len(strang2):
Constructing strings, especially one character at a time, is an expensive operation. You could do this more efficiently by just storing the location in the input string. You can compare sizes just by subtracting the start of that location from the end. At the end of the loop, you can assign the result in one go using s[start:end]
notation.
Assume s is a string of lower case characters.
When you have assumptions like this, it is generally prudent to check them. Coding challenges won't tend to require it. When you have a larger code base and are trying to work out where something went wrong, you'll thank your past self if the first thing that was given input it wasn't designed for is screaming about it so you know where to look.
Thanks for the heads up and all the tips! I will be more clear in my variable names, a bad habit of mine due to how lazy I am as well as I feel the lack of need of them with the relatively short amount of lines I have to write, but it is still a bad habit nonetheless.
â Durian Jaykin
May 12 at 2:10
add a comment |Â
up vote
4
down vote
You could also use regular expressions to search for the string in question:
import re, string
# Regex looks like 'a*b*c*...z*'
alphabetical_order = re.compile('*'.join(string.ascii_lowercase) + '*')
longest_match = max(alphabetical_order.findall(some_string), key=len)
An example run:
In [1]: alphabetical_order.findall('abcbcdcdef')
Out[1]: ['abc', 'bcd', 'cdef', '']
In [2]: max(_, key=len)
Out[2]: 'cdef'
In [3]: max(alphabetical_order.findall('abcbcd'), key=len)
Out[3]: 'abc'
Pros: Very little code required; easy to change "alphabetical order"; strictly-defined alphabet, so no mistakes in case of unexpected input; trivial support for unicode and case-insensitivity.
Cons: Cryptic code; not faster than @MathiasEttinger's solution, unless you make it case-sensitive (in which case it's slightly faster for the same functionality).
re.compile('*'.join(alphabet))
?
â Mathias Ettinger
May 11 at 19:37
@MathiasEttinger you need the trailing '*', so it'd need to bere.compile('*'.join(alphabet) + '*')
which looks a bit less clear to me (but I'm also overly fond of comprehensions and format strings, so others might find that more clear)
â scnerd
May 11 at 20:29
right, or even define the string manually with the stars since you are redefiningstring.ascii_lowercase
anyway.
â Mathias Ettinger
May 11 at 20:33
add a comment |Â
up vote
3
down vote
while second<=len(s):
second+=1
if second>=len(s):
break
These four lines can be replace by for second in range(second+1, len(s)):
.
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
11
down vote
accepted
You should put this code into a function so you are able to easily test and reuse it. Also make yourself familiar with the if __name__ == '__main__':
guard.
Now, for your approach, you basically search for any substring in alphabetical order and, as you do, save the longest for future processing. You could split your code into several smaller functions to help you organize it. A generator of substrings in alphabetical order may be of a great benefit:
def alphabetical_substrings(word):
current_sequence =
last_letter = ''
for letter in word:
if letter >= last_letter:
current_sequence.append(letter)
else:
yield ''.join(current_sequence)
current_sequence =
last_letter = letter
if current_sequence:
yield ''.join(current_sequence)
Then finding the longest is as simple as using the builtin max
with a special key
argument; it has the desired behaviour of returning the first value that matches the maximal criterion:
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
Lastly the tests could look like:
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
You can also simplify the writting of the generator using the pairwise
recipe:
import itertools
def pairwise_letters(iterable):
"""Generate pairs of elements e_n, e_n+1 from iterable.
It is assumed that iterable contains characters and the last
pair will contain its last element and the empty string so as
to break alphabetical ordering.
"""
first, second = itertools.tee(iterable)
next(second, None)
yield from itertools.zip_longest(first, second, fillvalue='')
def alphabetical_substrings(word):
"""Generate the substrings of `word` that appear in alphabetical order"""
current_sequence =
for letter, next_letter in pairwise_letters(word):
current_sequence.append(letter)
if letter > next_letter:
yield ''.join(current_sequence)
current_sequence.clear()
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
1
I used to take 6.00.1x and I think that this answer is out of scope of the edX course the OP was taking. Useful nevertheless.
â svavil
May 12 at 0:14
1
@svavil I agree but itertools is flippin cool, this is pretty useful to know, as well as if name == 'main':, confusing to me at first, but with a little time I should be able to use these functions in other projects.
â Durian Jaykin
May 12 at 2:07
add a comment |Â
up vote
11
down vote
accepted
You should put this code into a function so you are able to easily test and reuse it. Also make yourself familiar with the if __name__ == '__main__':
guard.
Now, for your approach, you basically search for any substring in alphabetical order and, as you do, save the longest for future processing. You could split your code into several smaller functions to help you organize it. A generator of substrings in alphabetical order may be of a great benefit:
def alphabetical_substrings(word):
current_sequence =
last_letter = ''
for letter in word:
if letter >= last_letter:
current_sequence.append(letter)
else:
yield ''.join(current_sequence)
current_sequence =
last_letter = letter
if current_sequence:
yield ''.join(current_sequence)
Then finding the longest is as simple as using the builtin max
with a special key
argument; it has the desired behaviour of returning the first value that matches the maximal criterion:
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
Lastly the tests could look like:
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
You can also simplify the writting of the generator using the pairwise
recipe:
import itertools
def pairwise_letters(iterable):
"""Generate pairs of elements e_n, e_n+1 from iterable.
It is assumed that iterable contains characters and the last
pair will contain its last element and the empty string so as
to break alphabetical ordering.
"""
first, second = itertools.tee(iterable)
next(second, None)
yield from itertools.zip_longest(first, second, fillvalue='')
def alphabetical_substrings(word):
"""Generate the substrings of `word` that appear in alphabetical order"""
current_sequence =
for letter, next_letter in pairwise_letters(word):
current_sequence.append(letter)
if letter > next_letter:
yield ''.join(current_sequence)
current_sequence.clear()
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
1
I used to take 6.00.1x and I think that this answer is out of scope of the edX course the OP was taking. Useful nevertheless.
â svavil
May 12 at 0:14
1
@svavil I agree but itertools is flippin cool, this is pretty useful to know, as well as if name == 'main':, confusing to me at first, but with a little time I should be able to use these functions in other projects.
â Durian Jaykin
May 12 at 2:07
add a comment |Â
up vote
11
down vote
accepted
up vote
11
down vote
accepted
You should put this code into a function so you are able to easily test and reuse it. Also make yourself familiar with the if __name__ == '__main__':
guard.
Now, for your approach, you basically search for any substring in alphabetical order and, as you do, save the longest for future processing. You could split your code into several smaller functions to help you organize it. A generator of substrings in alphabetical order may be of a great benefit:
def alphabetical_substrings(word):
current_sequence =
last_letter = ''
for letter in word:
if letter >= last_letter:
current_sequence.append(letter)
else:
yield ''.join(current_sequence)
current_sequence =
last_letter = letter
if current_sequence:
yield ''.join(current_sequence)
Then finding the longest is as simple as using the builtin max
with a special key
argument; it has the desired behaviour of returning the first value that matches the maximal criterion:
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
Lastly the tests could look like:
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
You can also simplify the writting of the generator using the pairwise
recipe:
import itertools
def pairwise_letters(iterable):
"""Generate pairs of elements e_n, e_n+1 from iterable.
It is assumed that iterable contains characters and the last
pair will contain its last element and the empty string so as
to break alphabetical ordering.
"""
first, second = itertools.tee(iterable)
next(second, None)
yield from itertools.zip_longest(first, second, fillvalue='')
def alphabetical_substrings(word):
"""Generate the substrings of `word` that appear in alphabetical order"""
current_sequence =
for letter, next_letter in pairwise_letters(word):
current_sequence.append(letter)
if letter > next_letter:
yield ''.join(current_sequence)
current_sequence.clear()
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
You should put this code into a function so you are able to easily test and reuse it. Also make yourself familiar with the if __name__ == '__main__':
guard.
Now, for your approach, you basically search for any substring in alphabetical order and, as you do, save the longest for future processing. You could split your code into several smaller functions to help you organize it. A generator of substrings in alphabetical order may be of a great benefit:
def alphabetical_substrings(word):
current_sequence =
last_letter = ''
for letter in word:
if letter >= last_letter:
current_sequence.append(letter)
else:
yield ''.join(current_sequence)
current_sequence =
last_letter = letter
if current_sequence:
yield ''.join(current_sequence)
Then finding the longest is as simple as using the builtin max
with a special key
argument; it has the desired behaviour of returning the first value that matches the maximal criterion:
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
Lastly the tests could look like:
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
You can also simplify the writting of the generator using the pairwise
recipe:
import itertools
def pairwise_letters(iterable):
"""Generate pairs of elements e_n, e_n+1 from iterable.
It is assumed that iterable contains characters and the last
pair will contain its last element and the empty string so as
to break alphabetical ordering.
"""
first, second = itertools.tee(iterable)
next(second, None)
yield from itertools.zip_longest(first, second, fillvalue='')
def alphabetical_substrings(word):
"""Generate the substrings of `word` that appear in alphabetical order"""
current_sequence =
for letter, next_letter in pairwise_letters(word):
current_sequence.append(letter)
if letter > next_letter:
yield ''.join(current_sequence)
current_sequence.clear()
def longest_substring_in_alphabetical_order(word):
return max(alphabetical_substrings(word), key=len)
if __name__ == '__main__':
print(longest_substring_in_alphabetical_order('azcbobobegghakl'))
edited May 11 at 8:14
answered May 11 at 8:02
Mathias Ettinger
21.8k32875
21.8k32875
1
I used to take 6.00.1x and I think that this answer is out of scope of the edX course the OP was taking. Useful nevertheless.
â svavil
May 12 at 0:14
1
@svavil I agree but itertools is flippin cool, this is pretty useful to know, as well as if name == 'main':, confusing to me at first, but with a little time I should be able to use these functions in other projects.
â Durian Jaykin
May 12 at 2:07
add a comment |Â
1
I used to take 6.00.1x and I think that this answer is out of scope of the edX course the OP was taking. Useful nevertheless.
â svavil
May 12 at 0:14
1
@svavil I agree but itertools is flippin cool, this is pretty useful to know, as well as if name == 'main':, confusing to me at first, but with a little time I should be able to use these functions in other projects.
â Durian Jaykin
May 12 at 2:07
1
1
I used to take 6.00.1x and I think that this answer is out of scope of the edX course the OP was taking. Useful nevertheless.
â svavil
May 12 at 0:14
I used to take 6.00.1x and I think that this answer is out of scope of the edX course the OP was taking. Useful nevertheless.
â svavil
May 12 at 0:14
1
1
@svavil I agree but itertools is flippin cool, this is pretty useful to know, as well as if name == 'main':, confusing to me at first, but with a little time I should be able to use these functions in other projects.
â Durian Jaykin
May 12 at 2:07
@svavil I agree but itertools is flippin cool, this is pretty useful to know, as well as if name == 'main':, confusing to me at first, but with a little time I should be able to use these functions in other projects.
â Durian Jaykin
May 12 at 2:07
add a comment |Â
up vote
11
down vote
if second>=len(s):
break
This is not necessary. You have just checked that in the loop condition.
first=0
second=1
strang1=''
strang2=''
Consider renaming these variables to say what they do more clearly. Even "begin" and "end" would be clearer than "first" and second, but do not be afraid of longer variable names.
As a rule of thumb, be wary of variable names which you have numbered. They often mean either that they do sufficiently the same thing and you could simplify the code by putting them in a list and looping, or they do not do the same thing and you should name them appropriately. (As is the case here)
strang1+=s[second]
if len(strang1)>len(strang2):
Constructing strings, especially one character at a time, is an expensive operation. You could do this more efficiently by just storing the location in the input string. You can compare sizes just by subtracting the start of that location from the end. At the end of the loop, you can assign the result in one go using s[start:end]
notation.
Assume s is a string of lower case characters.
When you have assumptions like this, it is generally prudent to check them. Coding challenges won't tend to require it. When you have a larger code base and are trying to work out where something went wrong, you'll thank your past self if the first thing that was given input it wasn't designed for is screaming about it so you know where to look.
Thanks for the heads up and all the tips! I will be more clear in my variable names, a bad habit of mine due to how lazy I am as well as I feel the lack of need of them with the relatively short amount of lines I have to write, but it is still a bad habit nonetheless.
â Durian Jaykin
May 12 at 2:10
add a comment |Â
up vote
11
down vote
if second>=len(s):
break
This is not necessary. You have just checked that in the loop condition.
first=0
second=1
strang1=''
strang2=''
Consider renaming these variables to say what they do more clearly. Even "begin" and "end" would be clearer than "first" and second, but do not be afraid of longer variable names.
As a rule of thumb, be wary of variable names which you have numbered. They often mean either that they do sufficiently the same thing and you could simplify the code by putting them in a list and looping, or they do not do the same thing and you should name them appropriately. (As is the case here)
strang1+=s[second]
if len(strang1)>len(strang2):
Constructing strings, especially one character at a time, is an expensive operation. You could do this more efficiently by just storing the location in the input string. You can compare sizes just by subtracting the start of that location from the end. At the end of the loop, you can assign the result in one go using s[start:end]
notation.
Assume s is a string of lower case characters.
When you have assumptions like this, it is generally prudent to check them. Coding challenges won't tend to require it. When you have a larger code base and are trying to work out where something went wrong, you'll thank your past self if the first thing that was given input it wasn't designed for is screaming about it so you know where to look.
Thanks for the heads up and all the tips! I will be more clear in my variable names, a bad habit of mine due to how lazy I am as well as I feel the lack of need of them with the relatively short amount of lines I have to write, but it is still a bad habit nonetheless.
â Durian Jaykin
May 12 at 2:10
add a comment |Â
up vote
11
down vote
up vote
11
down vote
if second>=len(s):
break
This is not necessary. You have just checked that in the loop condition.
first=0
second=1
strang1=''
strang2=''
Consider renaming these variables to say what they do more clearly. Even "begin" and "end" would be clearer than "first" and second, but do not be afraid of longer variable names.
As a rule of thumb, be wary of variable names which you have numbered. They often mean either that they do sufficiently the same thing and you could simplify the code by putting them in a list and looping, or they do not do the same thing and you should name them appropriately. (As is the case here)
strang1+=s[second]
if len(strang1)>len(strang2):
Constructing strings, especially one character at a time, is an expensive operation. You could do this more efficiently by just storing the location in the input string. You can compare sizes just by subtracting the start of that location from the end. At the end of the loop, you can assign the result in one go using s[start:end]
notation.
Assume s is a string of lower case characters.
When you have assumptions like this, it is generally prudent to check them. Coding challenges won't tend to require it. When you have a larger code base and are trying to work out where something went wrong, you'll thank your past self if the first thing that was given input it wasn't designed for is screaming about it so you know where to look.
if second>=len(s):
break
This is not necessary. You have just checked that in the loop condition.
first=0
second=1
strang1=''
strang2=''
Consider renaming these variables to say what they do more clearly. Even "begin" and "end" would be clearer than "first" and second, but do not be afraid of longer variable names.
As a rule of thumb, be wary of variable names which you have numbered. They often mean either that they do sufficiently the same thing and you could simplify the code by putting them in a list and looping, or they do not do the same thing and you should name them appropriately. (As is the case here)
strang1+=s[second]
if len(strang1)>len(strang2):
Constructing strings, especially one character at a time, is an expensive operation. You could do this more efficiently by just storing the location in the input string. You can compare sizes just by subtracting the start of that location from the end. At the end of the loop, you can assign the result in one go using s[start:end]
notation.
Assume s is a string of lower case characters.
When you have assumptions like this, it is generally prudent to check them. Coding challenges won't tend to require it. When you have a larger code base and are trying to work out where something went wrong, you'll thank your past self if the first thing that was given input it wasn't designed for is screaming about it so you know where to look.
edited May 11 at 11:49
answered May 11 at 7:21
Josiah
3,172326
3,172326
Thanks for the heads up and all the tips! I will be more clear in my variable names, a bad habit of mine due to how lazy I am as well as I feel the lack of need of them with the relatively short amount of lines I have to write, but it is still a bad habit nonetheless.
â Durian Jaykin
May 12 at 2:10
add a comment |Â
Thanks for the heads up and all the tips! I will be more clear in my variable names, a bad habit of mine due to how lazy I am as well as I feel the lack of need of them with the relatively short amount of lines I have to write, but it is still a bad habit nonetheless.
â Durian Jaykin
May 12 at 2:10
Thanks for the heads up and all the tips! I will be more clear in my variable names, a bad habit of mine due to how lazy I am as well as I feel the lack of need of them with the relatively short amount of lines I have to write, but it is still a bad habit nonetheless.
â Durian Jaykin
May 12 at 2:10
Thanks for the heads up and all the tips! I will be more clear in my variable names, a bad habit of mine due to how lazy I am as well as I feel the lack of need of them with the relatively short amount of lines I have to write, but it is still a bad habit nonetheless.
â Durian Jaykin
May 12 at 2:10
add a comment |Â
up vote
4
down vote
You could also use regular expressions to search for the string in question:
import re, string
# Regex looks like 'a*b*c*...z*'
alphabetical_order = re.compile('*'.join(string.ascii_lowercase) + '*')
longest_match = max(alphabetical_order.findall(some_string), key=len)
An example run:
In [1]: alphabetical_order.findall('abcbcdcdef')
Out[1]: ['abc', 'bcd', 'cdef', '']
In [2]: max(_, key=len)
Out[2]: 'cdef'
In [3]: max(alphabetical_order.findall('abcbcd'), key=len)
Out[3]: 'abc'
Pros: Very little code required; easy to change "alphabetical order"; strictly-defined alphabet, so no mistakes in case of unexpected input; trivial support for unicode and case-insensitivity.
Cons: Cryptic code; not faster than @MathiasEttinger's solution, unless you make it case-sensitive (in which case it's slightly faster for the same functionality).
re.compile('*'.join(alphabet))
?
â Mathias Ettinger
May 11 at 19:37
@MathiasEttinger you need the trailing '*', so it'd need to bere.compile('*'.join(alphabet) + '*')
which looks a bit less clear to me (but I'm also overly fond of comprehensions and format strings, so others might find that more clear)
â scnerd
May 11 at 20:29
right, or even define the string manually with the stars since you are redefiningstring.ascii_lowercase
anyway.
â Mathias Ettinger
May 11 at 20:33
add a comment |Â
up vote
4
down vote
You could also use regular expressions to search for the string in question:
import re, string
# Regex looks like 'a*b*c*...z*'
alphabetical_order = re.compile('*'.join(string.ascii_lowercase) + '*')
longest_match = max(alphabetical_order.findall(some_string), key=len)
An example run:
In [1]: alphabetical_order.findall('abcbcdcdef')
Out[1]: ['abc', 'bcd', 'cdef', '']
In [2]: max(_, key=len)
Out[2]: 'cdef'
In [3]: max(alphabetical_order.findall('abcbcd'), key=len)
Out[3]: 'abc'
Pros: Very little code required; easy to change "alphabetical order"; strictly-defined alphabet, so no mistakes in case of unexpected input; trivial support for unicode and case-insensitivity.
Cons: Cryptic code; not faster than @MathiasEttinger's solution, unless you make it case-sensitive (in which case it's slightly faster for the same functionality).
re.compile('*'.join(alphabet))
?
â Mathias Ettinger
May 11 at 19:37
@MathiasEttinger you need the trailing '*', so it'd need to bere.compile('*'.join(alphabet) + '*')
which looks a bit less clear to me (but I'm also overly fond of comprehensions and format strings, so others might find that more clear)
â scnerd
May 11 at 20:29
right, or even define the string manually with the stars since you are redefiningstring.ascii_lowercase
anyway.
â Mathias Ettinger
May 11 at 20:33
add a comment |Â
up vote
4
down vote
up vote
4
down vote
You could also use regular expressions to search for the string in question:
import re, string
# Regex looks like 'a*b*c*...z*'
alphabetical_order = re.compile('*'.join(string.ascii_lowercase) + '*')
longest_match = max(alphabetical_order.findall(some_string), key=len)
An example run:
In [1]: alphabetical_order.findall('abcbcdcdef')
Out[1]: ['abc', 'bcd', 'cdef', '']
In [2]: max(_, key=len)
Out[2]: 'cdef'
In [3]: max(alphabetical_order.findall('abcbcd'), key=len)
Out[3]: 'abc'
Pros: Very little code required; easy to change "alphabetical order"; strictly-defined alphabet, so no mistakes in case of unexpected input; trivial support for unicode and case-insensitivity.
Cons: Cryptic code; not faster than @MathiasEttinger's solution, unless you make it case-sensitive (in which case it's slightly faster for the same functionality).
You could also use regular expressions to search for the string in question:
import re, string
# Regex looks like 'a*b*c*...z*'
alphabetical_order = re.compile('*'.join(string.ascii_lowercase) + '*')
longest_match = max(alphabetical_order.findall(some_string), key=len)
An example run:
In [1]: alphabetical_order.findall('abcbcdcdef')
Out[1]: ['abc', 'bcd', 'cdef', '']
In [2]: max(_, key=len)
Out[2]: 'cdef'
In [3]: max(alphabetical_order.findall('abcbcd'), key=len)
Out[3]: 'abc'
Pros: Very little code required; easy to change "alphabetical order"; strictly-defined alphabet, so no mistakes in case of unexpected input; trivial support for unicode and case-insensitivity.
Cons: Cryptic code; not faster than @MathiasEttinger's solution, unless you make it case-sensitive (in which case it's slightly faster for the same functionality).
edited May 11 at 20:40
answered May 11 at 17:24
scnerd
6438
6438
re.compile('*'.join(alphabet))
?
â Mathias Ettinger
May 11 at 19:37
@MathiasEttinger you need the trailing '*', so it'd need to bere.compile('*'.join(alphabet) + '*')
which looks a bit less clear to me (but I'm also overly fond of comprehensions and format strings, so others might find that more clear)
â scnerd
May 11 at 20:29
right, or even define the string manually with the stars since you are redefiningstring.ascii_lowercase
anyway.
â Mathias Ettinger
May 11 at 20:33
add a comment |Â
re.compile('*'.join(alphabet))
?
â Mathias Ettinger
May 11 at 19:37
@MathiasEttinger you need the trailing '*', so it'd need to bere.compile('*'.join(alphabet) + '*')
which looks a bit less clear to me (but I'm also overly fond of comprehensions and format strings, so others might find that more clear)
â scnerd
May 11 at 20:29
right, or even define the string manually with the stars since you are redefiningstring.ascii_lowercase
anyway.
â Mathias Ettinger
May 11 at 20:33
re.compile('*'.join(alphabet))
?â Mathias Ettinger
May 11 at 19:37
re.compile('*'.join(alphabet))
?â Mathias Ettinger
May 11 at 19:37
@MathiasEttinger you need the trailing '*', so it'd need to be
re.compile('*'.join(alphabet) + '*')
which looks a bit less clear to me (but I'm also overly fond of comprehensions and format strings, so others might find that more clear)â scnerd
May 11 at 20:29
@MathiasEttinger you need the trailing '*', so it'd need to be
re.compile('*'.join(alphabet) + '*')
which looks a bit less clear to me (but I'm also overly fond of comprehensions and format strings, so others might find that more clear)â scnerd
May 11 at 20:29
right, or even define the string manually with the stars since you are redefining
string.ascii_lowercase
anyway.â Mathias Ettinger
May 11 at 20:33
right, or even define the string manually with the stars since you are redefining
string.ascii_lowercase
anyway.â Mathias Ettinger
May 11 at 20:33
add a comment |Â
up vote
3
down vote
while second<=len(s):
second+=1
if second>=len(s):
break
These four lines can be replace by for second in range(second+1, len(s)):
.
add a comment |Â
up vote
3
down vote
while second<=len(s):
second+=1
if second>=len(s):
break
These four lines can be replace by for second in range(second+1, len(s)):
.
add a comment |Â
up vote
3
down vote
up vote
3
down vote
while second<=len(s):
second+=1
if second>=len(s):
break
These four lines can be replace by for second in range(second+1, len(s)):
.
while second<=len(s):
second+=1
if second>=len(s):
break
These four lines can be replace by for second in range(second+1, len(s)):
.
answered May 11 at 15:30
Acccumulation
9395
9395
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f194169%2fa-program-that-prints-the-longest-substring-of-s-in-which-the-letters-occur-in-a%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password