How to convert string to integer without using library functions in Python? - python

I am trying to convert
a = "546"
to
a = 546
without using any library functions.

The "purest" I can think of:
>>> a = "546"
>>> result = 0
>>> for digit in a:
result *= 10
for d in '0123456789':
result += digit > d
>>> result
546
Or using #Ajax1234's dictionary idea if that's allowed:
>>> a = "546"
>>> value = {'0':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9}
>>> result = 0
>>> for digit in a:
result = 10 * result + value[digit]
>>> result
546

You can keep a dictionary that stores the string and integer values of a numeric key, and then iterate over the string. While iterating over the string, you can use enumerate to keep track of the index and then raise 10 to that power minus 1 and then multiply by the corresponding key from the dictionary:
a = "546"
length = 0
for i in a:
length += 1
d = {'1': 1, '0': 0, '3': 3, '2': 2, '5': 5, '4': 4, '7': 7, '6': 6, '9': 9, '8': 8}
count = 0
counter = 0
for i in a:
count += (10**(length-counter-1)*d[i])
counter += 1
print(count)
Output:
546

The trick is that 546 = 500 + 40 + 6, or 5*10^2 + 4*10^1 + 6*10^0.
Note how the exponent is just the index (in reverse). Using that, you can generalize this approach into a function:
def strToInt(number):
total = 0 # this is where we accumulate the result
pwr = len(number) - 1 # start the exponent off as 2
for digit in number: # digit is the str "5", "4", and "6"
digitVal = ord(digit) - ord('0') # using the ascii table, digitVal is the int value of 5,4, and 6.
total += digitVal * (10 ** pwr) # add 500, then 40, then 6
pwr -= 1 # make sure to drop the exponent down by one each time
return total
And you can use it like so:
>>> strToInt("546")
546

def stringToInt(s):
result = 0
value = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
for digit in s:
result = 10 * result + value[digit]
return result

def int(a):
ty = a.__class__.__name__
out = 0
di = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4,
'5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
if ty not in ("str", "int", "float", "bytes"):
raise TypeError("unsupported format")
if a.__class__ == float:
return a.__floor__()
elif a.__class__ == int:
return a
else:
ind = 0
for val in a[::-1]:
if val not in di:
raise ValueError("invalid input")
out += di[val]*(10**ind)
ind += 1
#print(out, di[val])
return out
print(int("55"))
55

You can loop through the string and perform the operation on each character using ord.
example:
a="546"
num=0
for i in a:
num = num * 10 + ord(i) - ord('0')

astr = "1234"
num = 0
for index,val in enumerate(astr[::-1]):
res = (ord(val) - ord('0')) * (10 ** index)
num += (res)

a=input()
r=0
for i in a:
r=r*10+(ord(i)-ord("0"))
print(r)
print(type(r))

Related

Find keys of dictionary that sum to 6

I'm having trouble accessing multiple values in a dictionary. Let's say I have this dictionary:
{'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5}
I want to find two keys that sum to 6 and display their values. Here, the keys 4 and 2 add to 6, so the 2 values are 3 and 1.
Where do I start? This is the code I have so far:
for key in dico:
if sum(key + key) == 6:
print(f"Numbers # {key:dico} have a sum of 6")
No need for extra loops (or itertools), they will only slow your program down. You already know what the other index needs to be (because you can subtract the index from 6), so just check if that index exists:
dct = {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5}
for i, key in enumerate(dct):
if i + 2 > len(dct)/2:
break
matchIndex = str(6 - int(key))
if dct.get(matchIndex) is not None:
print(f'Keys {key} and {matchIndex} have values {dct[key]} and {dct[matchIndex]}')
This approach has a O(n/2) time complexity, while the other answer has O(n^2) time complexity.
When I tested this approach with timeit, it took 1.72 seconds to run this answer one million times, but the itertools answer took 5.83 secondss.
You will need to compare each of the dictionary keys with the rest of the other keys. You can use itertools for this.
As you mention you would like to print the value of each of the keys you have in your dictionary, it would be something like this:
import itertools
dico = {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5}
for a, b in itertools.combinations(dico.keys(), 2):
if int(a) + int(b) == 6:
print(f"{dico[a]} - {dico[b]}")
You need two loops for that.
Also, have in mind that there is more than one answer to that problem
a = {'1': 0, '2': 1, '3': 2, '4': 3, '5': 4, '6': 5}
results = list()
for key_1 in a.keys():
for key_2 in a.keys():
if key_1 != key_2:
if a[key_1] + a[key_2] == 6:
if a[key_1] < a[key_2]:
results.append((key_1, key_2))
print(results)

Combining values/keys into one string and printing

Currently, I have a dictionary and I need to separate the keys and values and then add them together
Here is my code:
vowel_count = {"a": 0, "e": 4, "i": 8, "o": 14, "u": 20}
vowels = ""
total = 0
# Iterate through vowel_count and get all keys sorted. Combined them into
# one string and add all values. Print out the combined string and the
total value.
for vowel, count in vowel_count.items():
print(vowel)
print(count)
strings can be combined, concatenated, with + and integers can be summed with +
Splitting, Concatenating, and Joining Strings in Python
a object can be updated with +=
Where i=1, i += 1 now i is 2
Where v='a', v += 'b' now v is 'ab'
vowel_count = {"a": 0, "e": 4, "i": 8, "o": 14, "u": 20}
l = ''
i = 0
for k, v in vowel_count.items():
l += k
i += v
print(l)
'aeiou'
print(i)
46

Find out if this sequence is one in which the same numbers are in pairs, but there is one other number between the same numbers

I am total newbie in python who is practising right now with little 'algorithms'.
So here is my exercise:
N-number integers are given (user have to input). The task is to find out if this sequence is one in which the same numbers are in pairs, but there is one other number between the same numbers.
For example, for a sequence of 11 numbers 3 3 5 10 10 1 12 12 3 6 6, the answer is "yes" and for the sequence 2 2 3 15 15 4 4 8 4 4 1 the answer is "no".
Here's what I tried. But this gypsy-code is not working well:
n = int(input())
right_sequence = True
for i in range(n):
current = int(input())
if i > 0:
if current == previous:
if previous != current:
right_sequence = True
else:
right_sequence = False
previous = current
if right_sequence == True:
print('Yes')
else:
print('No')
I tried to use your own code as much as possible.
Basically the number of inputs should be at least 5. (The shortest correct answer would be in this format : A A B A A which has 5 input.
If we replace the i's with their remainder to 3. (i.e i % 3) Then the indexes for 8 input values would be:
0 1 2 0 1 2 0 1 ...
For which a correct answer would look like bellow:
A A B A A B A A ...
A correct list (The one that outputs "Yes") is the one that:
all the 0 indexes are different from their previous value (Except the first 0 which deosn't have previous value)
all the 1 indexes are equal to their previous value
all the 2 indexes are different from their previous value
The list ends with a 1 index
These 4 points are summarized into 4 if conditions in the bellow code. (The ones that have the value 'k' which carries the remainder of i'th to 3)
n = int(input())
right_sequence = True
k = 0
if n < 5:
right_sequence = False
for i in range(n):
current = int(input())
if i > 0:
k = i % 3
if k == 0:
if current == previous:
right_sequence = False # Print (No)
if k == 1:
if current != previous:
right_sequence = False # Print (No)
if k == 2:
if current == previous:
right_sequence = False # Print (No)
previous = current
if k != 1:
print('No')
elif right_sequence == True:
print('Yes')
elif right_sequence == False:
print('No')
You could slices and zip:
def f(l):
all(a == b != c for a, b, c in zip(x[::3], x[1::3], x[2::3]))
f([3, 3, 5, 10, 10, 1, 12, 12, 3, 6, 6])
# True
f([2, 2, 3, 15, 15, 4, 4, 8, 4, 4, 1])
# False
This will work only if the sequence starts with a pair and you might have to check special cases at the end, but it should hint in the right direction.
I have solved the issue the following way:
x = [2, 2, 3, 15, 15, 4, 4, 8, 4, 4, 1]
y = [3, 3, 5, 10, 10, 1, 12, 12, 6, 6]
def check_order(x):
for i in range(len(x)):
only_equal_in_row = True # all previous checked j index elements were equal to i
for j in range(i+1, len(x)):
if x[i] == x[j]:
if only_equal_in_row is False: # check if there was j not equal to i elements before
return False
else:
only_equal_in_row = False # found j element not equal to i
return True
if __name__ == "__main__":
print(check_order(x))
print(check_order(y))
Edit: Without functions due to OP request:
x = [2, 2, 3, 15, 15, 4, 4, 8, 4, 4, 1]
is_right = True
stop = False # need to stop outer for loop
for i in range(len(x)):
if stop:
break
only_equal_in_row = True # all previous checked j index elements were equal to i
for j in range(i+1, len(x)):
if x[i] == x[j]:
if only_equal_in_row is False: # check if there was j not equal to i elements before
is_right = False
stop = True
break
else:
only_equal_in_row = False # found j element not equal to i
print(is_right)

Calculating column wise for a matrix using numpy in python

By the following program, I am trying to calculate the number of occurance of '0','1','2',and '3' for each column. The program is not working as desired. I read somewhere that slicing of the matrix should be done for computing the occurance column wise but I am not sure how to do it. The program is written using numpy in python. How to do it using numpy?
import numpy as np
a=np.array([[ 2,1,1,2,1,1,2], #t1 is horizontal
[1,1,2,2,1,1,1],
[2,1,1,1,1,2,1],
[3,3,3,2,3,3,3],
[3,3,2,3,3,3,2],
[3,3,3,2,2,2,3],
[3,2,2,1,1,1,0]])
print(a)
i=0
j=0
two=0
zero=0
one=0
three=0
r=a.shape[0]
c=a.shape[1]
for i in range(1,r):
#print(repr(a))
for j in range(1,c):
#sele=a[i,j]
if (a[i,j]==0):
zero+=1
if (a[i,j]==1):
one+=1
if (a[i,j]==2):
two+=1
if (a[i,j]==3):
three+=1
if i==c-1:
#print(zero)
print(one)
i+=0
j=j+1
#print(two)
#print(three)
i=i+1
#print(zero)`
Also I want to print it in the following manner:
column: 0 1 2 3 4 5 6
occurrences: 0 0 0 0 0 0 0 1
1 1 3 2 2 4 3 1
2 2 1 3 4 1 2 2
3 4 3 2 1 2 2 2
Here is the code using list functionality
import numpy as np
inputArr=np.array([[ 2,1,1,2,1,1,2],
[1,1,2,2,1,1,1],
[2,1,1,1,1,2,1],
[3,3,3,2,3,3,3],
[3,3,2,3,3,3,2],
[3,3,3,2,2,2,3],
[3,2,2,1,1,1,0]
])
occurance = dict()
toFindList = [0,1,2,3]
for col in range(len(inputArr)):
collist = inputArr[:, col]
collist = (list(collist))
occurance['col_' + str(col)] = {}
for num in toFindList:
occurcount = collist.count(num)
occurance['col_' + str(col)][str(num)] = occurcount
for key, value in occurance.iteritems():
print key, value
Output:
col_2 {'1': 2, '0': 0, '3': 2, '2': 3}
col_3 {'1': 2, '0': 0, '3': 1, '2': 4}
col_0 {'1': 1, '0': 0, '3': 4, '2': 2}
col_1 {'1': 3, '0': 0, '3': 3, '2': 1}
col_6 {'1': 2, '0': 1, '3': 2, '2': 2}
col_4 {'1': 4, '0': 0, '3': 2, '2': 1}
col_5 {'1': 3, '0': 0, '3': 2, '2': 2}
This should give you the output format you want:
def col_unique(a):
return np.sum(np.dstack([np.in1d(a,i).reshape(a.shape) for i in np.unique(a)]), axis = 0).T

Combine strings. Count how many indices (from list) are in original strings. Python

junctions = [2,9,15,20]
seq_1 = 'sauron'
seq_2 = 'corrupted'
seq_3 = 'numenor'
combined = 'sauroncorruptednumenor' #seq_1 + seq_2 + seq_3
count_1 = 1
count_2 = 1
count_3 = 2
I have a list of 3 strings (seq_1-3). I combine them to create 1 long string (combined)
I have a list of indices (junctions). I have 3 different counters set to zero for each string (count_1-3)
What I am trying to do is find the position of each junction [2,9,15,20] in the combined sequence . . . if it is from seq_1 --> count_1 += 1, if it is from seq_2 --> count_2 += 1, from seq_3 --> count_3 += 1
example
junctions = [2,9,15,20]
count_1 = 0
count_2 = 0
count_3 = 0
combined = 'sauroncorruptednumenor'
seq_1 = 'sauron' #index 2 would be on 'u' in combined but originally from seq_1 so count_1 = count_1 + 1
seq_2 = 'corrupted' #index 9 would be on 'r' in combined so count_2 += 1
seq_3 = 'numenor' #index 15 would be 'n' in combined so count_3 += 1, and 20 would be 'o' so count_3 += 1
let me know if i need to clarify any differently
You could try something basic like
L_1 = len(seq_1)
L_2 = len(seq_2)
L_3 = len(seq_3)
junctions = [2, 9, 15, 20]
c_1, c_2, c_3 = (0, 0, 0)
for j in junctions:
if j < L_1:
c_1 += 1
elif j < L_1 + L_2:
c_2 += 1
elif j < L_1 + L_2 + L_3:
c_3 += 1
else:
Raise error
You can use collections.Counter and bisect.bisect_left here:
>>> from collections import Counter
>>> import bisect
>>> junctions = [2,9,15,20]
>>> seq_1 = 'sauron'
>>> seq_2 = 'corrupted'
>>> seq_3 = 'numenor'
>>> lis = [seq_1, seq_2, seq_3]
Create a list containing the indexes at which at each seq_ ends:
>>> start = -1
>>> break_points = []
for item in lis:
start += len(item)
break_points.append(start)
...
>>> break_points
[5, 14, 21]
Now we can simply loop over junctions and find each junction's position in the break_points list using bisect.bisect_left function.
>>> Counter(bisect.bisect_left(break_points, jun)+1 for jun in junctions)
Counter({3: 2, 1: 1, 2: 1})
Better output using collections.defaultdict:
>>> from collections import defaultdict
>>> dic = defaultdict(int)
for junc in junctions:
ind = bisect.bisect_left(break_points, junc) +1
dic['count_'+str(ind)] += 1
...
>>> dic
defaultdict(<type 'int'>,
{'count_3': 2,
'count_2': 1,
'count_1': 1})
#accessing these counts
>>> dic['count_3']
2
Could use collections.Counter, and repeat and chain from itertools, eg:
from itertools import chain, repeat
from operator import itemgetter
from collections import Counter
junctions = [2,9,15,20]
seq_1 = 'sauron'
seq_2 = 'corrupted'
seq_3 = 'numenor'
indices = list(chain.from_iterable(repeat(i, len(j)) for i, j in enumerate([seq_1, seq_2, seq_3], start=1)))
print Counter(itemgetter(*junctions)(indices))
# Counter({3: 2, 1: 1, 2: 1})

Categories

Resources