how to get the output in list as expected - python-3.x

how to find the output from the list1 when reversed it should be excluded from the output
example:
32 reverse is 23 which is already in list l1 so that should be excluded. Similarly 98 reverse is 89 hence output shud be as below.
l1=[32,48,98,76,23,89]
output as [48,76]
tried this
l2=[]
x=[str(x) for x in l1]
print(x)
for var in x:
print(var,var[::-1])
o/p as below
32 23
48 84
98 89
76 67
23 32
89 98
if the reverse 32 is 23 then exclude it..

You have successfully reversed the items in the input list.
Now all you need to do is check if the reversed items are present in the input list or not. If not, then append those items to an output list.
Try this.
l1=[32,48,98,76,23,89, 470, 74]
l2=[]
x=[str(x) for x in l1]
print(x)
out = []
for var in x:
# print(var,var[::-1])
if int(var[::-1]) not in l1:
out.append(int(var))
print(out) #[48, 76, 74]
Another approach without typecasting to string is below:
l1=[32,48,98,76,23,89, 470, 74]
out = []
for num in l1:
rev = 0
curr = num
while curr >0:
rev = rev*10+curr%10
curr = curr//10
if rev not in l1:
out.append(num)
print(out) # [48, 76, 74]
Note that both these approaches work only when the list contains whole numbers only.
Also this will also work for a number that ends in 0.
For example: if the input list contains 470 and 74, then 470 will be excluded from the output.
As reverse of '470' = '074' and int('074') = 74, hence this item will be excluded.

Related

A Rule of Divisibility by 13 - Codewars python challenge (RecursionError)

Instructions:
When you divide the successive powers of 10 by 13 you get the following remainders of the integer divisions:
1, 10, 9, 12, 3, 4.
Then the whole pattern repeats.
Hence the following method: Multiply the right most digit of the number with the left most number in the sequence shown above, the second right most digit to the second left most digit of the number in the sequence. The cycle goes on and you sum all these products. Repeat this process until the sequence of sums is stationary.
...........................................................................
Example: What is the remainder when 1234567 is divided by 13?
7×1 + 6×10 + 5×9 + 4×12 + 3×3 + 2×4 + 1×1 = 178
We repeat the process with 178:
8x1 + 7x10 + 1x9 = 87
and again with 87:
7x1 + 8x10 = 87
...........................................................................
From now on the sequence is stationary and the remainder of 1234567 by 13 is the same as the remainder of 87 by 13: 9
Call thirt the function which processes this sequence of operations on an integer n (>=0). thirt will return the stationary number.
thirt(1234567) calculates 178, then 87, then 87 and returns 87.
thirt(321) calculates 48, 48 and returns 48
My Code:
def thirt(n):
a = []
n = [int(i) for i in list(str(n))][::-1]
l = [1, 10, 9, 12, 3, 4][:len(n)]
y = sum([a * b for a,b in zip(n,l)])
a.append(y)
for c in a:
if a.count(c) == 1:
thirt(c)
else:
return c
thirt(5634)
When I run this I get an error
Traceback (most recent call last):
File "main.py", line 5, in <module>
Test.assert_equals(thirt(8529), 79)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
[Previous line repeated 994 more times]
File "/home/codewarrior/solution.py", line 3, in thirt
n = [int(i) for i in list(str(n))][::-1]
RecursionError: maximum recursion depth exceeded while getting the str of an object
when I remove some part of the code and leave it like
def thirt(n):
n = [int(i) for i in list(str(n))][::-1]
l = [1, 10, 9, 12, 3, 4][:len(n)]
y = sum([a * b for a,b in zip(n,l)])
return y
thirt(5634)
I get 148 in the output, and then I thirt(148), I get 57, which is the desired answer, same goes for other examples as well.
so I just need a proper way to recur this function, and I just want it to stop as soon as the values start repeating, i.e. I want the loop of recursion to break as soon as I get two 57's in a row, and then I need it to return 57.
But I can't figure out a proper way to do it, because this is the first time I've applied recursion in a function, my code is really messed up, I'll really appreciate any help.
You are getting the error depth exceeded while getting the str of an object because you are assigning the list of digits n to the same variable name as the function parameter n. That means after the first recursive call, you are running [int(i) for i in list(str(n))][::-1] on a list of individual digits, and then a list of lists, and so on, rather than a single input number as you're expecting.
Once you fix that, you run into the issue of how you are checking for whether to make the recursive call:
a = []
a.append(y)
for c in a:
if a.count(c) == 1:
thirt(c)
I can see what you're trying to do, and it will not work in recursion because every time the function is called, a is reset to an empty list. That means a.count(c) == 1 is always true, and your function will go into an infinite recursive loop.
Instead, for this algorithm all you need to do is check whether your newly calculated y is equal to the number n that was passed to the function. If they're the same, that means you've gotten the same number twice in a row, so the algorithm is done.
After that is fixed, it will look like you're getting somewhere. You can use this logic:
if n != y:
thirt(y)
else:
print(y) # expected answer outputted to console
return y
Except when you call thirt(1234567), the value returned is None ! What the heck? I printed y and it's correct, it's right there! What is happening is, the inner-most call to thirt is returning the number you need, but then the next level up in the function call stack doesn't do anything with it. So the function ends and returns None. To fix this, you need each level of the recursive call to pass its return value up the chain. So use return thirt(y) instead of just thirt(y).
Finally, you need to account for the case when the number passed to the function is longer than 6 digits. Your l list needs to repeat in a cycle, not stop with the 6 numbers you've listed. You can get the list to be the length you need by multiplying it by the length of n divided by six, rounded up whenever there's a remainder.
After all that, you'll end up with something like the following:
def thirt(n):
nList = [int(i) for i in list(str(n))][::-1]
remainders = [1, 10, 9, 12, 3, 4] * (
len(nList) // 6 + min(1, len(nList) % 6)
)
y = sum([a * b for a,b in zip(nList,remainders)])
if n != y:
return thirt(y)
else:
return y
print(thirt(1234567)) #87
Isn't this what you mean?
def thirt(n_raw):
a = []
n = [int(i) for i in list(str(n_raw))][::-1]
l = [1, 10, 9, 12, 3, 4]*(len(n)//6+1)
y = sum([a * b for a,b in zip(n,l)])
if(y==n_raw): return y
else: return thirt(y)
I think you just went in a very wrong direction with the second half of your function, but I might misunderstood the premise behind...

I want to get/print df by range instead of head or tail

I can't find or understand how to get the data I want by range
I want to know how to get df['Close']from x to y then .mean to sum it up
I have tried "costomclose = df['Close'],range(dagartot,val)"
But it gives me something else like heads and tails from df
if len(df) >= 34:
dagartot = len(df)
valdagar = 5
val = dagartot-valdagar
costomclose = df['Close'],range(dagartot,val)
print(costomclose)
edit:
<bound method NDFrame.tail of High Low ... Volume Adj Close
Date ...
2005-09-29 24.083300 23.583300 ... 74400.0 4.038682
2005-09-30 23.833300 23.500000 ... 148200.0 4.081495
2005-10-03 24.000000 23.333300 ... 27600.0 3.995869
2005-10-04 23.500000 23.416700 ... 132000.0 4.024417
2005-10-05 23.750000 23.500000 ... 15600.0 4.067230
... ... ... ... ... ...
2019-07-25 196.000000 193.050003 ... 355952.0 194.000000
2019-07-26 196.350006 194.000000 ... 320752.0 195.199997
2019-07-29 196.350006 193.550003 ... 301389.0 195.250000
2019-07-30 197.949997 194.850006 ... 233989.0 197.100006
2019-07-31 198.550003 195.600006 ... 323473.0 197.899994
[3479 rows x 6 columns]>
stop
Here is an example of slicing out the middle of something based on the encounter index:
>>> s = pd.Series(list('abcdefghijklmnop'))
>>> s
Out[135]:
0 a
1 b
...
12 m
13 n
14 o
15 p
dtype: object
>>> s.iloc[6:9]
Out[136]:
6 g
7 h
8 i
dtype: object
This also works for DataFrames, e.g. df.iloc[0] returns the first row and df.iloc[5:8] returns those rows, end not included.
You can also slice by actual index of the DataFrame, which is not necessarily a serially-counting sequence of integers by substituting iloc for loc.
Here is an example of slicing out the middle of a dataframe that stores the alphabet:
>>> df = pd.DataFrame([dict(num=i + 65, char=chr(i + 65)) for i in range(26)])
>>> df[(76 <= df.num) & (df.num < 81)]
num char
11 76 L
12 77 M
13 78 N
14 79 O
15 80 P

How to take user input when it is seperated by any number of spaces and line breaks in python?

I have been trying to take integer inputs seperated by any number of white spaces or line breaks. I know how to take space seperated outputs and outputs having line breaks. In C based languages we don't have to care about where the input is, it automatically takes the input when found, but I don't think this is the case with Python(correct me if I am wrong). Can anybody help?
I tried using a While statement till True and using a try statement in it. But it doesn't work.
a = []
try:
while(True):
a.append(int(input()))
except:
pass
print(a)
when i input
12 12
12
it returns an empty list. If i remove the int in the input it returns a list [12 12, 12].
Try this: The Shortest way possible
a = []
s=input()
while s != '':
i = s.split()
[a.append(int(j)) for j in i]
s=input()
print(a)
Input:
1 2 3
4 5
6
Output:
[1, 2, 3, 4, 5, 6]
You can also try:
a = []
s=input()
while s != '':
i = s.split()
a.extend(map(lambda s: int(s),i))
s=input()
print(a)
Wait, so I think I understand it now. You want to accept any amount of input, but save each input separated by whitespace as its own entry? There is actually a string method for that. Here's an example script for it. It's not the best, but it demonstrates the method pretty well.
list = []
string = "user input goes here"
splitString = string.split()
for word in splitString:
list.append(word)
print(list)
Output:
["user", "input", "goes", "here"]
The string.split() method uses space by default, but you can specify another delimiter like the # sign.
List = []
String = "Hi#my#name#is#bob"
newString = String.split("#")
for word in newString:
list.append(word)
EDIT: Here is a full working implementation that will work whether the thing separating two inputs is whitespace, newlines, or anything else you'd like.
import re
list = []
while True:
string = input()
if string == "break":
break
splitString = re.split("[\s | \r\n]", string)
for word in splitString:
list.append(word)
cleanList = []
for word in list:
if word != '':
cleanList.append(word)
print(cleanList)
Input:
12 94 17
56
3
Output:
[12, 94, 17, 56, 3]
Functional proof: Click here
Hope you will some insight in this example & have added my personal view of how to code.
Firstly, giving input with multi-spaces is understandable but not multi-lines. Prefer taking input one by one.
For testing & debugging purposes, prefer separate collecting user and processing input data.
Now, say you have collected your user input and stored as data using raw_input, which is handy when you need to collect multiline inputs. Please explore raw_input, it is supported in Python3 and Python2.
>>>
>>> data = '''12
...
... 12 12
...
...
... 12'''
>>> data
'12 \n\n12 12\n\n\n12'
>>> print(data)
12
12 12
12
step1: clear all line separations
>>> double_spaces = ' '
>>> single_space = ' '
>>> data = data.strip().replace('\n', single_space)
>>> data
'12 12 12 12'
step2: Fix multiple spaces
>>> while double_spaces in data:
... data = data.replace(double_spaces, single_space)
...
>>> data
'12 12 12 12'
>>> print(list(map(int, data.split()))
...
... )
[12, 12, 12, 12]
>>>
Problems with you code
>>> a = []
>>> try:
... while(True):
... a.append(int(input()))
... except:
... pass
...
12
1
12 12
>>> a
[12, 1]
>>>
When you enter 12 12, below is supposed to happen.
>>> int('12 12')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '12 12'
Since this code had bad exception handling except:, your use case is returning an empty list as expected.
Since I have changed the input, you see this difference.

How to recategorize numeric values into new grouping using Pandas as a function, with no limit of conditions [duplicate]

I've just started coding in python, and my general coding skills are fairly rusty :( so please be a bit patient
I have a pandas dataframe:
It has around 3m rows. There are 3 kinds of age_units: Y, D, W for years, Days & Weeks. Any individual over 1 year old has an age unit of Y and my first grouping I want is <2y old so all I have to test for in Age Units is Y...
I want to create a new column AgeRange and populate with the following ranges:
<2
2 - 18
18 - 35
35 - 65
65+
so I wrote a function
def agerange(values):
for i in values:
if complete.Age_units == 'Y':
if complete.Age > 1 AND < 18 return '2-18'
elif complete.Age > 17 AND < 35 return '18-35'
elif complete.Age > 34 AND < 65 return '35-65'
elif complete.Age > 64 return '65+'
else return '< 2'
I thought if I passed in the dataframe as a whole I would get back what I needed and then could create the column I wanted something like this:
agedetails['age_range'] = ageRange(agedetails)
BUT when I try to run the first code to create the function I get:
File "<ipython-input-124-cf39c7ce66d9>", line 4
if complete.Age > 1 AND complete.Age < 18 return '2-18'
^
SyntaxError: invalid syntax
Clearly it is not accepting the AND - but I thought I heard in class I could use AND like this? I must be mistaken but then what would be the right way to do this?
So after getting that error, I'm not even sure the method of passing in a dataframe will throw an error either. I am guessing probably yes. In which case - how would I make that work as well?
I am looking to learn the best method, but part of the best method for me is keeping it simple even if that means doing things in a couple of steps...
With Pandas, you should avoid row-wise operations, as these usually involve an inefficient Python-level loop. Here are a couple of alternatives.
Pandas: pd.cut
As #JonClements suggests, you can use pd.cut for this, the benefit here being that your new column becomes a Categorical.
You only need to define your boundaries (including np.inf) and category names, then apply pd.cut to the desired numeric column.
bins = [0, 2, 18, 35, 65, np.inf]
names = ['<2', '2-18', '18-35', '35-65', '65+']
df['AgeRange'] = pd.cut(df['Age'], bins, labels=names)
print(df.dtypes)
# Age int64
# Age_units object
# AgeRange category
# dtype: object
NumPy: np.digitize
np.digitize provides another clean solution. The idea is to define your boundaries and names, create a dictionary, then apply np.digitize to your Age column. Finally, use your dictionary to map your category names.
Note that for boundary cases the lower bound is used for mapping to a bin.
import pandas as pd, numpy as np
df = pd.DataFrame({'Age': [99, 53, 71, 84, 84],
'Age_units': ['Y', 'Y', 'Y', 'Y', 'Y']})
bins = [0, 2, 18, 35, 65]
names = ['<2', '2-18', '18-35', '35-65', '65+']
d = dict(enumerate(names, 1))
df['AgeRange'] = np.vectorize(d.get)(np.digitize(df['Age'], bins))
Result
Age Age_units AgeRange
0 99 Y 65+
1 53 Y 35-65
2 71 Y 65+
3 84 Y 65+
4 84 Y 65+

checking range of number and writing a value in a new column in pandas dataframe

I need to iterate over column 'movies_rated', check the value against the conditions, and write a value in a newly create column 'expert_level'. When I test on a subset of data, it works. But when I run it against my whole dateset, it only gets filled with value 1.
for num in df_merge['movies_rated']:
if num in range(20,31):
df_merge['expert_level'] = 1
elif num in range(31,53):
df_merge['expert_level'] = 2
elif num in range(53,99):
df_merge['expert_level'] = 3
elif num in range(99,202):
df_merge['expert_level'] = 4
else:
df_merge['expert_level'] = 5
here's a sample dataframe.
movies = [88,20,35,55,1203,99,2222,847]
name = ['angie','chris','pine','benedict','alice','spock','tony','xena']
df = pd.DataFrame(movies,name,columns=['movies_rated'])
certainly there's a less verbose way of doing this?
You could build an IntervalIndex and then apply pd.cut. I'm sure this is a duplicate, but I can't find one right now which uses both closed='left' and .codes, though I'm sure it exists.
bins = pd.IntervalIndex.from_breaks([0, 20, 31, 53, 99, 202, np.inf], closed='left')
df["expert_level"] = pd.cut(movies, bins).codes
which gives me
In [242]: bins
Out[242]:
IntervalIndex([[0.0, 20.0), [20.0, 31.0), [31.0, 53.0), [53.0, 99.0), [99.0, 202.0), [202.0, inf)]
closed='left',
dtype='interval[float64]')
and
In [243]: df
Out[243]:
movies_rated expert_level
angie 88 3
chris 20 1
pine 35 2
benedict 55 3
alice 1203 5
spock 99 4
tony 2222 5
xena 847 5
Note that I've set this up so that scores below 20 get a 0 value, so they can be distinguished from really high rankings. If you really want everything outside the bins to get 5, it'd be straightforward to remap 0 to 5, or just pass breaks of [20, 31, 53, 99, 202] and then map anything with a code of -1 (which means 'not binned') to 5.
I think np.select with the pandas function between is a good choice for you:
conds = [df.movies_rated.between(20,30), df.movies_rated.between(31,52),
df.movies_rated.between(53,98), df.movies_rated.between(99,202)]
choices = [1,2,3,4]
df['expert_level'] = np.select(conds,choices, 5)
>>> df
movies_rated expert_level
angie 88 3
chris 20 1
pine 35 2
benedict 55 3
alice 1203 5
spock 99 4
tony 2222 5
xena 847 5
you could do it with apply and a function:
def expert_level_check(num):
if 20<= num < 31:
return 1
elif 31<= num < 53:
return 2
elif 53<= num < 99:
return 3
elif 99<= num < 202:
return 4
else:
return 5
df['expert_level'] = df['movies_rated'].apply(expert_level_check)
it is slower to manually iterate over a df, I recommend reading this

Resources