## Place value + value of letters

8 posts
Hi all,

I have written a simple program which sorts a list of numbers and/or letters.

BUT!

number 233 for example, will come before 3, due to the leading 2.
A similar thing happens with words.

I have used a simple
number1 > number2
line to see which of a pair is bigger.

My question is: how may I add place value to my program?

thanks
Posts: 42
Joined: Wed Nov 16, 2011 3:04 pm
Post the code, let's have a look.
Please feel free to tap into my abundant lack of knowledge.

Posts: 399
Joined: Fri Sep 21, 2012 4:13 pm
Location: Up North
As you say 'similar thing happen with words' you are at the essence of the issue: your variables are most likely strings/text, so even though what you think of as numbers are actually string/text representation of the number - and because strings/text is sorted alphabetically (not numerically), "223" comes before "3".

Code: Select all
`Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> print 2 < 3True>>> print 223 < 3False>>> print "223" < "3"True>>> print "a2" < "a3"True>>> i = 223>>> j = 3>>> print i < jFalse>>> i = "223">>> j = "3">>> print i < jTrue>>>`

Now, as you say 'program which sorts a list of numbers and/or letters' you cannot really get both:
- if you have only numbers (in numeric variables), you can sort them in numeric order
- if you have only letters, you can sort then in alphabetic order
- if you have mixed numbers and letters, you can sort them in alphabetic order (or you have to create your own comparison function that returns something else)

Hope that is clears it at least a bit!

Hmm... just out of curiosity tried this:

Code: Select all
`>>> print "a" < 65False>>> print "2" < 3False`

...so it seems you can compare numbers and strings, but how the Python compares them is beyond me (a beginner in Python myself).
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 852
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
@ -rst-, it looks like it is comparing the ASCII (or maybe Unicode) encoding of the character. "2" is 50, and "a" is 97.

The problem is that things can get complex and ambiguous. How should these strings be ordered?

this2string1000
this19string900
1,456,234.3
1.456.234,3
1456234.3
14562343

It is ambiguous enough that any general solution would be insufficient more often than it was useful.

The pragmatic solution is to always use the same number of digits with leading zeros.

Moderator
Posts: 2877
Joined: Mon Jan 09, 2012 3:16 pm
Ok so having read your post I abandoned the idea of supporting non-number inputs.

To fix my code I changed the raw_input() to input() (code below) which seems to have changed the variable type in my list.

here is my (messy) code:
Code: Select all
`list_in=[]iterations = 1inputs=0print "how many numbers do you want to input?\n"to_be_input=input()print "input integers plz; and 00 to end input\n"while inputs<to_be_input:   input_last = input()   input_last   list_in.append(input_last)   inputs=inputs+1print "you just input\n" ,list_in, "\n beginning sorting"#next bit iterate until there is no more change between iterationswhile 1<2:   Y=1   changes=0   while Y<len(list_in):  #this loop is the single do/dont flip part of the code         X=Y-1      if list_in[X] > list_in[Y]:         tempX=list_in[X]         tempY=list_in[Y]         list_in[X]=tempY         list_in[Y]=tempX         changes=1      Y=Y+1   print iterations,list_in   iterations=iterations+1   if changes==0:      breakprint list_in`

now changing the raw_input() to input() means I cant have my nice input loop

1st: is there a way I can change the data type from raw_input to the type input() gives?
2nd: feel free to scream at me about how poor my code is: i want tips on how to improve it

thanks guys

PS: I know bubble sort is not the most efficient, but that is not the point of this
Posts: 42
Joined: Wed Nov 16, 2011 3:04 pm
Bubble sort is one of the best algorithms to start with (simple enough to understand and simulate with pen and paper)!

What do you think is 'not so nice' with this input loop?

I assume the 'and 00 to end' is left from your original... There is one extra line within the loop: the lonely 'input_last'. Other that that it looks ok - maybe the variable names could be a bit more descriptive and at least follow the same pattern: to_be_input, last_input, input_list, n_inputs (or num_inputs) ...these are a bit of a question of personal taste as well...

In the bubble sort you should be able to do the swap with only one extra variable - or maybe even without any - this is a good exercise The while loop as it is now, the test '1<2' could(/should) be written as 'True' (just because Python offers the boolean variable type, that is missing from many languages). Also the changes variable could be a boolean... And to polish it off, use a real (boolean) variable to replace the 'while True' + 'break'.

Guess that covers the Question 2

Answer to question 1: you could do
Code: Select all
`last_input = int(raw_input())`

...which is better than input() as it would fail for anything not integer ...obviously a good programmer would make sure the code can gracefully handle this - after you get all the rest working, see handling exceptions

Something to think...
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'
Posts: 852
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland
Thanks a lot!

yes the input 00 was an experiment to see if I could end the loop like that (before, I had it break on an empty space)

I see what you mean about the switch too: but I was going for ease-of-thinking rather than efficiency.

now to tinker on quick sort.... ( a bit more challenging methinks)
Posts: 42
Joined: Wed Nov 16, 2011 3:04 pm
"input()" is a security hole. The user can type Python code in and it will get interpreted

Code: Select all
`x = 42y = input()print y`

if the user types "x" then y is set to 42. Try it.

For that reason input() in Python 3 is redefined to be the same as raw_input() in Python 2, and Python 2 users are encouraged to use raw_input() only.

raw_input() always returns a string and it is the program's responsibility to convert it. Unfortunately the only clean way to do that is to use exceptions.
Code: Select all
`   x = raw_input()   try:      input_last = int(x)   except ValueError:      try:         input_last = float(x)      except ValueError:         input_last = x`

We try to convert it to an integer first, because that's the most stringent. If that fails we try to convert it to a float, and if that fails we leave it as a string.

Now we need to be able to compare strings with numbers, so we define a function to do that. It takes two parameters: a and b, and it returns -1 if a<b, +1 if a>b and 0 if they are the same:
Code: Select all
`def mytest (a, b):   if type(a) == str and type(b) != str:      return -1   elif type(a) != str and type(b) == str:      return +1         elif a < b:      return -1   elif a > b:      return +1   else:      return 0`

that just orders all strings lower than all numbers, but you can obviously enhance it if you have a better ordering in your application.

And you use the comparison function in the sort function:
Code: Select all
`while True:   Y=1   changes=0   while Y<len(list_in):  #this loop is the single do/dont flip part of the code         X=Y-1      if mytest(list_in[X], list_in[Y]) > 0:         tempX=list_in[X]         tempY=list_in[Y]         list_in[X]=tempY         list_in[Y]=tempX         changes=1      Y=Y+1   print iterations,list_in   iterations=iterations+1   if changes==0:      breakprint list_in`

By the way, you could just use
Code: Select all
`list_out = sorted(list_in)`

It does actually work, but the way it sorts strings and numbers is not defined and may change. So to be correct you have to tell it your comparison function. You can do that in Python 2:
Code: Select all
`list_out = sorted(list_in, cmp=mytest)`

but in Python 3 they've taken out the cmp parameter and the equivalent method requires even more newbie unfriendly language features.

Moderator
Posts: 2877
Joined: Mon Jan 09, 2012 3:16 pm