The output is 100 but i don't understand why - python

The output is 100 but i don't understand why. Can someone give some insight into how this code works step by step.
def fun(n):
if (n > 100):
return n - 5
return fun(fun(n+11))
print(fun(45))

Decompose your code.
def fun(n):
if (n > 100):
return n - 5
return fun(fun(n+11))
print(fun(45))
> n =45, n > 100 == False, return fun(fun(n + 11))
> fun(45+11) == fun(56), n = 56, 56 > 11 == False, return fun(fun(n + 11))
> fun(56+11), n = 67
> fun(67+11), n = 78
> fun(78+11), n = 89
> fun(89 + 11), n= 100
> fun(100+11), n = 111
> fun(111), n > 100 return 111 - 5
> fun(106), return 106 - 5
> fun(101), return 101 - 5
> fun(96), return fun(fun(96+11))
> fun(107), return 107 - 5
> fun(102), return 102 - 5
> fun(97), return fun(fun(97+11))
> 108 - 5
> 103 - 5
> fun(98)
> 109 - 5
> 104 - 5
> fun(99)
> 110 - 5
> 105 - 5, return 100
And here with code:
def fun(n, s):
space = " " * s
if (n > 100):
print(f"{space} > return {n}-5={n-5}")
return [n - 5, s - 3]
print(f"{space} > return fun(fun({n} + 11))\n {space + ' '} > return fun(fun({n+11}))")
return fun(*fun(n+11, s+3))
print(fun(45, 0))

As it has been pointed in some comments, your best chance is to write down what is going on on paper:
When n is lower than 100, you add 11 to n, and go deeper.
When n is higher than 100, you return n-5, and go higher.
If you want to represent this on paper, you can go down each time you add 11, and return up each time you subtract 5. You'll have your result when surpass your starting point, going up.
START 100
| ^
V |
45 99 99 105
56 98 98 104 110 110
67 97 97 103 109 109
78 96 96 102 108 108
89 101 107 107
100 106
111 111
Since you're experimenting with double recursion, I suppose you're already familiar with recursion; if not, have a look there first!

Related

Cumulative result with specific number in pandas

This is my DataFrame:
index, value
10, 109
11, 110
12, 111
13, 110
14, 108
15, 106
16, 100
I want to build another column based on multippliing by 0,05 with cumulative result.
index, value, result
10, 109, 109
11, 110, 109 + (0,05 * 1) = 109,05
12, 111, 109 + (0,05 * 2) = 109,1
13, 110, 109 + (0,05 * 3) = 109,15
14, 108, 109 + (0,05 * 4) = 109,2
15, 106, 109 + (0,05 * 5) = 109,25
16, 100, 109 + (0,05 * 6) = 109,3
I tried to experiment with shift and cumsum, but nothing works. Can you give me an advice how to do it?
Now I do something like:
counter = 1
result = {}
speed = 0,05
for item in range (index + 1, last_row_index + 1):
result[item] = result[first_index] + speed * counter
counter += 1
P.S. During your answers I've edited column result. Please don't blame me. I am really silly person, but I try to grow.
Thank you all for your answers!
Use numpy:
df['result'] = df['value'].iloc[0]*1.05**np.arange(len(df))
Output:
index value result
0 10 109 109.000000
1 11 110 114.450000
2 12 111 120.172500
3 13 110 126.181125
4 14 108 132.490181
5 15 106 139.114690
6 16 100 146.070425
After you edited the question:
df['result'] = df['value'].iloc[0]+0.05*np.arange(len(df))
output:
index value result
0 10 109 109.00
1 11 110 109.05
2 12 111 109.10
3 13 110 109.15
4 14 108 109.20
5 15 106 109.25
6 16 100 109.30
if indices are consecutive
df['result'] = (df['index'] - df['index'][0]) * 0.05 + df['value'][0]
or not:
df['result'] = df.value.reset_index().index * 0.05 + df.value[0]
df['result'] = np.arange(len(df)) * 0.05
df['result'] = df['value'].add(df['result'])
print(df)
Output:
value result
0 109 109.00
1 110 110.05
2 111 111.10
3 110 110.15
4 108 108.20
5 106 106.25
6 100 100.30

'int' object is not subscriptable on second iteration of loop when trying to convert a string item in a list to a list of integers

I'm new to Python and I'm pretty confused as to why this part of my program is causing problems.
n = int(input())
c = []
l = []
i = 0
while(i<n):
z = int(input())
c.append(z)
x = str(input())
l.append(x)
i += 1
listCount = 0
while(listCount < n ):
binNumber = c[listCount]
dataList = [int(n) for n in l[listCount].split()]
dataList.sort()
listLength = len(dataList)
lowestData = dataList[0]
l = lowestData
while( l <= dataList[listLength-1]):
intervalCounter = 0
traverseCounter = 0
while(traverseCounter < listLength):
if(dataList[traverseCounter] >= l and dataList[traverseCounter] <= l + binNumber - 1):
intervalCounter += 1
traverseCounter += 1
else:
traverseCounter += 1
print( str(l) +'-'+ str(l + binNumber - 1) + ' ' + str(intervalCounter))
l = l + binNumber
print('\b')
listCount += 1
The program outputs correctly on the first iteration of the loop but on the second or more iteration of the loop, it gives me this
Traceback (most recent call last):
File "solution.py", line 21, in <module>
dataList = [int(n) for n in l[listCount].split()]
TypeError: 'int' object is not subscriptable
Does first iteration of the loop change the code in any way to make it behave like this, I'm really confused as to how this works for the first loop but not the second.
The inputs are n test cases followed by 2 lines each first being the intervals and the second line being the values
input
2
10
36 25 38 46 55 68 72 55 36 38 67 45 22 48 91 46 52 61 58 55
50
2 2 1 255 0 3 4 5 6 7 200 100 10 50 0
This is how the output is supposed to be:
22-31 2
32-41 4
42-51 4
52-61 6
62-71 2
72-81 1
82-91 1
0-49 11
50-99 1
100-149 1
150-199 0
200-249 1
250-299 1
But all I get is:
22-31 2
32-41 4
42-51 4
52-61 6
62-71 2
72-81 1
82-91 1

Issue with collatz conjecture in python, loop ends far too early

I wrote a program to check the highest number of steps of the collatz conjecture in a range. However, the number I get is incorrect, it appears that the loop ends far too early. Can anyone tell me what is wrong with my code? I checked multiple times over different ranges and each time it is still wrong.
def collatz_sequence(n):
sequence = []
while n != 1:
sequence.append(n)
if n % 2 == 0:
n = n // 2
elif n % 2 != 0:
n = 3 * n + 1
return sequence
max_len = 1
for i in range(1, 1000):
if len(collatz_sequence(i)) > max_len:
max_len = i
print(max_len)
You are setting max_len to the index of the longest sequence, not its length. You want to keep track of the length of the longest sequence seen so far (and update it for longer sequences as they are seen), rather than its position in the first 1000 sequences. Try:
def collatz_sequence(n):
sequence = []
while n != 1:
sequence.append(n)
if n % 2 == 0:
n = n // 2
elif n % 2 != 0:
n = 3 * n + 1
return sequence
max_len = 1
for i in range(1, 1000):
seq_len = len(collatz_sequence(i))
if seq_len > max_len:
max_len = seq_len
print(i, max_len)
3 7
6 8
7 16
9 19
18 20
25 23
27 111
54 112
73 115
97 118
129 121
171 124
231 127
313 130
327 143
649 144
703 170
871 178
you want to store len(collatz_sequence(i)) in max_len:
max_len = 1
for i in range(1, 1000):
l = len(collatz_sequence(i))
if l > max_len:
max_len = l
print(i, max_len)

Python loop returns false answers and I don't understand why

Here is my code:
def readTogether(path):
ins = open(path, "r")
array = [] # Filtered result
for line in ins:
line = line.replace('\n', '') # Remove empty lines
while ' ' in line:
line = line.replace(' ', ' ') # Remove white space
line = line.strip()
line = line.split(' ')
for elem in line:
# Make sure each element is entered as integer
array.append(int(elem))
ins.close()
return array
mylist = readTogether('B:\Desktop\input.txt') # http://pastebin.com/rDfYCgxP
someint = 0
# n is every number from 0 to the lenght of mylist
for n in range(0, len(mylist)):
# for each "letter" in the n object of mylist (converted to a string)
for x in str(mylist[n]):
# for how many "letters" are in mylist[n]
for y in range(0, len(str(mylist[n]))):
someint += ((int(x) * (int(y) + 1)))
print(someint, end=' ')
someint = 0
The idea is to take every integer and add together the digit * location(digit). For example, 1776 would be 1*1 + 7*2 + 7*3 + 6*4 = 60
Expected outcome was:
13 8 23 81 8 5 0 122 175 203 60 94 210 9 87 66 28 16 21 6 4 0 36 60 36 43 94 42 53 96 12 170 99 141 98 25 96 158 13
Actual outcome:
27 18 45 375 36 5 0 936 1440 1620 210 390 1512 15 567 220 66 27 36 18 4 0 170 270 120 108 435 150 345 728 36 1485 525 1575 728 60 405 1665 150 405 1665 21
Any help is appreciated, since I'm a newbie to Python
here is an example with enumerate built-in function:
mylist = [['1', '7', '7', '6']] # http://pastebin.com/rDfYCgxP
someint = 0
# n is every number from 0 to the lenght of mylist
for value in mylist:
someint = 0
for i, number in enumerate(value, start=1):
someint += i * int(number)
print someint
What does enumerate do? It returns an enumerate object, a list of tuples where first value is an index and second value is a value from given list, e.g:
>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
For more information about enumerate please visit the documentation page.
I think you need to loop over x and y at the same time, e.g. change:
for x in str(mylist[n]):
# for how many "letters" are in mylist[n]
for y in range(0, len(str(mylist[n]))):
someint += ((int(x) * (int(y) + 1)))
to
for y,x in enumerate(str(mylist[n])):
someint += ((int(x) * (y + 1)))
Your current code is looping over each digit x, and then for each digit adding that digit * 1, then that digit * 2, etc., where you only want to include each digit in the sum once.

Is it efficient to perform individual, nested if statements?

I'm working on the following problem:
You are driving a little too fast, and a police officer stops you. Write code to compute the result, encoded as an int value: 0=no ticket, 1=small ticket, 2=big ticket. If speed is 60 or less, the result is 0. If speed is between 61 and 80 inclusive, the result is 1. If speed is 81 or more, the result is 2. Unless it is your birthday -- on that day, your speed can be 5 higher in all cases.
I came up with the following code:
def caught_speeding(speed, is_birthday):
if is_birthday == True:
if speed <= 65:
return 0
elif speed <= 85:
return 1
else:
return 2
else:
if speed <= 60:
return 0
elif speed <= 80:
return 1
else:
return 2
I feel like checking each one individually is a bit inefficient, or is it ok?
You gotta love the bisect module.
def caught_speeding(speed, is_birthday):
l=[60,80]
if is_birthday:
speed-=5
return bisect.bisect_left(l,speed)
I have no problems with your code. It is readable and clear.
If you want to go for less lines then you can do something like this:
def caught_speeding(speed, is_birthday):
adjustment = 5 if is_birthday else 0
if speed <= 60 + adjustment:
return 0
elif speed <= 80 + adjustment:
return 1
else:
return 2
You can do this:
def caught_speeding(speed, is_birthday):
if is_birthday:
speed = speed - 5
if speed <= 60:
return 0
elif speed <= 80:
return 1
else:
return 2
Doing is_birthday == True means you didn't quite get booleans yet ;-)
Check this one. It is optimised:
def caught_speeding(speed, is_birthday):
if speed in range(0,66 if is_birthday else 61):
return 0
elif speed in range(0,86 if is_birthday else 81):
return 1
return 2
Assuming that speed is an integer, and that efficiency means speed of running, not speed of understanding:
>>> def t(speed, is_birthday):
... speed -= 5 * is_birthday
... return speed // 61 + speed // 81
...
>>> for s in xrange(58, 87):
... print s, t(s, False), t(s, True)
...
58 0 0
59 0 0
60 0 0
61 1 0
62 1 0
63 1 0
64 1 0
65 1 0
66 1 1
67 1 1
68 1 1
69 1 1
70 1 1
71 1 1
72 1 1
73 1 1
74 1 1
75 1 1
76 1 1
77 1 1
78 1 1
79 1 1
80 1 1
81 2 1
82 2 1
83 2 1
84 2 1
85 2 1
86 2 2
>>>
def caught_speeding(speed, is_birthday):
speed -= 5 * is_birthday
return 0 if speed < 61 else 2 if speed > 80 else 1

Categories

Resources