Ordering Number Lists


#1

I wonder if the very knowledgeable CS community can come to my aid once more? [-O<

I am looking to present a ranked list of variables and I am racking my brains to see if there is an easier way to do this…

NAME : SCORE
Bill :5
Ted :1
end of list

Now the instant option is…

*if (bill_score) > (ted_score)
NAME : KILLS
Bill : {bill_score} Ted : {ted_score}
end of list

and then continue for the other combinations… (easy if there are only 2 names on the list)
*if (bill_score) > (ted_score)
*if (bill_score) = (ted_score)

BUT… this suddenly becomes much harder (in my opinion prohibitively so) if there are additional categories to split a tied result, say…

NAME : SCORE : ATTEMPTS
Bill :5 : 3
Ted :5 : 6
end of list

AND what happens if there are 4 names on the list… or 10 or 20?!!

So… can someone come up with a sneakier work around or do I need to rethink my list… or do I just suck it up and write the mother of all *if/*elseif subroutines!! (*if a > b and a > c…and a > t then: abcdefghijklmnopqrst *elseif a < b and a >c… and a > t then: bacdefghijklmnopqrst :open_mouth: )


#2

You can mimic array behaviour and loop through them, but as it stands you would need to do a variable by variable comparison, that would just cut the amount of copy and paste down considerably. I believe there was a good example somewhere else, I’ll edit this post with it if I find it.


#3

@CJW wow - I didn’t understand a word of that… must mean it is a much better way of doing it… here’s hoping you can find it within the 30mind edit window…!


#4

One of the main privileges of being a mod is immunity to the 30 minute edit cutoff.


#5

I couldn’t find it… Sorry! If I get a spare moment this evening I’ll write my own example up.

Edit: And what a glorious boon that is! @Havenstone ^^


#6

:((

(fake edit within 30 mins - re-read post properly… that is very kind CJW - Thank you!)


#7

I’m working on it right now. Just a little rusty so it’s taking a while.

Edit: Believe it or not, it’s looking like it’d actually be easier to just write a long list of *ifs.

I’ve not done extensive testing, but this is based off of the bubble sort algorithm.
It basically runs through a list of numbers and compares each one to the one next to it, if the one next to it is bigger it swaps them. If it swaps during a run, it’ll run again, if it completes a run through the list without swapping - we can hopefully assume that everything is in the right order (biggest left, largest right).

This should give you a basis to work from, you’ll note that I’ve not incorporated a method for assigning names to scores - I’m a big believer in learning by doing, so see if you can’t do that bit by yourself? :wink:

Hope it works ok for you!


*comment assign our numbers to our fake "array"
*temp number_1 5
*temp number_2 10
*temp number_3 4
*temp number_4 7
*temp number_5 2
*temp number_6 5
*temp number_7 10
*temp number_8 4
*temp number_9 7
*temp number_10 2

*comment define extra variables
*temp have_swapped false
*temp pointer 0
*temp list_size 10

*label loop
*if ((pointer = (list_size -1)) and (have_swapped != true))
 *comment if no swaps are made we can (hopefully) assume that everything is in the right order and finish.
 *goto scoring
*if (have_swapped)
 *comment if a swap has been made at the end of a list iteration, reset the pointer and run again.
 *set pointer 0
 *set have_swapped false
 *goto loop
*set pointer + 1
*if (({("number_"&pointer)} > {("number_"&(pointer + 1))}) or ({("number_"&pointer)} = {("number_"&(pointer + 1))}))
 *comment if the left hand side number is bigger or equal to the right hand side, do nothing.
 *goto loop
*else
 *comment if the right hand side is bigger, swap them and flag as having swapped.
 *temp store {("number_"&pointer)}
 *setref ("number_"&pointer) {("number_"&(pointer + 1))}
 *setref ("number_"&(pointer + 1)) store
 *set have_swapped true
 *goto loop

*label scoring
[b]SCORING[/b]
*line_break
*line_break
*temp n list_size
*temp str ""

*label print_loop
*set str {"number_"&n}
${str}
*line_break
*set n - 1
*if n > 0
 *goto print_loop
*finish

If you want to test it:

https://dl.dropboxusercontent.com/u/7840892/CJW/choicescript/tools/online-cs-tester/mygame/index.html

You should only need to change the variables at the top (like list_size) and obviously create and set the right amount of number_# variables.


#8

@CJW
Edit: Believe it or not, it’s looking like it’d actually be easier to just write a long list of *ifs.

You know what… It F*****G isn’t!

But it IS pure genius my friend, that’s what it is! =D> ^:)^ =D>

I mean I can read it and I can see what it does (and I’ve even changed the direction of number travel…) but I still haven’t got a clue HOW it does it… I mean I kinda see what it does but I would NEVER had come up with that in a million years! (and you just knocked it up in a spare moment!)

thankyouthankyouthankyouthankyou =D> ^:)^ =D> (you get 2 as its soooo good!)


#9

Glad you like it, but if you can take the time to try and understand it a little bit - I’d highly recommend it. And if you have any questions - I’m always happy to answer!
A spare five minutes spent reading about bubble sorting will make it much easier to understand: http://mathbits.com/MathBits/Java/arrays/Bubble.htm

What I did was bare sorting basics, so if you end up making any additions or edits to it I’d love to know :slight_smile:


#10

@CJW I really am!

I’ve always struggled with the setref command… my brain doesn’t quite get round it yet! And totally get the idea on bubble sorting (i’ve used a similar (albeit much more basic) type of loop for selecting a random order for things to happen)

But I must say I am scratching at how to stick the name… its trickier than it looks (to me at least!)

*comment assign our numbers to our fake “array”
*temp number_1 5
*temp number_2 10
*temp number_3 4
*temp number_4 7
*temp number_5 2
*temp number_6 5
*temp number_7 10
*temp number_8 4
*temp number_9 7
*temp number_10 2

*temp name_1 “ONE”
*temp name_2 “TWO”
*temp name_3 “THREE”
*temp name_4 “FOUR”
*temp name_5 “FIVE”
*temp name_6 “SIX”
*temp name_7 “SEVEN”
*temp name_8 “EIGHT”
*temp name_9 “NINE”
*temp name_10 “TEN”

*comment define extra variables
*temp have_swapped false
*temp pointer 0
*temp list_size 10

*label loop
*if ((pointer = (list_size -1)) and (have_swapped != true))
*comment if no swaps are made we can (hopefully) assume that everything is in the right order and finish.
*goto scoring
*if (have_swapped)
*comment if a swap has been made at the end of a list iteration, reset the pointer and run again.
*set pointer 0
*set have_swapped false
*goto loop
*set pointer + 1
*if (({(“number_”&pointer)} < {(“number_”&(pointer + 1))}) or ({(“number_”&pointer)} = {(“number_”&(pointer + 1))}))
*comment if the left hand side number is bigger or equal to the right hand side, do nothing.
*goto loop
*else
*comment if the right hand side is bigger, swap them and flag as having swapped.
*temp store {(“number_”&pointer)}
*setref (“number_”&pointer) {(“number_”&(pointer + 1))}
*setref (“number_”&(pointer + 1)) store
*set have_swapped true
*goto loop

*label scoring
SCORING
*line_break
*temp n list_size
*temp str “”
*temp nom “”
*label print_loop
*set str {“number_”&n}
*set nom {“name_”&n}
{nom} {str}
*line_break
*set n - 1
*if n > 0
*goto print_loop
*finish

That’s where I’ve got to - but its late… I’m guessing I have to link a new variable to the sorted number… hmmm will try more tomorrow!

(edit : nope still stumped and can’t let it lie - what I have just writes a list of named numbers and I thought I might have to sort them too but I can’t since its in text… *grrr*)


#11

In the above code you don’t move the names when there’s a match, so they’ll not stay assigned to their number. If you’re still stumped tomorrow, I’ll fill you in!


#12

@CJW done it! \:D/

It is interesting why people choose to code late into the night when it is so much easier to get one’s brain around stuff in the morning when it is fresher (even though the body isn’t! My 3+3/4yr old decided that he wanted to keep waking up all night and still get up at 6.45am as fresh as a daisy!


*comment assign our numbers to our fake "array"
*temp number_1 5
*temp number_2 10
*temp number_3 4
*temp number_4 7
*temp number_5 2
*temp number_6 5
*temp number_7 10
*temp number_8 4
*temp number_9 7
*temp number_10 2

*temp name_1 "ONE"
*temp name_2 "TWO"
*temp name_3 "THREE"
*temp name_4 "FOUR"
*temp name_5 "FIVE"
*temp name_6 "SIX"
*temp name_7 "SEVEN"
*temp name_8 "EIGHT"
*temp name_9 "NINE"
*temp name_10 "TEN"

*comment define extra variables
*temp have_swapped false
*temp pointer 0
*temp list_size 10

*label loop
*if ((pointer = (list_size -1)) and (have_swapped != true))
 *comment if no swaps are made we can (hopefully) assume that everything is in the right order and finish.
 *goto scoring
*if (have_swapped)
 *comment if a swap has been made at the end of a list iteration, reset the pointer and run again.
 *set pointer 0
 *set have_swapped false
 *goto loop
*set pointer + 1
*if ({("number_"&pointer)} <= {("number_"&(pointer + 1))})
 *comment if the right hand side number is bigger or equal to the left hand side, do nothing.
 *comment <b>combined *if statements and swapped comparison direction in order to have sort list from big numbers downwards</b>
 *goto loop
*else
 *comment if the left hand side is bigger, swap them and flag as having swapped.
 *temp store {("number_"&pointer)}
 *setref ("number_"&pointer) {("number_"&(pointer + 1))}
 *setref ("number_"&(pointer + 1)) store
*comment <b>doubled up on these bad boys - I knew I had to do this last night, its just that in my fuzzy thinking I didn't now how to sort the "text" values of the name_x variables... but actually all I needed to do was to just swap any name_x variables in response to a corresponding swap of the number_x variables</b>
 *temp store2 {("name_"&pointer)}
 *setref ("name_"&pointer) {("name_"&(pointer + 1))}
 *setref ("name_"&(pointer + 1)) store2
 *set have_swapped true
 *goto loop

*label scoring
[b]SCORING[/b]
*line_break
*temp n list_size
*temp str ""
*temp nom ""
*label print_loop
*set str {"number_"&n}
*set nom {"name_"&n}
${nom} ${str}
*line_break
*set n - 1
*if n > 0
 *goto print_loop
*finish

What can I say - I am an uber-hacking-genius :-B !
*cough*

(ps: thanks again - would still be writing *if statements/hurling macbook out the window if not for you!)


#13

Knew you’d be able to do it, good job! :smiley:


#14

And I’m thinking that if we needed a tie breaker, all that would be needed would be an extra shuffler subroutine linked to another variable underneath when the first variable is the same on both sides.

So if left < right then swap
if right > left then no swap
if left = right then look at next variable
if left2 < right2 then swap
if left2 > right2 then no swap
if left2 = right2 then look rinse and repeat etc etc

I think @CJW stands for @CoolJW!


#15

Well as it stands it doesn’t swap identical numbers, but that’s not an issue as the order is correct regardless of which “7” (or other number) comes first.

If you’re looking to decide who gets first/second/third place when there’s identical scores you could just compare the top three variables under the scoring label.

Proof of multiple number order concept (sorry some of the markers are messed up in the pre tags)


||
318137793
3 > 1 - do nothing

  ||
318137793
1 < 8 - swap

    ||
381137793
1 = 1 - do nothing

      ||
381137793
1 < 3 - swap
   
        ||
381317793
1 < 7 - swap

          ||
381371793
1 < 7 - swap

           ||
381377193
1 < 9 - swap

             ||
381377913
1 < 3 - swap

||
381377913
3 < 8 - swap

  ||
831377913
3 > 1 - do nothing

    ||
831377913
1 < 3 - swap

      ||
833177913
1 < 7 - swap

        ||
833717913
1 < 7 - swap

          ||
833771913
1 < 9 - swap

           ||
833779113
1 = 1 - do nothing

             ||
833779113
1 < 3 - swap

||
833779131
8 > 3 - do nothing

  ||
833779131
3 = 3 - do nothing

    ||
833779131
3 < 7 - swap

      ||
837379131
3 < 7 - swap

        ||
837739131
3 < 9 - swap

          ||
837793131
3 > 1 - do nothing

           | |
837793131
1 < 3 - swap

             ||
837793311
1 = 1 - do nothing

| |
837793311
8 > 3 - do nothing

  | |
837793311
3 < 7 - swap

    ||
873793311
3 < 7 - swap

      ||
877393311
3 < 9 - swap

       ||
877933311
rest of comparisons in this list will obviously do nothing.
So back to the start...

 ||
877933311
8 > 7 - do nothing

  ||
877933311
7 = 7 - do nothing

    ||
877933311
7 < 9 - swap

      ||
879733311
rest of comparisons in this list will obviously do nothing.
So back to the start...

||
879733311
8 > 7 - do nothing

  ||
879733311
7 < 9 - swap

    ||
897733311
rest of comparisons in this list will obviously do nothing.
So back to the start...

||
897733311
8 < 9 - swap

  ||
987733311
rest of comparisons in this list will obviously do nothing.
So back to the start...

No swaps this time, so we're in order - aren't we?

9 8 77 333 11


#16

@CJW The visual guide is very helpful thank you! However just got stuck again!! I have successfully increased the list to 20 and added some permanent variables to it it but I was wondering about how to only display the top 10 in the list…

I know I still need the sub-routine to order all 20 variables… (just setting list size to 10 doesn’t work as it just orders the first 10 on the list - leaving out the bottom 10 entirely!)
So I’m thinking it has to do with the *label scoring bit…

So all you have to do is

*if n > 11

et voila

Wow - you’re good… teaching me when you’re not even here!


#17

@CJW actually really *have* got stuck again… (and this actually *might* not be possible!)

Say we order out list of 20 (easy)
And we only print the top 10 (done)

I would like the option to show the MC’s score / position if they were ranking 16th for instance (and therefore wouldn’t show in the top 10. The way the subroutine is written, I’m not sure you CAN search to see if any particular number occurs in a particular position in the list… can it?

eg:
TOP 10 RANKINGS
1 : 7 points : Emily
2 : 7 points : Colin
3 : 6 points : Jenny
4 : 6 points : Rob
5 : 6 points : Erik
6 : 5 points : Konrad
7 : 5 points : Chen
8 : 5 points : Casey
9 : 5 points : Tamara
10 : 5 points : Johnny

16 : 3 points : MC ADDED AS MC is not in the TOP 10

but if MC’s score is higher…
TOP 10 RANKINGS
1 : 7 points : Emily
2 : 7 points : Colin
3 : 6 points : Jenny
4 : 6 points : Rob
5 : 6 points : Erik
6 : 5 points : MC
7 : 5 points : Konrad
8 : 5 points : Chen
9 : 5 points : Casey
10 : 5 points : Tamara

The *if command is going to have to check where (MC >= 10th place) in which case do nothing OR if (MC <10th place) then print their position and score separately…

I tried lots of combos of str/nom taking your example variables - but can’t get to show the MC’s position - and when I “fudge” it… it doesn’t work when the MC score is higher or lower… :-?


#18

There are - as always - numerous ways of approaching it. It’s arguably inefficient, but you could just add a new routine which cycles through the entire list of names and prints one if it’s a match AND isn’t in the top 10.

I haven’t tested that, I just wrote it straight into this post, so it may not work - but hopefully gives you a rough idea. There are other ways to do it, but that’s the first one that springs to mind!

This should be run after printing the scores.


*label check_player_position
*temp n 0
*label name_check_loop
*set n + 1
*if ({"name_"&n} = player_name)
  *if (n <= 10)
    *comment do nothing/as it's already printed
    *finish
  *comment else double line break and print
  *line_break
  *line_break 
  *temp your_score {"number_"&n}
  You didn't make the top ten, your final score was ${your_score}.
*if (n = list_size)
   *finish
*goto name_check_loop


#19

@CJW And another thing… found serious issue with trying to ADD to the variables in our “array”

Added a simple ADD +10 to temp variable number_5… should move it up the list now huh? Well it does on the first pass… and then all kinds of crazy breaks loose!
(is this what you meant be maybe if statements would be easier?!) :(( head hurting and really lost now…

@CJW wow… sorry about being such a pain in the a… Don’t know why but this kind of coding level (ie: basic!) just doesn’t seem overly intuitive to me… I have figured out that IF I define a set of temp variables and then clear them before I import the new permanent variable scores in… I can ADD to them and re-rank them…

*sigh* I’ll try not to bother you too much more! And thanks for the above too - will have a good look at it… although I may end up ditching it the idea… particularly as I want to find out where the MC is in the top 20 and then print the actual position AND the score… head still hurts!


#20

Well what I gave you prints the score, and to print the position you’d just add one more line that prints the n variable, no? ^^

Your problem is likely that you just THINK it’s harder than it actually is, try relaxing a little! Take a break every now and again, get a cup of tea. It’ll slowly come together.

I don’t see how or why you’d have any issues with adding to the numbers, as long as you’re doing it before you’re sorting them, not during or after.

Although, that said. This isn’t basic coding anymore, this is getting a little more advanced - at least in terms of choicescript. “Proper” programming languages would have all sorts of methods and functions that would actually do all this sorting stuff for you.