What is the meaning of "range( i + 1 )"? - python-3.x

I have a question ,what is the meaning of "range( i + 1 )" below ,if I want to show the output which has xyyzzz?
a = ("x", "y", "z")
for i in range(len(a)):
for j in range( i + 1):
print(a[i])
output: x
y
y
z
z
z

I tried to explain this to you with values
i = 0 ---> j = range(1) = 0 : a[0] = x
--------------------------------
i = 1 ----> j =range(2) = (0,1) : a[1] = y
: a[1] = y
-----------------------------------------
i = 2 ----> j = range(3) = (0,1,2) : a[2] = z
: a[2] = z
: a[2] = z

range(n) gives you values from 0 to n-1.
If you are unfamiliar with Python currently, this can be represented in different ways:
In mathematical interval notation, you can represent this as [0,n) . The left value is included, and the right one is excluded.
Taking len(a) to be 3, the above for loops would be written in C as:
for (int i = 0 ; i < 3 ; ++i){
for (int j = 0 ; j <= i ; ++j){ // note the <= . We can also do j < (i+1)
...
}
}
Your code first calculates len(a), which is 3, since this is a container with 3 elements (this specific container is called a tuple). The first for loop goes from 0 to 2, while the second for loop goes from 0 to wherever the counter of the outer for loop is at (less than or equal to). This causes the first value to be printed just once, next twice, and the last one thrice.
(If you want to test your understanding further, try to figure out what would be printed if we had print(a[j]) inside the loops rather than a[i].)
range() is a versatile and powerful thing in Python, it can do much more than just give you values from 0 to n-1. Do read about it if you intend to use Python.

Related

While Loop doesn't seem to iterate throug the whole list

Code is supposed to sum all numbers given by user input until only a single digit number remains.
Input 19991229 should result in 6, but I'm getting 33 instead, as if the two remaining numbers
aren't summed.
Here's the code:
b_d = input("enter birthdate")
digits = []
for d in b_d:
digits.append(int(d))
print(digits)
life = 0
while (sum(digits)) >= 10 :
for x in digits:
life += x
digits.remove(x)
print(life)
this resolves the issue, but it's too ad hoc and doesn't work on all cases:
r = 0
for y in str(life):
r += int(y)
print(y)

Why isn't my for loop working, but my while loop is?

[Sorry in advance, I'm very new to programming.]
This is for project euler problem #2. The goal is to calculate the sum of all even fibonacci numbers that do not exceed 4 million. For anyone not familiar with fibonacci numbers, a fibonacci number is simply a number that is the sum of the two previous numbers in the sequence. For example, the first few fibonacci numbers are 1,2,3,5,8,13,21,34 ...
My code is below beginning with some variables, then my while loop, and finally my for loop.
n = 0
n2 = 1
fibsum = 0
fibrange = range(1,4000001)
while (n2 <= 4000000):
n2 = n2 + n
n = n2 - n
if n2 % 2 == 0:
fibsum += n2
print (fibsum)
# for n2 in fibrange:
# n2 = n2 + n
# n = n2 - n
# if n2 % 2 == 0:
# fibsum += n2
# print(fibsum)
As I said, my while loop works like a charm, but when I run the for loop the output of fibsum is 0. So the value is not changing at all.
I've tried range (1, 4000001) in place of fibrange. I really have no idea what else to try. This is like my 4th or 5th program ever.
Using for loop in range function, The Value of the variable n2 changes according only to range function.You cannot manually change the variable in for loop while using range function.
for and while and are different types of loops.
while: Repeats a statement or group of statements while a given condition is TRUE. It tests the condition before executing the loop body.
for: Executes a sequence of statements multiple times and abbreviates the code that manages the loop variable.
With while you can do something like this:
a = 0
b = 1
target = 4000000
result = 0
while a <= target:
if a % 2 == 0:
result +=a
a, b = b, a + b
print(result)
With for:
a, b = 0, 1
result = 0
target = 4000000
fib_sequence = 35 # -> the length of fibonacci sequence
for _ in range(fib_sequence):
if a % 2 == 0:
result +=a
a, b = b, a + b
if a >= target: break
print(result)

Nested loop in python3

How does a nested loop work?
I tried to make a triangle this is my code:
x = 0
string = ""
while x <= 5:
y = x
while y > 0:
string = string + "*"
y = y - 1
string = string + "\n"
x = x + 1
print(string)
But it came out like this And this is the output:
*
**
***
****
*****
How does a nested loop work in python?
You must debug your code to understand how the nested loop works
for your code, the nested loop will work as following,
for each x where x= 5 the while loop of y will run for 5 times,
then again,
when x=4 the while loop of y will run for 4 times,
and as per this the while loop of x will have 5 iterations and the while loop of y will have about 15 iterations equivalent to number of stars in your pyramid or pattern.

Cut K sequences of length L to obtain the biggest number

We have a number of N digits (it can start with 0). We must find the biggest number which can be obtained cutting K disjoint sequences of length L.
N can be very big so our number should be stored as a string.
Example 1)
nr = 12122212212212121222
K = 2, L = 3
answer: 22212212221222
We can cut "121" (from 0th digit) and "121" (from 12th digit).
Example 2)
nr = 0739276145
K = 3, L = 3
answer: 9
We can cut "073", "276" and "145".
I have tried something like this:
void cut(string str, int K, int L) {
if (K == 0)
return;
// here we cut a single sequence of length L
// in a way that the new number is the biggest
cut(str, K - 1, L);
}
But in this way, I can cut 2 sequences which in the initial number are not disjoint, so my method it's not correct. Please help me solve the problem!
You can define cutsrecursively:
cuts(s, 0, L) = s
cuts(s, K, L) = max(s[i:j] + cuts(s[j+L:], K-1, L) for j=i..len(s)-K*L)
As is normal in these problems, you can use dynamic programming to avoid an exponential runtime. You can probably avoid so much string slicing and appending, but this is an example solution in Python:
def cuts(s, K, L):
dp = [s[i:] for i in xrange(len(s)+1)]
for k in xrange(1, K+1):
dp = [max(s[i:j] + dp[j+L] for j in xrange(i, len(dp)-L))
for i in xrange(len(dp)-L)]
return dp[0]
print cuts('12122212212212121222', 2, 3)
print cuts('0739276145', 3, 3)
Output:
22212212221222
9

String lexicographical permutation and inversion

Consider the following function on a string:
int F(string S)
{
int N = S.size();
int T = 0;
for (int i = 0; i < N; i++)
for (int j = i + 1; j < N; j++)
if (S[i] > S[j])
T++;
return T;
}
A string S0 of length N with all pairwise distinct characters has a total of N! unique permutations.
For example "bac" has the following 6 permutations:
bac
abc
cba
bca
acb
cab
Consider these N! strings in lexicographical order:
abc
acb
bac
bca
cab
cba
Now consider the application of F to each of these strings:
F("abc") = 0
F("acb") = 1
F("bac") = 1
F("bca") = 2
F("cab") = 2
F("cba") = 3
Given some string S1 of this set of permutations, we want to find the next string S2 in the set, that has the following relationship to S1:
F(S2) == F(S1) + 1
For example if S1 == "acb" (F = 1) than S2 == "bca" (F = 1 + 1 = 2)
One way to do this would be to start at one past S1 and iterate through the list of permutations looking for F(S) = F(S1)+1. This is unfortunately O(N!).
By what O(N) function on S1 can we calculate S2 directly?
Suppose length of S1 is n, biggest value for F(S1) is n(n-1)/2, if F(S1) = n(n-1)/2, means it's a last function and there isn't any next for it, but if F(S1) < n(n-1)/2, means there is at least one char x which is bigger than char y and x is next to y, find such a x with lowest index, and change x and y places. let see it by example:
S1 == "acb" (F = 1) , 1 < 3 so there is a char x which is bigger than another char y and its index is bigger than y, here smallest index x is c, and by first try you will replace it with a (which is smaller than x so algorithm finishes here)==> S2= "cab", F(S2) = 2.
Now let test it with S2, cab: x=b, y=a, ==> S3 = "cba".\
finding x is not hard, iterate the input, and have a variable name it min, while current visited character is smaller than min, set min as newly visited char, and visit next character, first time you visit a character which is bigger than min stop iteration, this is x:
This is pseudocode in c# (but I wasn't careful about boundaries e.g in input.Substring):
string NextString(string input)
{
var min = input[0];
int i=1;
while (i < input.Length && input[i] < min)
{
min = input[i];
i++;
}
if (i == input.Length) return "There isn't next item";
var x = input[i], y=input[i-1];
return input.Substring(0,i-2) + x + y + input.Substring(i,input.Length - 1 - i);
}
Here's the outline of an algorithm for a solution to your problem.
I'll assume that you have a function to directly return the n-th permutation (given n) and its inverse, ie a function to return n given a permutation. Let these be perm(n) and perm'(n) respectively.
If I've figured it correctly, when you have a 4-letter string to permute the function F goes like this:
F("abcd") = 0
F("abdc") = 1
F(perm(3)) = 1
F(...) = 2
F(...) = 2
F(...) = 3
F(perm(7)) = 1
F(...) = 2
F(...) = 2
F(...) = 3
F(...) = 3
F(...) = 4
F(perm(13)) = 2
F(...) = 3
F(...) = 3
F(...) = 4
F(...) = 4
F(...) = 5
F(perm(19)) = 3
F(...) = 4
F(...) = 4
F(...) = 5
F(...) = 5
F(perm(24)) = 6
In words, when you go from 3 letters to 4 you get 4 copies of the table of values of F, adding (0,1,2,3) to the (1st,2nd,3rd,4th) copy respectively. In the 2nd case, for example, you already have one derangement by putting the 2nd letter in the 1st place; this simply gets added to the other derangements in the same pattern as would be true for the original 3-letter strings.
From this outline it shouldn't be too difficult (but I haven't got time right now) to write the function F. Strictly speaking the inverse of F isn't a function as it would be multi-valued, but given n, and F(n) there are only a few cases for finding m st F(m)==F(n)+1. These cases are:
n == N! where N is the number of letters in the string, there is no next permutation;
F(n+1) < F(n), the sought-for solution is perm(n+(N-1)!), ;
F(n+1) == F(n), the solution is perm(n+2);
F(n+1) > F(n), the solution is perm(n+1).
I suspect that some of this might only work for 4 letter strings, that some of these terms will have to be adjusted for K-letter permutations.
This is not O(n), but it is at least O(n²) (where n is the number of elements in the permutation, in your example 3).
First, notice that whenever you place a character in your string, you already know how much of an increase in F that's going to mean -- it's however many characters smaller than that one that haven't been added to the string yet.
This gives us another algorithm to calculate F(n):
used = set()
def get_inversions(S1):
inv = 0
for index, ch in enumerate(S1):
character = ord(ch)-ord('a')
cnt = sum(1 for x in range(character) if x not in used)
inv += cnt
used.add(character)
return inv
This is not much better than the original version, but it is useful when inverting F. You want to know the first string that is lexicographically smaller -- therefore, it makes sense to copy your original string and only change it whenever mandatory. When such changes are required, we should also change the string by the least amount possible.
To do so, let's use the information that the biggest value of F for a string with n letters is n(n-1)/2. Whenever the number of required inversions would be bigger than this amount if we didn't change the original string, this means we must swap a letter at that point. Code in Python:
used = set()
def get_inversions(S1):
inv = 0
for index, ch in enumerate(S1):
character = ord(ch)-ord('a')
cnt = sum(1 for x in range(character) if x not in used)
inv += cnt
used.add(character)
return inv
def f_recursive(n, S1, inv, ign):
if n == 0: return ""
delta = inv - (n-1)*(n-2)/2
if ign:
cnt = 0
ch = 0
else:
ch = ord(S1[len(S1)-n])-ord('a')
cnt = sum(1 for x in range(ch) if x not in used)
for letter in range(ch, len(S1)):
if letter not in used:
if cnt < delta:
cnt += 1
continue
used.add(letter)
if letter != ch: ign = True
return chr(letter+ord('a'))+f_recursive(n-1, S1, inv-cnt, ign)
def F_inv(S1):
used.clear()
inv = get_inversions(S1)
used.clear()
return f_recursive(len(S1), S1, inv+1, False)
print F_inv("acb")
It can also be made to run in O(n log n) by replacing the innermost loop with a data structure such as a binary indexed tree.
Did you try to swap two neighbor characters in the string? It seems that it can help to solve the problem. If you swap S[i] and S[j], where i < j and S[i] < S[j], then F(S) increases by one, because all other pairs of indices are not affected by this permutation.
If I'm not mistaken, F calculates the number of inversions of the permutation.

Resources