Python for loops for noob - python

I'm taking the MIT 6 Programming with Python course for kicks and for a problem set everyone, teach included, wrote their for loop like this:
s="whataboutbob"
for char in range(len(s)):
Isn't that the same as:
s="whataboutbob"
for char in s:
why would someone use the range and len functions if you can just use the variable? What am I missing? I'd ask them but im doing the course solo and the forums are empty-ish. Thanks.

They're not the same thing.
for char in s:
print(char)
Will print the characters in s. I.e 'w', 'h', 'a', etc.
for n in range(len(s)):
print(n)
Will print the numbers 0, 1, 2, etc.

If you need to do some sort of operation with the indices of a list or a string in python, then you would use the range function. In that sense, iterating over a range provides more flexibility.
Another alternative when using a for loop is using the enumerate function. If you were to write
s="whataboutbob"
for n, char in enumerate(s):
then in your loop you would be able to use the variable n to refer to the index in the string, and the variable char to refer to the actual character at that index.

for char in range(len(s)): iterates over numbers from zero to length of string, another loop iterates over characters of string: w,h,a,t,... It is not the same.

The len() function takes the number of characters that you are currently on, starting from 0. For instance in apple, the a would be 0, the p would be 1 etc.
On the other hand
for char in (variable):
print char
would print each letter in that variable, so like
a-p-p-l-e.

It is NOT the same thing:
s="whataboutbob"
for char in s:
print(char)
Would give us a result of
w
h
a
t
a
b
o
u
t
b
o
b
whilst
s="whataboutbob"
for char in range(len(s)):
print(char)
would give us this result:
0
1
2
3
4
5
6
7
8
9
10
11

Related

Trying to solve a Python looping vowel question

I want to solve the below question:
Input_str - "I love Programming in Python"
Initialise 'n_cnt' as 0 and 'output' as 0
v='aeiouAEIOU'
FOR every w in input_str.split()
Initialise cnt to 0
FOR every c in w
check IF c is present in v
if true, increment 'cnt' by 1
end inner for loop
check IF 'cnt' is greater than or equal to 'n_cnt'
if true, assign 'cnt' to 'n_cnt' and assign 'w' to 'output'
end outer for loop
Print 'output'
Here's my code:
Input_str="I love Programming in Python"
n_cnt=0
output=0
v='aeiouAEIOU'
Split=Input_str.split()
for w in Split:
cnt=1
for c in w:
if c in v:
cnt=cnt+1
break
if cnt>=n_cnt:
cnt=n_cnt
output=w
print(output)
What am I doing wrong?
I am not quite sure what your motive is with this program but I assume you want to count the number of vowels in a particular string:
So, here is my implementation:
string = "I love Programming in Python"
vowel_cnt = 0
for i in string:
if i in "aeiouAEIOU":
vowel_cnt += 1
print("number of vowels = ", vowel_cnt)
First, you initialize a counter to 0, then you iterate through all the indices of the string one by one and check if the element at that index is in the String with all the vowels i.e "aeiouAEIOU", if yes, you increment the counter by 1.
First, use StackOverflow code editor to create python indentations, so the code can be easily read. Also, try to state your problem clearly, so when someone solves it, you can check that the result is what you want. The following code seems to be the correct version of your source code, it splits the sentence into words and selects the words that contain one character from v.
Input_str="I love Programming in zzzz Python"
n_cnt=0
output=0
v='aeiouAEIOU'
Split=Input_str.split()
print(Split)
for w in Split:
cnt=1
for c in w:
if c in v:
cnt=cnt+1
break
if cnt >= n_cnt:
n_cnt=cnt
output=w
print(output)
also you said in your question that cnt should be assigned to n_cnt but in your codes you did it incorrectly. The above source code will skip zzzz and print the other words in each line.

Repeat string with a specific pattern without slicing

I'm working on a pretty annoying Python assignment and I'm lost. These are the requirements:
Ask for input.
For each character in the saved string I need to output said string with a certain modification. For example, if the input is abcd the output looks like this:
abcd
bcda
cdab
dabc
I.e. there are len(input) lines, each line begins with the next input[i] character and repeats to the length of the original input.
I should not use slicing, it's loop practice (T_T). No functions or packages. Loops only.
I made a working script that looks like this:
w = input('Type a word:')
w2 = ''
for i, char in enumerate(w):
w2 = w[i:]+w[:i]
print(w2)
It's neat and short. But it will be marked down for slicing. Can Python loop gurus please help me remake it into loops? Thanks so much in advance!
You can use indexing into the original string using a modulo on itself:
w = "aword"
lw = len(w)
for offset in range(lw):
for character in range(lw):
print(w[(offset+character) % lw], end="")
print()
Output:
aword
worda
ordaw
rdawo
dawor
If your sum of offset and character overshoots the amount of characters the modulo operation wraps it around.
If you can't slice strings, you can append and pop lists. So, convert the string to a list and work with list methods.
>>> test = "abcd"
>>> l = list(test)
>>> for _ in range(len(l)):
... print("".join(l))
... l.append(l.pop(0))
...
abcd
bcda
cdab
dabc
Just for fun another one:
s = 'aword'
ss = s * 2 # 'awordaword'
for i in range(len(s)):
for j in range(len(s)):
print(ss[i+j], end='')
print()
Output:
aword
worda
ordaw
rdawo
dawor

How do I return the number of unique digits in a positive integer

Example: unique_dig(123456) All unique
6
I'm trying to write code to have a function return how many unique numbers there are in a positive integer.
count = 0
for i in unique_digits:
if count.has_key(i):
count[i] += 1
else:
count[i] = count + 1
Convert the integer to a string, convert that string to a set of characters, then get the size of the set.
>>> N = 12334456
>>> len(set(str(N)))
6
I am indebted to Stefan Pochmann for teaching me something. (See the comments.)
Here is a solution in pseudocode. You should be able to convert this into Python without too much trouble. Depending on the limitations (I assume this is homework of some kind), you may need to nest a second loop to check each char against the arrayOfUniqueCharacters.
someInputString = "abracadabra"
emptyArrayOfUniqueCharacters = []
FOR char IN someInputString
IF char NOT IN arrayOfUniqueChars
APPEND char TO arrayOfUniqueChars
RETURN length OF arrayOfUniqueChars

Finding common letters between 2 strings in Python

For a homework assignment, I have to take 2 user inputted strings, and figure out how many letters are common (in the same position of both strings), as well as find common letters.. For example for the two strings 'cat' and 'rat', there are 2 common letter positions (which are positions 2 and 3 in this case), and the common letters are also 2 because 'a' is found one and 't' is found once too..
So I made a program and it worked fine, but then my teacher updated the homework with more examples, specifically examples with repetitive letters, and my program isn't working for that.. For example, with strings 'ahahaha' and 'huhu' - there are 0 common letters in same positions, but there's 3 common letters between them (because 'h' in string 2 appears in string 1, three times..)
My whole issue is that I can't figure out how to count if "h" appears multiple times in the first string, as well as I don't know how to NOT check the SECOND 'h' in huhu because it should only count unique letters, so the overall common letter count should be 2..
This is my current code:
S1 = input("Enter a string: ")
S2 = input("Enter a string: ")
i = 0
big_string = 0
short_string = 0
same_letter = 0
common_letters = 0
if len(S1) > len(S2):
big_string = len(S1)
short_string = len(S2)
elif len(S1) < len(S2):
big_string = len(S2)
short_string = len(S1)
elif len(S1) == len(S2):
big_string = short_string = len(S1)
while i < short_string:
if (S1[i] == S2[i]) and (S1[i] in S2):
same_letter += 1
common_letters += 1
elif (S1[i] == S2[i]):
same_letter += 1
elif (S1[i] in S2):
common_letters += 1
i += 1
print("Number of positions with the same letter: ", same_letter)
print("Number of letters from S1 that are also in S2: ", common_letters)
So this code worked for strings without common letters, but when I try to use it with "ahahaha" and "huhu" I get 0 common positions (which makes sense) and 2 common letters (when it should be 3).. I figured it might work if I tried to add the following:
while x < short_string:
if S1[i] in S2[x]:
common_letters += 1
else:
pass
x += 1
However this doesn't work either...
I am not asking for a direct answer or piece of code to do this, because I want to do it on my own, but I just need a couple of hints or ideas how to do this..
Note: I can't use any functions we haven't taken in class, and in class we've only done basic loops and strings..
You need a data structure like multidict. To my knowledge, the most similar data structure in standard library is Counter from collections.
For simple frequency counting:
>>> from collections import Counter
>>> strings = ['cat', 'rat']
>>> counters = [Counter(s) for s in strings]
>>> sum((counters[0] & counters[1]).values())
2
With index counting:
>>> counters = [Counter(zip(s, range(len(s)))) for s in strings]
>>> sum(counters[0] & counters[1].values())
2
For your examples ahahaha and huhu, you should get 2 and 0, respectively since we get two h but in wrong positions.
Since you can't use advanced constructs, you just need to simulate counter with arrays.
Create 26 elements arrays
Loop over strings and update relevant index for each letter
Loop again over arrays simultaneously and sum the minimums of respective indexes.
A shorter version is this:
def gen1(listItem):
returnValue = []
for character in listItem:
if character not in returnValue and character != " ":
returnValue.append(character)
return returnValue
st = "first string"
r1 = gen1(st)
st2 = "second string"
r2 = gen1(st2)
if len(st)> len(st2):
print list(set(r1).intersection(r2))
else:
print list(set(r2).intersection(r1))
Note:
This is a pretty old post but since its got new activity,I posted my version.
Since you can't use arrays or lists,
Maybe try to add every common character to a var_string then test
if c not in var_string:
before incrementing your common counter so you are not counting the same character multiple times.
You are only getting '2' because you're only going to look at 4 total characters out of ahahaha (because huhu, the shortest string, is only 4 characters long). Change your while loop to go over big_string instead, and then add (len(S2) > i) and to your two conditional tests; the last test performs an in, so it won't cause a problem with index length.
NB: All of the above implicitly assumes that len(S1) >= len(S2); that should be easy enough to ensure, using a conditional and an assignment, and it would simplify other parts of your code to do so. You can replace the first block entirely with something like:
if (len(S2) > len(S1)): (S2, S1) = (S1, S2)
big_string = len(S1)
short_string = len(S2)
We can solve this by using one for loop inside of another as follows
int y=0;
for(i=0;i<big_string ;i++)
{
for(j=0;j<d;j++)
{
if(s1[i]==s2[j])
{y++;}
}
If you enter 'ahahaha' and 'huhu' this code take first character of big
string 'a' when it goes into first foor loop. when it enters into second for loop
it takes first letter of small string 'h' and compares them as they are not
equal y is not incremented. In next step it comes out of second for loop but
stays in first for loop so it consider first character of big string 'a' and
compares it against second letter of small string 'u' as 'j' is incremented even
in this case both of them are not equal and y remains zero. Y is incremented in
the following cases:-
when it compares second letter of big string 'h' and small letter of first string y is incremented for once i,e y=1;
when it compares fourth letter of big string 'h' and small letter of first string y is incremented again i,e y=2;
when it compares sixth letter of big string 'h' and small letter of first string y is incremented again i,e y=3;
Final output is 3. I think that is what we want.

Python - build new string of specific length with n replacements from specific alphabet

I have been working on a fast, efficient way to solve the following problem, but as of yet, I have only been able to solve it using a rather slow, nest-loop solution. Anyways, here is the description:
So I have a string of length L, lets say 'BBBX'. I want to find all possible strings of length L, starting from 'BBBX', that differ at, at most, 2 positions and, at least, 0 positions. On top of that, when building the new strings, new characters must be selected from a specific alphabet.
I guess the size of the alphabet doesn't matter, so lets say in this case the alphabet is ['B', 'G', 'C', 'X'].
So, some sample output would be, 'BGBG', 'BGBC', 'BBGX', etc. For this example with a string of length 4 with up to 2 substitutions, my algorithm finds 67 possible new strings.
I have been trying to use itertools to solve this problem, but I am having a bit of difficulty finding a solution. I try to use itertools.combinations(range(4), 2) to find all the possible positions. I am then thinking of using product() from itertools to build all of the possibilities, but I am not sure if there is a way I could connect it somehow to the indices from the output of combinations().
Here's my solution.
The first for loop tells us how many replacements we will perform. (0, 1 or 2 - we go through each)
The second loop tells us which letters we will change (by their indexes).
The third loop goes through all of the possible letter changes for those indexes. There's some logic to make sure we actually change the letter (changing "C" to "C" doesn't count).
import itertools
def generate_replacements(lo, hi, alphabet, text):
for count in range(lo, hi + 1):
for indexes in itertools.combinations(range(len(text)), count):
for letters in itertools.product(alphabet, repeat=count):
new_text = list(text)
actual_count = 0
for index, letter in zip(indexes, letters):
if new_text[index] == letter:
continue
new_text[index] = letter
actual_count += 1
if actual_count == count:
yield ''.join(new_text)
for text in generate_replacements(0, 2, 'BGCX', 'BBBX'):
print text
Here's its output:
BBBX GBBX CBBX XBBX BGBX BCBX BXBX BBGX BBCX BBXX BBBB BBBG BBBC GGBX
GCBX GXBX CGBX CCBX CXBX XGBX XCBX XXBX GBGX GBCX GBXX CBGX CBCX CBXX
XBGX XBCX XBXX GBBB GBBG GBBC CBBB CBBG CBBC XBBB XBBG XBBC BGGX BGCX
BGXX BCGX BCCX BCXX BXGX BXCX BXXX BGBB BGBG BGBC BCBB BCBG BCBC BXBB
BXBG BXBC BBGB BBGG BBGC BBCB BBCG BBCC BBXB BBXG BBXC
Not tested much, but it does find 67 for the example you gave. The easy way to connect the indices to the products is via zip():
def sub(s, alphabet, minsubs, maxsubs):
from itertools import combinations, product
origs = list(s)
alphabet = set(alphabet)
for nsubs in range(minsubs, maxsubs + 1):
for ix in combinations(range(len(s)), nsubs):
prods = [alphabet - set(origs[i]) for i in ix]
s = origs[:]
for newchars in product(*prods):
for i, char in zip(ix, newchars):
s[i] = char
yield "".join(s)
count = 0
for s in sub('BBBX', 'BGCX', 0, 2):
count += 1
print s
print count
Note: the major difference from FogleBird's is that I posted first - LOL ;-) The algorithms are very similar. Mine constructs the inputs to product() so that no substitution of a letter for itself is ever attempted; FogleBird's allows "identity" substitutions, but counts how many valid substitutions are made and then throws the result away if any identity substitutions occurred. On longer words and a larger number of substitutions, that can be much slower (potentially the difference between len(alphabet)**nsubs and (len(alphabet)-1)**nsubs times around the ... in product(): loop).

Categories