Alphanumeric sorting in Python and negative numbers - python

I have a fairly simple list (a number followed by a sentence), here in the right order:
-347 a negative number
-100 another negative number
-25 and again, a negative number
17 some text
25 foo bar
100 two same texts
100 two same texts (almost)
350 a positive number
I need to sort that list each time a new item is added.
I searched S.O. and found that answer :
Sorting in python - how to sort a list containing alphanumeric values?
The code I used is freakish’s, which goes :
import re
def convert(str):
return int("".join(re.findall("\d*", str)))
list1.sort(key=convert)
In order to better explain my problem, I shuffled the list and ran the code.
The result was :
17 some text
-25 and again, a negative number
25 foo bar
100 two same texts (almost)
100 two same texts
-100 another negative number
-347 a negative number
350 a positive number
What went wrong ? What is the precision in the code that would sort naturally the negative numbers?

Sort can accept a tuple, so first sort by the number, then by the text after
list_text = """-347 a negative number
-100 another negative number
-25 and again, a negative number
17 some text
25 foo bar
100 two same texts
100 two same texts (almost)
350 a positive number"""
list1 = list_text.split("\n")
list1.sort(key=lambda x: (int(x.split()[0]), x.split(" ",1)))
print("\n".join(list1))

The easiest approach, IMHO, would be to split the string to individual words, and then sort by the first word converted to an int:
list1.sort(key = lambda x : int(x.split(" ")[0]))
EDIT:
As Keatinge, the above solution won't properly handle two strings that start with the same number. Using the entire string as a secondary search term should solve this issue:
list1.sort(key = lambda x : (int(x.split(" ")[0]), x)

Related

Take out numbers from String without list

I have to make a (def) program using Python language where user inserts a string ( up to 8 digits numbers (0-9) and letters (a-z) together), program has to find out how many numbers are there in a string. Program will calculate the sum and average of those numbers.
Approach 1 : Pure implementation by string, without using list at all.
def sum_and_average(string):
COUNT = 0
SUM = 0
for value in string:
if value.isdigit():
SUM += int(value)
COUNT +=1
print('Sum :',SUM)
print('Average :',SUM/COUNT)
Approach 2 : Using List Comprehensions and Ascii values
def sum_and_average2(s):
L = [int(var) for var in s if 48<=ord(var)<=57]
print('Sum :', sum(L))
print('Average :', sum(L)/len(L))
Approach 3 : Using Regex, Already Mentioned However Regex will also store values as list object so in your case approach 1 would be best but approach 3 will be fastest in case of long string input.
you can use regular expression to parse the spring to get your numbers and letters separately and then perform the required operation on the numbers.
Example
import re
def spring_program(spring):
regex = re.compile("([0-9]+)([a-z]+)")
numbers = regex.match(spring).group(1)
letters = regex.match(spring).group(2)
print(numbers)
print(letters)
#you can now do any manipulation to the numbers

Regular expression between two integers

I'm trying to build a regular expression that will match the word mark to an integer greater or equal to 140000 and less than or equal to 150000.
So, for example, the minimum value would be mark_140000 and the maximum value would be mark_150000. The values mark_139999 and mark_150001 would be invalid.
I have a method that will match from 140000 to 149999:
"^mark_14[0-9]{4}$"
How can I get the maximum to include 150000?
simple enough, just create 2 cases:
"^mark_(14[0-9]{4}|150000)$"
Your regex needs to account for all the possibilities of 140000 to 150000
^mark_1(4\d{4})|(50{4})
You could write a small function that checks if the number part is in the range:
import re
data = """So for example the minimum value would be mark_140000 and the maximum value would be mark_150000. The values mark_139999 and mark_150001 would be Many thanks and mark_100000000000000"""
rx = re.compile(r'mark_(\d+)')
def check(number):
number = float(number)
if 140000 <= number <= 150000:
return True
return False
matches = [match.group(0)
for match in rx.finditer(data)
if check(match.group(1))]
print(matches)
This yields
['mark_140000', 'mark_150000']

veryfying the output of a string in a certain format

I am trying to check whether or not a licence plate fits a certain format when the user inputs a number plate. It needs to be in the format of two numbers, three letters, and finally two more numbers. If it does not match this format then it must save it to a list.
speed_limit = []
while True :
speed = float()
distance = 50
time=float(raw_input('enter time'))
speed = distance / time
print speed
if speed > 31.2928:
#70 mph converted into meters per second
number_plate = raw_input('enter number plate')
number_plate.upper()
speed_limit.append(number_plate)
print speed_limit
else:
print 'ok'
This is my current code, I am not sure if this is possible or I am asking a too vague question but I need help!
You can do a regular expression match. The regex key that you would be needing is
(\d{2}[A-Z]{3}\d{2})
This returns 2 numbers, 3 letters and 2 numbers. You can try more regex combinations here
Try the following lines in your command prompt to check the code-
import re
m = re.match('(\d{2}[A-Z]{3}\d{2})','12MNB36')
m holds the result if the string matched the pattern or not.

Computing persistence number of an integer

I am trying to make a code that does the following:
Multiplying the digits of an integer and continuing the process gives
the surprising result that the sequence of products always arrives at
a single-digit number.
For example:
715 -> 35 -> 15 -> 5
88 -> 64 -> 24 -> 8
27 -> 14 -> 4
The number of products necessary to reach the single-digit
number is called the persistence number of that integer. Thus 715
and 88 have a persistence number of 3, while 27 has persistence 2.
Make a program to find the only two-digit number with persistence
greater than 3?
I was able to come up with a rough idea and the code is below but it doesn't seem to work:
num2=0
num3=0
num4=0
num=input("what is your number?")
while num in range(10,100):
print 'step1'
num1=num%10*num/10
if num1-10>10:
print 'step2'
num2=num1%10*num1/10
elif num2-num1>10:
print 'step3'
num3=num2%10*num2/10
elif num3-num2>10:
print 'step4'
num4=num3%10*num3/10
elif num4-num3>10:
print 'step5'
print num4
else:
break
The program is Python and I simply can't figure this out. If someone could possibly help me I would appreciate it greatly!
You should use a while or for loop to multiply the digits instead of hardcoding what to do with the first, second and so on digits.
In pseudocode...
productSoFar = 1
digitsLeftToMultipy = #the number
while there are digits left to multiply:
get the next digit and
update produtsSoFar and digitsLeftToMultiply
Also, use
10 <= n < 100
instead of
n in range(10, 100)
So you only do a couple of comparisons instead of a sequential lookup that takes time proportional to the length of the range.
Functions are friends.
Consider a function, getEnds(x), which when passed an integer, x will extract the first digit and the last digit (as integers) and return the result as a tuple in the form (first_digit, last_digit). If x is a single-digit number the tuple will contain one element and be in the form (x), otherwise it will be two. (A simple way to do this is to turn the number into a string, extract the first/last digit as a string, and then convert said strings back into numbers... however, there are many ways: just make sure to honor the function contract, as stated above and -- hopefully -- in the function documentation.)
Then, where n is the current number we are finding the persistence for:
ends = getEnds(n)
while ends contains two elements
n = first element of ends times second element of ends
ends = getEnds(n)
# while terminates when ends contained only one element
# now it's only a matter of "counting" the persistence
For added points, make sure this is in a -- [an] appropriately named/documented -- function as well and consider the use of a recursive function instead of a while-loop.
Happy coding.
If you're trying to get the digits of a number, convert it into a string first and reference them with array notation.

Determining the number of possible combinations

I'm trying to figure out how many possible ways there are to combine various elements form this string.
"{Hello|Hi|Hey} {world|earth}{!|.|?}"
Where one item (separated by a pipe/|) is selected at random from each group ({}) and combined into a single string.
So the above "template" could produce:
Hello world.
Hi earth?
Hey world.
Hi world?
I'm guessing this is a type of permutation, but I want to make sure I'm getting this right.
It would be really nice if this worked with "n" nested items as well.
"{{Hello|Hi|Hey} {world|earth}|{Goodbye|farewell} {noobs|n3wbz|n00blets}}"
I'd prefer a math/statistics based solution over brute-force looping to get the answer if possible.
Thanks!
Well, there are 3 x 2 x 3 = 18 combinations in your first example.
Your second example is 3 x 4 x 2 x 3 = 72 combinations.
I'm not entirely sure what you mean by {a|b}|{c|d} though, I'm assuming you mean pick one of either (a or b) or (c or d), which is 4 choices.
You might want to read up on combinations here or here.
Update: Yep, it's that simple. Your problem is exactly like counting the number of combinations of digits in a number. For example, if I want to find the number of combinations of an ATM PIN number (4 decimal digits), I have sets {0-9}, {0-9}, {0-9}, {0-9}. There are 10 possibilities for the first choice (= 10). For each of those numbers, there are 10 possibilities for the second choice (= 10 × 10). For each of those, there are 10 for the third (= 10 × 10 × 10) and 10 for the fourth (= 10 × 10 × 10 × 10 = 10,000). It should be intuitively clear that there are 10,000 possibilities for a 4 digit decimal number.
Your example uses sets of words instead of sets of digits, but the principle is the same. The number of combinations is the number of items in set 1 × number of items in set 2 × ... × number of items in set n, etc.
It gets more complicated when you start putting restrictions in, or are picking multiple items from the same set, etc.
The problem breaks down to two simple sub-problems:
count how many combinations are within braces and separated within vbars, for each braces pair
multiply those numbers
So for 1 I'd go with a plain regular expression + looping approach:
import re
def docount(thestring):
x = re.compile(r'{([^}]}')
counts = [mo.group(0).count('|')+1 for mo in x.finditer(thestring)]
result = 1
for c in counts: result *= c
return result
I've embedded 2 as well since that's the most trivial part anyway (if you're keen on using reduce for such purposes, that's OK too in lieu of the last three lines, I guess;-).

Categories

Resources