Loop function advice - python-3.x

I am currently doing a course on the fundamentals of python and I have a question regarding the below loop function:
x = 0
for index in range(5, 10):
x = x + 10
print("The value of X is {}".format(x))
When I print it I get the following result:
The value of X is 10
The value of X is 20
The value of X is 30
The value of X is 40
The value of X is 50
This is where I get confused, I was expecting a result like:
The value of X is 60
The value of X is 70
The value of X is 80
The value of X is 90
The value of X is 100
Am I misunderstanding something?

Here is value of x, index at each loop iteration
Iteration 1. x = 10 + 0 , index = 5
Iteration 2. x = 10 + 10 , index = 6
Iteration 3. x = 10 + 20 , index = 7
Iteration 4. x = 10 + 30 , index = 8
Iteration 5. x = 10 + 40 , index = 9
Thats how your loop will execute

What your function effectively does is to call
x = x + 10
five times. Since it is initialized with x = 0, the output makes sense to me.
The index variable in the loop is not used at all. The following loops would be equivalent:
for _ in range(5, 10):
...
for i in range(0, 5):
...
In your case, it is only about repeating a certain operation 5 times.
If you wanted to have an output as described in the questions, you would need to modify the loop as follows:
x = 10
for i in range(5, 10):
# This loop will be performed for values
# of i of [5, 6, 7, 8, 9], so it includes
# the first value (5) and excludes that last
# one (10)
print(x * i)
>> 50
>> 60
>> 70
>> 80
>> 90

Look at the code line by line:
First, you initialize the variable x to the value 0.
Then you set up a loop which will run five times.
You add 10 to the original value of x, and set that new value to x
You print the value of x.
Repeat 5 times.
x starts at 0, then you add 10, then 10 again, and so on, until the final value is 50. Does that make sense?
To produce the output you are expecting, this is a loop you could use:
>>> x = 0
>>> for index in range(6, 11):
... x = index * 10
... print("The value of X is {}".format(x))
The value of X is 60
The value of X is 70
The value of X is 80
The value of X is 90
The value of X is 100

The initial value of x is set to 0 and in each iteration of the loop you're adding 10 to it. That's why you get these values.

I believe you wanted it something like this.
x = 0
for index in range(6,11):
x = index*10
print("The value of X is {}".format(x))

Related

Python - How to compute the value of n+nn+nnn+nnnn with a given digit as the value of n

Write a program that computes the value of n+nn+nnn+nnnn with a given digit as the value of n.
For example, if n=9 , then you have to find the value of 9+99+999+9999
I need some pointers to make this code dynamic in nature.... Kindly let me know
taking into account k terms and a value n :
(10**np.arange(k)).cumsum().sum()*n
Example
k=4
n=1
(10**np.arange(k)).cumsum().sum()*n
#1234
I assume that parameters are:
k - the number of numbers to sum (e.g. in the title of your post
there are 4 numbers to sum),
n - the digit with increasing number number of occurrences in each
number to sum.
Then the function counting such a sum can be expressed as:
def mySum(k, n):
return n * sum([ n1 * n2 for n1, n2 in zip(
[ i + 1 for i in range(k) ],
[ 10 ** (k - i - 1) for i in range(k) ])])
E.g. mySum(4, 2) gives 2468 (2 + 22 + 222 + 2222).
Details of the above case
If k == 4, but n == 1, we can break the sum into:
1 = 1
11 = 10 + 1
111 = 100 + 10 + 1
1111 = 1000 + 100 + 10 + 1
---------------------------------------------
1234 = 1000 * 1 + 100 * 2 + 10 * 3 + 1 * 4
Note that:
[ i + 1 for i in range(k) ] yields [1, 2, 3, 4],
[ 10 ** (k - i - 1) for i in range(k) ] yields [1000, 100, 10, 1],
so multiplication of these 2 zipped lists yields [1000, 200, 30, 4]
and sum of it is 1234.
Now, if n is e.g. 2, all that remains to be done is to multiply the
abobe sum just by n and this is the result.
Can try this out. Modify the range of loop as per program.
num = int(input("Enter a number: "))
t = 0
total = 0
for a in range(4):
t = num + t*10
total = total + t
print(total)

Cycle through a variable range with another variable

I need to loop through 2 variables and cycle through 1 variable from 2 variables (whichever is bigger) until the range of the 2nd (longest) last.
For example
x = 5 #input by user
y = 8 #input by user
for x_val, y_val in itertools.zip_longest(range(x), range(y), fillvalue='-'):
print(x_val)
print(y_val)
Expected output
0
0
1
1
2
2
3
3
4
4
0
5
1
6
2
7
tried
x = 5
x_cyc = itertools.cycle(range(x))
y = 8
for x_val, y_val in itertools.zip_longest(range(x), x_cyc):
print(x_val)
print(y_val)
but that didn't make much sense.
you dont need zip longest, you create an infinite cycle for the smaller of the two numbers and then normal range for the larger number. this way the min range will be infinite and max range will be the finite range.
You can simply use normal zip to go through them till you reach the end of the non infinite range.
from itertools import cycle
x = 8
y = 5
min_range = cycle(range(min(x, y)))
max_range = range(max(x, y))
for x_val, y_val in zip(min_range, max_range):
print(x_val)
print(y_val)
OUTPUT
0
0
1
1
2
2
3
3
4
4
0
5
1
6
2
7
UPDATE BASED ON COMMENTS
Now the x_val and y_val are bound to the x and y range and the lowest of x or y ints will be cycled in range.
from itertools import cycle
x = 8
y = 5
x_range = range(x)
y_range = range(y)
if x > y:
y_range = cycle(y_range)
elif y > x:
x_range = cycle(x_range)
for x_val, y_val in zip(x_range, y_range):
print(x_val)
print(y_val)
Note that the output will now differ when x is greater than y or when y is greater than x since x will always output first.
OUTPUT x=2, y=3
0
0
1
1
0
2
OUTPUT x=3 y=2
0
0
1
1
2
0

Finding unique triangles given in n number of triangles in python

Given n-number of triangles, we are required to find how many triangles are unique out of given triangles. For each triangle we are given three integers a, b and c (the sides of a triangle).
A triangle is said to be unique if there is no other triangle with same set of sides.
Sample Input:
7 6 5
5 7 6
8 2 9
2 3 4
2 4 3
Sample Output:
1
Explanation:
Each line is a triangle with 3 sides given. The first two triangles are identical since they have similar sides (just the orders are different). ie. the sum of all the sides for both triangles are equal.
The third triangle '8 2 9' is unique since no other triangle has the exact similar sides. So the output is 1 (total number of unique triangles)
Sample Input:
34 5 32
15 20 6
4 2 3
5 6 9
15 20 6
34 5 32
Sample Output:
2
Here the triangles '423' and '560' are unique. So the output is 2 (total number of unique triangles)
This is what I did...
n = int(input())
arr = [list(map(int, input().split())) for x in range(n)]
def uniqueTriangle(arr):
row = len(arr)
col = len(arr[0])
mp = {}
hel = {}
for i in range(row):
tri = arr[i]
tri.sort()
strA = [str(x) for x in tri]
strB = ''
strB = strB.join(strA)
if strB not in mp.values():
mo[i] = strB
else:
hell[i] = strB
count = 0
for i in range(row):
if i in mp:
val = mp.get(i)
if val not in hel.values():
count = count + 1
print (count)
Apologize for the ugly code. But how can I make this code better?
from collections import Counter
arr = [[7, 6, 5],[5, 7, 6],[8, 2, 9],[2, 3, 4],[2, 4, 3]]
def unique_triangles(arr):
counter = Counter([frozenset(a) for a in arr])
return len([res for res in counter if counter[res] == 1])
Use frozenset to mark each unique set of triangle
use collections.Counter to count the number of unique sets found in the input array
return the set appeared only once
This is what I did :
n = int(input())
l=[]
for i in range(n):
t = [int(side) for side in input().split()]
l.append(set(t))
ans=[]
for j in l:
count=0
for i in l:
if i==j:
count+=1
if count==1:
ans.append(j)
print(len(ans))

Python Pandas - Group into list of named tuples

I have the following data
from io import StringIO
import pandas as pd
import collections
stg = """
target predictor value
10 predictor1 A
10 predictor1 C
10 predictor2 1
10 predictor2 2
10 predictor3 X
20 predictor1 A
20 predictor2 3
20 predictor3 Y
30 predictor1 B
30 predictor2 1
30 predictor3 X
40 predictor1 B
40 predictor2 2
40 predictor2 3
40 predictor3 X
40 predictor3 Y
50 predictor1 C
50 predictor2 3
50 predictor3 Y
60 predictor1 C
60 predictor2 4
60 predictor3 Z
"""
I've done this to get the list of predictors and values that have the same list of targets:
src = pd.read_csv(StringIO(stg), delim_whitespace=True, dtype=str)
grouped = src.groupby(["predictor","value"])['target'].apply(','.join).reset_index()
print(grouped)
predictor value target
0 predictor1 A 10,20
1 predictor1 B 30,40
2 predictor1 C 10,50,60
3 predictor2 1 10,30
4 predictor2 2 10,40
5 predictor2 3 20,40,50
6 predictor2 4 60
7 predictor3 X 10,30,40
8 predictor3 Y 20,40,50
9 predictor3 Z 60
From here I ultimately want to create a list of named tuples for each list of targets that represents the predictor and the value
Predicate = collections.namedtuple('Predicate',('predictor', 'value'))
EDIT:
To clarify, I want to create a list of Predicates so in a separate process, I can iterate them and construct query strings like so:
#target 10,20
data_frame.query('predictor1="A"')
#target 10,30
data_frame.query('predictor2="1"')
#target 10,30,40
data_frame.query('predictor3="X"')
#target 20,40,50
data_frame.query('predictor2="3" or predictor3="Y"')
I'd thought to try and use the target list and create a list of predictors and values like so
grouped_list = grouped.groupby('target').agg(lambda x: x.tolist())
print(grouped_list)
predictor value
target
10,20 [predictor1] [A]
10,30 [predictor2] [1]
10,30,40 [predictor3] [X]
10,40 [predictor2] [2]
10,50,60 [predictor1] [C]
20,40,50 [predictor2, predictor3] [3, Y]
30,40 [predictor1] [B]
60 [predictor2, predictor3] [4, Z]
This gives me 2 columns each containing a list. I can iterate these rows like so
for index, row in grouped_list.iterrows():
print("--------")
for pred in row["predictor"]:
print(pred)
But I can't see how to get from here to something like this (which does not work but hopefully illustrates what I mean):
for index, row in grouped_list.iterrows():
Predicates=[]
for pred, val in row["predicate","value"] :
Predicates.append(Predicate(pred, val))
Traceback (most recent call last):
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/core/indexes/base.py", line 2563, in get_value
return libts.get_value_box(s, key)
File "pandas/_libs/tslib.pyx", line 1018, in pandas._libs.tslib.get_value_box
File "pandas/_libs/tslib.pyx", line 1026, in pandas._libs.tslib.get_value_box
TypeError: 'tuple' object cannot be interpreted as an integer
Any pointers would be greatly appreciated - I'm pretty new to python so figuring things out in a step by step fashion - there may be a far better way of achieving the above.
Cheers
David
I think you need list comprehension:
L = [Predicate(x.predictor, x.value) for x in grouped.itertuples()]
print (L)
[Predicate(predictor='predictor1', value='A'),
Predicate(predictor='predictor1', value='B'),
Predicate(predictor='predictor1', value='C'),
Predicate(predictor='predictor2', value='1'),
Predicate(predictor='predictor2', value='2'),
Predicate(predictor='predictor2', value='3'),
Predicate(predictor='predictor2', value='4'),
Predicate(predictor='predictor3', value='X'),
Predicate(predictor='predictor3', value='Y'),
Predicate(predictor='predictor3', value='Z')]
EDIT:
d = {k:[Predicate(x.predictor, x.value) for x in v.itertuples()]
for k,v in grouped.groupby('target')}
print (d)
{'10,30': [Predicate(predictor='predictor2', value='1')],
'30,40': [Predicate(predictor='predictor1', value='B')],
'20,40,50': [Predicate(predictor='predictor2', value='3'),
Predicate(predictor='predictor3', value='Y')],
'10,30,40': [Predicate(predictor='predictor3', value='X')],
'10,40': [Predicate(predictor='predictor2', value='2')],
'10,20': [Predicate(predictor='predictor1', value='A')],
'60': [Predicate(predictor='predictor2', value='4'),
Predicate(predictor='predictor3', value='Z')],
'10,50,60': [Predicate(predictor='predictor1', value='C')]}

Spliting a comma delimitted string into several columns and asigning 0 to nospace

In my data.frame a vector x containing text strings (with six values (from 0 to 100) separated by comma inside each string) in this format:
x[1] "3,2,4,34,2,9"
x[2] "45,,67,,,"
x[3] ",,,,99,"
Here is the link to the actual vector I am having problems with: x.cvs x.cvs
Unfortunately, the value of "0" is recorded as "an empty no space" between the two commas, or before the first comma, or after the last comma.
It would be great first to be able to transform it into:
x[1] "3,2,4,34,2,9"
x[2] "45,0,67,0,0,0"
x[3] "0,0,0,0,99,0"
But most importantly, I would like to split this vector into 6 different vectors x1, x2, x3, x4, x5, x6 and each of them to take the value from the string, and replace "no space" between commas with "0", for example, the result should be:
x1[3] 0
x6[2] 0
I think the strsplit() would have worked if there has been a value between commas, but since there is no value, not even an empty space, I am not sure what is the right way to proceed, without getting NAs.
I tried the following, but it does give me a lot of errors:
x<- as.character(x)
x <- gsub(",,", ",0,", x)
x <- gsub(", ,", ",0,", x)
splitx = do.call("rbind", (strsplit(x, ",")))
splitx = data.frame(apply(splitx, 2, as.numeric))
names(splitx) = paste("x", 1:6, sep = "")
I get errors...
In rbind(c("51", "59", "59", "60", "51", "51"), c("51", "59", "59", :
number of columns of result is not a multiple of vector length (arg 10994)
In apply(splitx, 2, as.numeric) : NAs introduced by coercion
Here are two alternatives to consider, depending on what you are actually expecting as your output.
The first option outputs a set of vectors, but I find that to be a little bit unnecessary and can quickly litter your workspace with lots of objects.
The second option, which I prefer, creates a convenient data.frame with each row representing one of the items from your vector "x".
Sample Data
x <- vector()
x[1] <- "3,2,4,34,2,9"
x[2] <- "45,,67,,,"
x[3] <- ",,,,99,"
Option 1
Names <- paste0("A", seq_along(x))
for (i in seq_along(x)) {
assign(Names[i], {Z <- scan(text=x[i], sep=","); Z[is.na(Z)] <- 0; Z})
}
A1
# [1] 3 2 4 34 2 9
A2
# [1] 45 0 67 0 0 0
A3
# [1] 0 0 0 0 99 0
Option 2
Z <- read.csv(text = x, header = FALSE)
Z[is.na(Z)] <- 0
Z
# V1 V2 V3 V4 V5 V6
# 1 3 2 4 34 2 9
# 2 45 0 67 0 0 0
# 3 0 0 0 0 99 0
Extracting values from a data.frame is as easy as specifying the desired rows and columns.
Z[1, 3]
# [1] 4
Z[2, 4]
# [1] 0
Z[3, c(1, 3, 5)]
# V1 V3 V5
# 3 0 0 99

Resources