Sorting numbers in python - python

I'm trying to get a function where if you do sort(listname) it would sort all the numbers inside that list from least to greatest.
I'm not sure whats wrong with mine, but I need some help as the output isn't actually least to greatest it does least to greatest for the first two numbers of the number.
Example :
If list has 23, 212, 44 in it than I sort it the output will be like this.
Output :
212,23,44
It should be 23, 44, 212.
Code:
def sort(my_list):
size = len(my_list)
for i in range(size):
for j in range(size-i-1):
if(my_list[j] > my_list[j+1]):
tmp = my_list[j]
my_list[j] = my_list[j+1]
my_list[j+1] = tmp
More code :
numbers=([])
amount=input("How many numbers are in your list? ")
print("")
counter = 0
ran = 0
while counter < int(amount):
counter = counter + 1
ran = ran + 1
num3 = input(str(ran) + ". Input: ")
try:
val = int(num3)
except ValueError:
num3 = input(str(ran) + ". Input: ")
sort(numbers)
numbers.append(num3)

That looks like your list doesn't contain any numbers but strings. Python doesn't try to guess what might be inside of those strings, so you get an odd sort order.
You have two options:
Convert list elements to int before comparing them (if(int(my_list[j]) > int(my_list[j+1])):)
Search this site for python natural sort to get answers how to implement "natural sorting" in Python.

If you just want it sorted, use sorted:
sorted_my_list = sorted(my_list,key=int)
Or to sort it, in place, use
my_list.sort(key=int)
If you want to fix your program, turn my_list into ints or at least compare integers
if ( int(my_list[j]) > int(my_list[j+1])):
Also, you can swap two variables in one statement:
my_list[j],my_list[j+1] = my_list[j+1],my_list[j]

I just used your code (Just added a return statement). And it returns the expected values:
def sort(my_list):
size = len(my_list)
for i in range(size):
for j in range(size-i-1):
if(my_list[j] > my_list[j+1]):
tmp = my_list[j]
my_list[j] = my_list[j+1]
my_list[j+1] = tmp
return my_list # Note I added this return statement
print sort([23,212,44])
>>>
[23, 44, 212]

Related

How can I assign positives and negatives to a string?

I'm trying to create this code so that when variable J is present, it is a positive number, but if H is present, it is a negative number. Here is my code.
record = ['1J2H']
def robot_location(record: str):
if J in record:
sum()
if H in record:
** I dont know how to subtract them**
print(robot_location(record)
So if record = [1J2H] then the output should be ((+1)+(-2)) = -1 should be the output... how can I do that?? Somebody pls help explain this.
You need to iterate over string inside list, check char by char and asume thats always length of string will be odd
record = ['1J2H']
def robot_location(record: str):
total = 0
aux_n = 0
for a in record:
if a.isnumeric():
aux_n = int(a)
else:
if a == 'H':
total = total + aux_n*-1
else:
total = total + aux_n
aux_n = 0
return total
print(robot_location(record[0]))
Here is a concise way to do this via a list comprehension:
record = '1J2H'
nums = re.findall(r'\d+[JH]', record) # ['1J', '2H']
output = sum([int(x[:-1]) if x[-1] == 'J' else -1*int(x[:-1]) for x in nums])
print(output) # -1
One way to do that is by using iter and converting the string into an iterable, that allows to use next which moves the iteration to the next item meaning that if one simply iterates over it it will get moved to the next item and then if one uses next it will return the current value where the "pointer"? is and move it to the next value so the next iteration with a for loop (list comprehension in this case) will get the next value, meaning that the loop will return only the numbers while next will return only the letters:
lst = ['1J2H']
def robot_location(record: str):
record = iter(record)
numbers = [int(i) if next(record) == 'J' else -int(i) for i in record]
return sum(numbers)
print(robot_location(lst[0]))
You could modify a string like s = '1J2H' to '1+2*-1+0' and let Python evaluate it:
result = eval(s.replace('J', '+').replace('H', '*-1+') + '0')

python intelligent hexadecimal numbers generator

I want to be able to generate 12 character long chain, of hexadecimal, BUT with no more than 2 identical numbers duplicate in the chain: 00 and not 000
Because, I know how to generate ALL possibilites, including 00000000000 to FFFFFFFFFFF, but I know that I won't use all those values, and because the size of the file generated with ALL possibilities is many GB long, I want to reduce the size by avoiding the not useful generated chains.
So my goal is to have results like 00A300BF8911 and not like 000300BF8911
Could you please help me to do so?
Many thanks in advance!
if you picked the same one twice, remove it from the choices for a round:
import random
hex_digits = set('0123456789ABCDEF')
result = ""
pick_from = hex_digits
for digit in range(12):
cur_digit = random.sample(hex_digits, 1)[0]
result += cur_digit
if result[-1] == cur_digit:
pick_from = hex_digits - set(cur_digit)
else:
pick_from = hex_digits
print(result)
Since the title mentions generators. Here's the above as a generator:
import random
hex_digits = set('0123456789ABCDEF')
def hexGen():
while True:
result = ""
pick_from = hex_digits
for digit in range(12):
cur_digit = random.sample(hex_digits, 1)[0]
result += cur_digit
if result[-1] == cur_digit:
pick_from = hex_digits - set(cur_digit)
else:
pick_from = hex_digits
yield result
my_hex_gen = hexGen()
counter = 0
for result in my_hex_gen:
print(result)
counter += 1
if counter > 10:
break
Results:
1ECC6A83EB14
D0897DE15E81
9C3E9028B0DE
CE74A2674AF0
9ECBD32C003D
0DF2E5DAC0FB
31C48E691C96
F33AAC2C2052
CD4CEDADD54D
40A329FF6E25
5F5D71F823A4
You could also change the while true loop to only produce a certain number of these based on a number passed into the function.
I interpret this question as, "I want to construct a rainbow table by iterating through all strings that have the following qualities. The string has a length of 12, contains only the characters 0-9 and A-F, and it never has the same character appearing three times in a row."
def iter_all_strings_without_triplicates(size, last_two_digits = (None, None)):
a,b = last_two_digits
if size == 0:
yield ""
else:
for c in "0123456789ABCDEF":
if a == b == c:
continue
else:
for rest in iter_all_strings_without_triplicates(size-1, (b,c)):
yield c + rest
for s in iter_all_strings_without_triplicates(12):
print(s)
Result:
001001001001
001001001002
001001001003
001001001004
001001001005
001001001006
001001001007
001001001008
001001001009
00100100100A
00100100100B
00100100100C
00100100100D
00100100100E
00100100100F
001001001010
001001001011
...
Note that there will be several hundred terabytes' worth of values outputted, so you aren't saving much room compared to just saving every single string, triplicates or not.
import string, random
source = string.hexdigits[:16]
result = ''
while len(result) < 12 :
idx = random.randint(0,len(source))
if len(result) < 3 or result[-1] != result[-2] or result[-1] != source[idx] :
result += source[idx]
You could extract a random sequence from a list of twice each hexadecimal digits:
digits = list('1234567890ABCDEF') * 2
random.shuffle(digits)
hex_number = ''.join(digits[:12])
If you wanted to allow shorter sequences, you could randomize that too, and left fill the blanks with zeros.
import random
digits = list('1234567890ABCDEF') * 2
random.shuffle(digits)
num_digits = random.randrange(3, 13)
hex_number = ''.join(['0'] * (12-num_digits)) + ''.join(digits[:num_digits])
print(hex_number)
You could use a generator iterating a window over the strings your current implementation yields. Sth. like (hex_str[i:i + 3] for i in range(len(hex_str) - window_size + 1)) Using len and set you could count the number of different characters in the slice. Although in your example it might be easier to just compare all 3 characters.
You can create an array from 0 to 255, and use random.sample with your list to get your list

Funny behaviour of my recursive function

t = 8
string = "1 2 3 4 3 3 2 1"
string.replace(" ","")
string2 = [x for x in string]
print string2
for n in range(t-1):
string2.remove(' ')
print string2
def remover(ca):
newca = []
print len(ca)
if len(ca) == 1:
return ca
else:
for i in ca:
newca.append(int(i) - int(min(ca)))
for x in newca:
if x == 0:
newca.remove(0)
print newca
return remover(newca)
print (remover(string2))
It's supposed to be a program that takes in a list of numbers, and for every number in the list it subtracts from it, the min(list). It works fine for the first few iterations but not towards the end. I've added print statements here and there to help out.
EDIT:
t = 8
string = "1 2 3 4 3 3 2 1"
string = string.replace(" ","")
string2 = [x for x in string]
print len(string2)
def remover(ca):
newca = []
if len(ca) == 1: return()
else:
for i in ca:
newca.append(int(i) - int(min(ca)))
while 0 in newca:
newca.remove(0)
print len(newca)
return remover(newca)
print (remover(string2))
for x in newca:
if x == 0:
newca.remove(0)
Iterating over a list and removing things from it at the same time can lead to strange and unexpected behvaior. Try using a while loop instead.
while 0 in newca:
newca.remove(0)
Or a list comprehension:
newca = [item for item in newca if item != 0]
Or create yet another temporary list:
newnewca = []
for x in newca:
if x != 0:
newnewca.append(x)
print newnewca
return remover(newnewca)
(Not a real answer, JFYI:)
Your program can be waaay shorter if you decompose it into proper parts.
def aboveMin(items):
min_value = min(items) # only calculate it once
return differenceWith(min_value, items)
def differenceWith(min_value, items):
result = []
for value in items:
result.append(value - min_value)
return result
The above pattern can, as usual, be replaced with a comprehension:
def differenceWith(min_value, items):
return [value - min_value for value in items]
Try it:
>>> print aboveMin([1, 2, 3, 4, 5])
[0, 1, 2, 3, 4]
Note how no item is ever removed, and that data are generally not mutated at all. This approach helps reason about programs a lot; try it.
So IF I've understood the description of what you expect,
I believe the script below would result in something closer to your goal.
Logic:
split will return an array composed of each "number" provided to raw_input, while even if you used the output of replace, you'd end up with a very long number (you took out the spaces that separated each number from one another), and your actual split of string splits it in single digits number, which does not match your described intent
you should test that each input provided is an integer
as you already do a print in your function, no need for it to return anything
avoid adding zeros to your new array, just test first
string = raw_input()
array = string.split()
intarray = []
for x in array:
try:
intarray.append(int(x))
except:
pass
def remover(arrayofint):
newarray = []
minimum = min(arrayofint)
for i in array:
if i > minimum:
newarray.append(i - minimum)
if len(newarray) > 0:
print newarray
remover(newarray)
remover(intarray)

How can I use string formatting to assign unique variable?

I've got a list and i've managed to turn the list into strings. Now I want to assign a variable to each item in the list by using string formatting to append a 1 onto the end of the variable.
listOne = ['33.325556', '59.8149016457', '51.1289412359']
itemsInListOne = int(len(listOne))
num = 4
varIncrement = 0
while itemsInListOne < num:
for i in listOne:
print a = ('%dfinalCoords{0}') % (varIncrement+1)
print (str(listOne).strip('[]'))
break
I get the following error: SyntaxError: invalid syntax
How can I fix this and assign a new variable in the format:
a0 = 33.325556
a1 = 59.8149016457 etc.
Your current code has a few issues:
listOne = ['33.325556', '59.8149016457', '51.1289412359']
itemsInListOne = int(len(listOne)) # len will always be an int
num = 4 # magic number - why 4?
varIncrement = 0
while itemsInListOne < num: # why test, given the break?
for i in listOne:
print a = ('%dfinalCoords{0}') % (varIncrement+1) # see below
print (str(listOne).strip('[]')) # prints list once for each item in list
break # why break on first iteration
One line in particular is giving you trouble:
print a = ('%dfinalCoords{0}') % (varIncrement+1)
This:
simultaneously tries to print and assign a = (hence the SyntaxError);
mixes two different types of string formatting ('%d' and '{0}'); and
never actually increments varIncrement, so you will always get '1finalCoords{0}' anyway.
I would suggest the following:
listOne = ['33.325556', '59.8149016457', '51.1289412359']
a = list(map(float, listOne)) # convert to actual floats
You can easily access or edit individual values by index, e.g.
# edit one value
a[0] = 33.34
# print all values
for coord in a:
print(coord)
# double every value
for index, coord in enumerate(a):
a[index] = coord * 2
Looking at your previous question, it seems that you probably want pairs of coordinates from two lists, which can also be done with a simple list of 2-tuples:
listOne = ['33.325556', '59.8149016457', '51.1289412359']
listTwo = ['2.5929778', '1.57945488999', '8.57262235411']
coord_pairs = zip(map(float, listOne), map(float, listTwo))
Which gives:
coord_pairs == [(33.325556, 2.5929778),
(59.8149016457, 1.57945488999),
(51.1289412359, 8.57262235411)]

formatting list to convert into string

Here is my question
count += 1
num = 0
num = num + 1
obs = obs_%d%(count)
mag = mag_%d%(count)
while num < 4:
obsforsim = obs + mag
mylist.append(obsforsim)
for index in mylist:
print index
The above code gives the following results
obs1 = mag1
obs2 = mag2
obs3 = mag3
and so on.
obsforrbd = parentV = {0},format(index)
cmds.dynExpression(nPartilce1,s = obsforrbd,c = 1)
However when i run the code above it only gives me
parentV = obs3 = mag3
not the whole list,it only gives me the last element of the list why is that..??
Thanks.
I'm having difficulty interpreting your question, so I'm just going to base this on the question title.
Let's say you have a list of items (they could be anything, numbers, strings, characters, etc)
myList = [1,2,3,4,"abcd"]
If you do something like:
for i in myList:
print(i)
you will get:
1
2
3
4
"abcd"
If you want to convert this to a string:
myString = ' '.join(myList)
should have:
print(myString)
>"1 2 3 4 abcd"
Now for some explanation:
' ' is a string in python, and strings have certain methods associated with them (functions that can be applied to strings). In this instance, we're calling the .join() method. This method takes a list as an argument, and extracts each element of the list, converts it to a string representation and 'joins' it based on ' ' as a separator. If you wanted a comma separated list representation, just replace ' ' with ','.
I think your indentations wrong ... it should be
while num < 4:
obsforsim = obs + mag
mylist.append(obsforsim)
for index in mylist:
but Im not sure if thats your problem or not
the reason it did not work before is
while num < 4:
obsforsim = obs + mag
#does all loops before here
mylist.append(obsforsim) #appends only last
The usual pythonic way to spit out a list of numbered items would be either the range function:
results = []
for item in range(1, 4):
results.append("obs%i = mag_%i" % (item, item))
> ['obs1 = mag_1', 'obs2 = mag_2', 'ob3= mag_3']
and so on (note in this example you have to pass in the item variable twice to get it to register twice.
If that's to be formatted into something like an expression you could use
'\n'.join(results)
as in the other example to create a single string with the obs = mag pairs on their own lines.
Finally, you can do all that in one line with a list comprehension.
'\n'.join([ "obs%i = mag_%i" % (item, item) for item in range (1, 4)])
As other people have pointed out, while loops are dangerous - its easier to use range

Categories