for loop with changed iterator - python-3.x

I can't make the iterator shorter while I'm running on it.
I want to write a function which gets a string and deletes repeating sequences in it.
for example:
if a have the string aaaaabbbbbbbcccccccDDDDDDaaaaa
I should get in return abcDa.
I tried to run over the string with a for loop and every time I see a new letter I will save the letter in a variable which adds up to be the fixed string.
def string_sequence_fixing(string):
c = ''
for char in my_str:
if c != char:
c = char
else:
my_str = my_str.replace(c, '', my_str.count(c) - 1)
return my_str
The problem I want to avoid is too many iterations.
When I see a new character I want to delete all the other sequences of it,
but the second line from the end does not update the "condition" in the for a loop.

Short Answer: loops don't work that way.
Longer answer:
Here is some simple pseudo code, for your perusal:
j=99
print "J is " j
for j=0;20;5
print j \t
end
print "Now J is " j
The output may surprise you.
run
J is 99
0 5 10 15 20
Now J is 99
The reason is: the variable j in the loop is NOT the as the j variable outside the loop.
I like to use the term "stack" (some languages claim they don't use a stack. In those cases I call it a "not-stack stack). The stack simple means a temporary storage space in memory.
The initial variable "j" goes into the "program data space". The loop variable "j" goes into the "stack data space."
Using a variable doesn't 'really' mean you are using a variable, it's just a mnemonic to a memory space. Let's have another look at that sample code:
pointer-to-program-space-variable-named-j = 99 (poke into memory location 1:4500)
pointer-to-stack-space-variable-named-j = 0 (poke into memory location 87:300)
print pointer-to-stack-space-variable-named-j followed by tab
increment pointer-to-stack-space-variable-named-j by 5
repeat until pointer-to-stack-space-variable-named-j = 20
print pointer-to-program-space-variable-named-j
With this knowledge, let's look at your code to see what is going on:
def string_sequence_fixing(string):
c = ''
for char in *STACK*.my_str:
if c != char:
c = char
else:
my_str = my_str.replace(c, '', *PROGRAM*.my_str.count(c) - 1)
return my_str
See how they are different variables? NEVER assume that a loop variable and a program variable are the same. You need to redo you algorithm to accomplish what you want to do.
Also, see the link provided by #David Cullen.

You can use groupby() from itertools. Code is like:
data = 'aaabbbcccDDDDDEfggghiij'
from itertools import groupby
dataN = ''
for d in groupby(data):
dataN += d[0]
print(dataN)
output:
abcDEfghij

Related

Print "n" results of a function "n" times

I want to print out a sort of pyramid. User inputs an integer value 'i', and that is displayed i-times.
Like if input=5
1
22
333
4444
55555
I have tried this:
input=5
for i in range(input+1):
print("i"*i)
i=i+1
The result of which is
i
ii
iii
iiii
iiiii
The problem is that (as far as I know), only a string can be printed out 'n' times, but if I take out the inverted commas around "i", it becomes (i*i) and gives out squares:
0
1
4
9
16
25
Is there a simple way around this?
Thanks!
Just convert your int loop varaible to str before building the output string by multiplying:
input = 5
for i in range(1, input+1):
print(str(i) * i)
Try this:
a = 5
for i in range(a): # <-- this causes i to go from 0,1,2,3,...,a-1
print("{}".format(i+1)*(i+1)) # < -- this creates a new string in each iteration ; an alternative would be str(i+1)*(i+1)
i=i+1 # <-- this is unnecessary, i already goes from 0 to a-1 and will be re-created in the next iteration of the loop.
This creates a new string in each iteration of the loop.
Note that for i in range(a) will go through the range by itself. There is no need to additionally increment i at the end. In general it is considered bad practise to change indices you loop over.

calling functions in python 3 from within a function

Given a string, return the count of the number of times that a substring length 2 appears in the string and also as the last 2 chars of the string, so "hixxxhi" yields 1 (we won't count the end substring).
last2('hixxhi') → 1
last2('xaxxaxaxx') → 1
last2('axxxaaxx') → 2
I found this question in one of the websites (https://codingbat.com/prob/p145834).
The answer to the above question as given on the website is as follows :
def last2(str):
# Screen out too-short string case.
if len(str) < 2:
return 0
# last 2 chars, can be written as str[-2:]
last2 = str[len(str)-2:]
count = 0
# Check each substring length 2 starting at i
for i in range(len(str)-2):
sub = str[i:i+2]
if sub == last2:
count = count + 1
return count
I have a doubt on the below mentioned line of code
last2 = str[len(str)-2:]
Now, I know that this piece of code is extracting the last 2 letters of the string 'str'. What I am confused about is the variable name. As you can see that the variable name is same as the name of the function. So is this line calling the function again and updating the value of the variable 'str' ??
def last2(str):
. . .
This creates a parameter called str that shadows the built-in str class*. Within this function, str refers to the str parameter, not the str built-in class.
This is poor practice though. Don't name your variables the same thing as existing builtins. This causes confusing situations like this, and leads to issues like this.
A better name would be something that describes what purpose the string has, instead of just a generic, non-meaningful str.
* The built-in str is actually a class, not a plain function. str(x) is a call to the constructor of the str class.
def last2(str):
if len(str) == 0:
return 0
last_two = str[-2::]
count = 0
for i in range(len(str)):
if last_two == str[i :i + 2]:
count += 1
return count-1
this is the answer that was correct for me for the first time. The official answer is better, but this one might be less confusing for you.

Sorting strings without methods and other types

Hello I have to reorder a string, I am banned from using other types and str methods
So my problem is that I could not figure out how to end my code to get it work with any string
I tried to compare the results with sorted() to check and I am stuck at the first exchange
My code:
i = 0
s1 = "hello"
s2 = sorted(s1)
while (i<len(s1)):
j=i+1
while (j<=len(s1)-1):
if (s1[i] > s1[j]):
s1 = s1[0:i] + s1[j] + s1[i]
j+=1
i+=1
print(s1)
print(s2)
I tried to add + s1[len(s1):] at the end of the operation but
I only had found the result for a single string(that I was testing) adding thisI am really stuck, how can I make it work for all the strings with different lenghts??
Thanks
You're not reconstructing the string correctly when doing s1 = s1[0:i] + s1[j] + s1[i] as you're replacing one character for the other but you omit to actually interchange the two and to add the remains of the splitted string to the end of the new string.
Given what your code looks like, I would do it like this:
i = 0
s1 = "hello"
s2 = sorted(s1)
while i < len(s1):
j = i + 1
while j <= len(s1)-1:
if s1[i] > s1[j]:
s1 = s1[0:i] + s1[j] + s1[i+1:j] + s1[i] + s1[j+1:len(s1)]
j += 1
i += 1
print("".join(s2))
# > 'ehllo'
print(s1)
# > 'ehllo'
Please tell me if anything is unclear!
I am banned from using other types and str methods
Based upon your criteria, your request is impossible. Just accessing the elements of a string requires string methods.
The technique that you are using is very convoluted, hard to read and is difficult to debug. Try running your code in a debugger.
Now given that you are allowed to convert a string to a list (which requires string methods), redesign your code to use simple, easy to understand statements.
The following code first converts the string into a list. Then loops thru the list starting at the beginning and compares each following character to the end. If any character is less then the current character, swap. As you step thru the string, the character swaps will result in a sorted list. At the end convert the list back to a string using join().
msg = 'hello'
s = list(msg)
for i in range(len(s) - 1):
for j in range(i + 1, len(s)):
if s[i] <= s[j]:
continue
# swap characters
s[i], s[j] = s[j], s[i]
print(msg)
print(''.join(s))

How do I achieve this following function only using while loop?

I'm currently working on this problem that ask me to generate an arrow pattern using loops function that looks something like this:
"How many columns? 3"
*
*
*
*
*
I know I can do this with for loop(probably more efficient too), but that is not what I aimed for. I wanted to achieve this only using while loop.
I have some ideas:
1. I set up a control variable and an accumulator to control the loop
2. I then write 2 separate loops to generate the upper and lower part of the pattern. I was thinking about inserting the space before the asterisks using method like this:
(accumulator - (accumulator - integer)) * spaces.
#Ask the user how many column and direction of column
#they want to generate
Keep_going = True
Go = 0
while keep_going:
Column_num = int(input("How many columns? "))
if Column_num <= 0:
print("Invalid entry, try again!")
else:
print()
Go = 1
#Upper part
while Keep_going == True and Go == 1:
print("*")
print(""*(Column_num - (Column_num - 1) + "*")
...but I soon realized it wouldn't work because I don't know the user input and thus cannot manually calculate how many spaces to insert before asterisks. Now everything on the internet tells me to use for loop and range function, I could do that, but I think that is not helpful for me to learn python since I couldn't utilize loops very well yet and brute force it with some other method just not going to improve my skills.
I assume this is achievable only using while loop.
#Take your input in MyNumber
MyNumber = 5
i = 1
MyText = '\t*'
while i <=MyNumber:
print(MyText.expandtabs(i-1))
i = i+1
i = i-1
while i >=1:
print(MyText.expandtabs(i-1))
i = i-1
Python - While Loop
Well first you have to understand that a while loop loops until a requirement is met.
And looking at your situation, to determine the number of spaces before the * you should have an ongoing counter, a variable that counts how many spaces are needed before you continue. For example:
###Getting the number of columns###
while True:
number=int(input('Enter number of rows: '))
if number<=0:
print('Invalid')
else:
###Ending the loop###
break
#This will determine the number of spaces before a '*'
counter=0
#Loops until counter equals number
while counter!=number:
print(" "*counter + "*")
#Each time it loops the counter variable increases by 1
counter=counter+1
counter=counter-1
#Getting the second half of the arrow done
while counter!=0:
counter=counter-1
print(" "*counter + "*")
Please reply if this did not help you so that i can give a more detailed response

Comparing spaces in python

I am creating a cipher script in python without any modules but I have come accross a problem that i cant solve. When I am comparing msg[3] which has the value (space) it should be equal to bet[26] which is also a space. If i compare msg[3] with bet[26] in the shell...
>>>msg[3] == bet[26]
True
The output is True. However when i run the program and output the value of enmsg there is no value 26 where the value 26 should be.
enmsg = []
msg = "try harder"
bet = "abcdefghijklmnopqrstuvwxyz "
for x in range(0, len(msg)):
for i in range(0, 26):
if msg[x] == bet[i]:
print(msg[x])
enmsg.append(i)
You should get out of the habit of iterating over a range of indices and then looking up the value at the index. Instead iterate directly over your iterables, using enumerate when necessary.
enmsg = []
msg = "try harder"
bet = "abcdefghijklmnopqrstuvwxyz "
for msg_char in msg:
for index, bet_char in enumerate(bet):
if msg_char == bet_char:
print(msg_char)
enmsg.append(index)
Your second loop iterations are too short so it is not reaching the space symbol.
Try with this:
enmsg = []
msg = "try harder"
bet = "abcdefghijklmnopqrstuvwxyz "
for x in range(0, len(msg)):
for i in range(len(bet)):
if msg[x] == bet[i]:
print(msg[x])
enmsg.append(i)
The upper bound of range is not inclusive; you'll need to extend this by one to actually check the 26th index of the string. Better yet, iterate up through len(bet) as you did for len(msg) for the outer loop.

Resources