Saturday, May 18, 2013

PyTutorial: playing with actions


This is the 3rd in a series of posts.  If you want to go the the start, go here.

In the previous tutorial, we created various types of information.  Now, we're going to do stuff with them.

Take the list, for instance:
>>> booga = [5, 3, 6, 29, 3, 2, 4]

Suppose we want to print each item in the list to the screen.  How do we do that?
Well, we can print the whole list at once, like this:  (try it)

>>> print booga

or we can do the tiring work of printing them individually like this: (try this too, yes, go ahead and suffer)
>>> print booga[0]
>>> print booga[1]
>>> print booga[2]
>>> print booga[3]
>>> print booga[4]
>>> print booga[5]
>>> print booga[6]

But, you ask yourself, there must be a better way!  Well, actually, there is!

For loop galore!

Just about every programming language has ways to loop through lists.  Python offers a convenient way using a "for" loop.  Before explaining it, I just want you to see how it looks like, and think about what it does:


Hmmm... Fascinating, isn't it?  By the way, this is all typed in a file called "booga1.py", as explained in the previous tutorial under the headline of "I'm tired of using IDLE and all the ">>>", I want to program like a BOSS!".  Look at it again if you forgot about it.  I know I have. :)

So, what happened there? Have you figured it out? Great! Let's move on.

Ok ok!! I'll explain it!!!! No need to get huffy.  So the first line should be obvious by now, we're creating a list, and calling it "booga". 

The next line is the new part.  There is a "for" (in lower case, that's important).  IDLE colors it orange because it's a special keyword that tells Python to do a loop.  Now what is this "zukini" all of a sudden?  And this whole "in" business? 

The way to loop through a list in Python is to tell python which list you want to loop though, and also tell python into which variable you want to put each individual list item while looping over it.  In this case, we're looping though the list booga, and we, arbitrarily, asked Python to place each loop item in a variable named "zukini".  We could have called it anything else.  Yes, even "Razban".


Notice that the Python code is fairly structured: to write a "for" loop, one needs to write "for", then the variable name that is used as a place-holder for every item in the list, then the word "in", then the list name, and finally a colon, ":".  Then, to actually do something (presumably with the items), one needs to use indentation (use the "Tab" key in the keyboard) to tell Python do perform that line of code for every item in the loop.
More on Python and tabs: tabs are very important to Python.  In a way, tabs are like a "hidden" command.   Hidden, because, well, you don't really see that tab, do you? :)  But it's there, and it's how Python can figure out what it needs to do.  In loops, the tabs tell Python which part of the code is a part of the loop, and which isn't (you'll see examples in a moment.)  I just want to stress to you the importance of tabs, and that you should pay close attention to how your Python code is indented.  It makes a difference.  Sometimes, a big one.   
Another little note, is that IDLE sometimes can figure out that you need a tab, and will place one there for you automatically. For instance, if you press <Enter> after the colon, you'll notice that IDLE has indented the next line for you automatically!   Of course, you can change the indentation in your code easily, just like in any other word processor, by using the <Tab> and <Backspace> keys.  
In our case, all we want to do is print that item to the screen, so we wrote "print zukini", and that's all.  But we could have done a lot more in the loop.  For instance, to double each item in the loop, and then print it, we can do something like this:


Or even something like this:

Notice how all three lines are indented?  This tells Python to perform all of them for each item in the list.

As you can see, there are plenty of ways of achieving the same end.  When you write code, try to make chose a way that not only gets the job done, but does it in the most elegant way possible.  So, if I had to chose between the above two examples, I would clearly have chosen the former.  But it's a matter of style and personal preference as well.

Assignment 3.1: using our "booga" list, make a loop that prints each value squared (multiplied by itself).
Assignment 3.2: again, using "booga", make a loop that prints each value squared plus seven.
Of course, in a program, you can have more than one for loop.  You can do whatever you want in your code.  For instance you can do stuff like this, or anything else you feel like:


Try to figure out what it'll do.  Then type it in and see if it does what you expect.
Assignment 3.3: play with the above code, add more loops, add more lists, go wild, really!
Did you go wild?  Great.
Now we're about to go even wilder!

Check this out:

Holy Shmoly!!  What are we seeing here?  Can this be?  Is this real?
Notice the lists within a list?  Notice the loop within a loop?
What do you think will happen when you run it?  Try typing it in and find out!  You can also add a "print a" above the "for b in a:" line to help you see what is going on.

Now!

Great.  As you have noticed, it printed all the items in all the lists.  The way this works is basically like this:

  • The outer for loop (that is, "for a in beep:") places each item of the list beep inside variable a, and then runs the indented code.  If you look closely at beep, you will see that it is a list, in which each item of the list is another list!  Thus a first gets the list [3, 4, "hi"], and then it gets the list [2, 4, 9, 22, 44], and finally, it gets the list ["hi", and "there"].  You see, Python doesn't care about what you have in the list, when you do a for loop on a list, it runs through each item of the list, whatever it may be (in our case about, each of them is another list.)
  • The inner for loop (that is, "for b in a") runs through each item of list a and places it inside variable b.  This code only works because a is always a list, which only works because all the items inside beep are lists.  It then runs the indented code ("print b") for each such item.  To see how this code can break, try changing beep to contain some non-list items, like so:
    beep = [ [3, 4, "hi"], 7, [34, 5, 2] ].  What do you get when you run it now?  Do you see that you get an error when a is 7?  That's because you can't run a for loop on a number!  


All that may have seemed like a lot of hard work for very little.  But what about this:

Wow, now we're talking.  A lot of things are going on here.  Can you figure them out?
Again, try typing it in and see what happens.  But because it's a bit long, I'll show you what I get when I run it, just so you have something to compare with:
Can you follow what's going on here?

It's becoming less and less trivial to follow the code, isn't it?  And you can expect it to get even harder to follow as what you're trying to do gets more and more complicated.  Figuring out what it does or what's wrong with it gets harder and harder.  This is why elegance is of supreme importance when coding.  It actually ends up saving time and energy in the long-run.  Can you figure out how this program basically sums up the product of all the items in the sub-lists?  Or in English: for each list within the large list, the program multiples all its items together.  Then, to get the "grand total", it adds all those numbers up!  Simple no?
Assignment 3.4: Modify the loop-within-the-loop program above to add together all the items in the sublists, and then, to get the grand total, multiply the resulting numbers together.  (Note, your grand total should not be 0, obviously.  It should be 1650.  hehe, did you get that?)
 Nice.

Decision Time!

Just as in real life, most programs need to make many decisions.  In most computer languages this is pretty straight-forward, and Python is no exception.  Check this out:
Can you guess what it does?  Type it in and find out!! Again, notice that "if" and "else" are keywords in orange, and thus must be typed in lowercase.  Also, notice the colons at the end of the "if" and "else" statements.  And again, notice that after the "if" and "else", the "print" statements are indented (kind of like in the for loops).  I would type it in a new file, call it whatever you like, and run it (by pressing F5, remember?)

Did you try it?  Did you see that "large number" was printed on the screen?  Now what do you think will happen if instead of having x equal 4 at the start, you set it equal to 0?  What about if it's set to 2?  Try it!

It's also possible to make more complicated decisions, such as:
Type the above in and run it.  Notice that we can test for more than one thing at the same time, using the "and" and "or" keywords, as well as test for more than one variable at a time (x and y, in our case).   Also note that by using indentation, you control what gets run if what you're testing, or condition, in tech-speak, is correct (or true, in tech-speak).  Try changing the values for x and y and see what happens.  How about trying:

  • x= 4, y = 9
  • x=200, y = 200
  • x=200, y=-10
One thing to get used to is, when checking that a value equals something, you use the double-equal sign, ==.  That is, if you want to assign a value to a variable, such as the number 33 to variable, hi, you would do something like this:
>>> hi = 33

Yet, if you want to check to see if hi already equals 33 (without assigning anything to it), you can do something like this:
>>> if hi == 33: .......

In other words, a single-equal sign assigns a value to a variable, while a double-equal sign compares two values.

Basically, these are the comparisons that you can do:
Of course, you can compare any sort of data, including text (and even lists):
What do you think will get printed?  Try it and find out! :)
Assignment 3.5: try to do some if-else statements that compare integers, floats, and strings.  Go wild here.
The way this all works in Python is by having a new type of data (like integers and strings) called boolean, which can either be "True" or "False":
>>> type(True)
>>> type(False)
>>> x = True
>>> type (x)
>>> x = 7 > 3
>>> print x

This means that you can do things like this:

Do you see what happens there?

As you have probably guessed by now, you can have some rather complicated conditionals.  Using parenthesis, you can make them even more complicated:

You can basically do whatever you want.  There's also a "not" keyword, which basically turns a "True" into a "False" and a "False" into a "True":
Sometimes, it can make the code clearer.  You don't have to use it.

BTW, you may have noticed that sometimes I only have an "if", and sometimes I have an "if" and later an "else".  Basically, to test for a condition, you use an "if" statement.  If you want to do something when that condition fails, you can use the "else".  But what if, when a condition fails, and only when it fails, you want to check for another condition before doing something?  Well, you can do this in one of two ways.  The easy way or the ugly way.

The easy way is this:

See the "elif" keyword.  Nice, isn't it?  It stands for "else if".  Type it in and try it out for different values of x.
Note that the above is very very different from this:

All I did was change the two "elif" statements with "if" statements.  Do you see that?  But now, the program will work very differently.  Again try it with different values for x (for instance, try 200, 70, 20, and 5)

What differences do you notice?  You can read the comments (in red) to get a better understanding of why the two similar programs behave differently.  An "elif" is only run if all the previous "elifs", up to the "if" are false.  Thus they are dependent on each other.  Same goes with the "else".  On the other hand, an "if" starts a new group of dependencies, and is independent of the if/elif/else above it.

Thus in the first case, all the conditional tests are dependent on each other, thus only one of them can have its code run.  In the second example, the first three "ifs" are independent, thus any of one them can have its code run.  Try running it with the values 200, 70, 30, and 5 to see what I mean.  Of course, in the second example, the "else" is dependent on the "if" above it, thus between them, only one can have its code run.

BTW, you don't need to have an "else" in the end.  You can have a lone "if", or an if with as many "elifs" as you like with or without an "else" in the end.
Assignment 3.6: play around with ifs, elifs, and elses....  See what you can do with them.  Pay close attention to the indentations, and remember, using indentation, you can have more than one "print" statement following an "if" or anything else.  
Now, as promised, the ugly (but important to understand) way to do things.  I can write the first example from above in a different way, but in a way that behaves in exactly the same way:
I added the red shapes in order to highlight the importance of indentation here.  Python is very indentation sensitive.  It's part of what makes the code so clean and beautiful, but it must be something that you need to be aware of.   See how the indentation actually determines which part of the code is relevant for each "if" or "else" statement.   Also, you can see that you can have an "if" within an "else" statement.  You can also have an "if" within an "if", or an "if" within an "elif".  You can do just about whatever you imagine, just pay close attention to the indentation, as it's the invisible hand that calls the shots in Python.

Look at the following code:
Do you see how the two if statements are similar, yet different?
Try running it with various values for x, such as: 150, 300, and 50.  They behave differently, can you figure out why?
Assignment 3.7: play around with the above code until you figure out why or why or why?!!!

The Power, oh the Power!

Can you imagine what happens when you mix the power of the loop with the glory of the conditional statement?  That's right.

Check this out:
Don't be afraid.  Go ahead and type it in, and then let it run!
Exciting, isn't it?

Did you get that the max val is 94?  What you did here was write your first algorithm, tech-speak for a logical way to solve a problem.  Given any list z, we end up printing its largest item.  
Assignment 3.8: play around with different values in z, and see what happens.
Have you, by chance, placed in z all negative numbers, such as [-30, -22, -99, -38] ?
If not, try it now.  What do you expect to get?  What do you actually get?
Well, the largest number in [-30, -22, -99, -38] is -22.  So why do you get 0?  0 isn't even in the list!

HAHAHAHAHAHAHA!!! I believe that this is your first real bug.  Life as a programmer truly sucks, and now you know why.

Well, what can you do to solve this little problem of ours?
Assignment 3.9: think about it for 10 minutes and then get back to me.
Well, how did the thinking go?  Were you able to make it work?  There are a few ways to solve this, the good, the bad, and the ugly.  Lets start with the bad:

All I did here was change max_val for 0 to -9999999.  It works with our z. Great!  Not great.  If z was [-999999999, -9999999999], we would still get the wrong answer.  Thus this is basically lame.

The ugly way is basically something like this:
Can you figure out how it works?  Try typing it in and see what happens.  Basically, we added a new variable, found_something, that keeps track of whether or not we found something, anything.  In tech-speak, this type of variable is usually called a "flag", because it's used to signal (like a flag) that something is going on.  In our case, that something is whether or not we have a real value (from the list) assigned to max_val.   We're basically using  found_something to tell us something about max_val:  when found_something is False, it indicates that max_val has no meaning, that is it's just some random number we came up with, in our case, "0".  But when found_something is True, it indicates that max_val is meaningful, that is, it contains a value that is actually found in the list.

Note that found_something starts out False, and the first item in the list immediately sets it to True. Thus our logic here becomes: if we haven't seen anything yet, we just grab that item (which always happens to be the first item) without comparing it to anything.   Otherwise (and for all other items), we need to compare that value with max_val when deciding whether or not to assign it to max_val.

That way, we're only comparing items in the list to each other, and not to an arbitrary number that we made up.  It's a step forward.  Ugly, but a step forward.  Yet there is still a bug here!

NO?!!! YES!!!!!  NO?!!!!! YES!!!!!! NO?!!!!!! YES?!!!

Try giving it an empty list, such as:
z = []

Then what happens?  It says that the max vals is 0, when in fact there aren't any values at all!!  Well, one way to get over this, is to do something like this:

Now it works well.  But it's UGLY....  And ugly means hard to understand, or change in the future.  And if there's something we know for certain, is that sooner or later, the future is bound to arrive.

How about this:
Much cleaner, isn't it?  So what are we doing here?
First, we're checking to see if the list is empty using the len command.  Did you forget all about the len command?  Go back to the previous section on information and get reacquainted.  :)  It basically gives you, or returns, in tech-speak, a number that is the number of items in the list.  Thus if len(z) equals 0, it means that the list is empty.

If the list is not empty, we know we can take the first item in the list and assign it to max_val.  This way, we're only comparing items in the list to each other, and not to some arbitrary values.

Like what you see?  Awesome! Now it's time for you to sit on your ass and work:

Test first, dive-in later

Before giving you your next assignments, I want to mention one of the most important aspects in software development: it's called unit-testing.  What this means is that you should have a plan on how you're going to find out whether or not your program is working as expected.  As you can tell by now, it's not very easy to just "look" at a piece of code and figure out exactly what it does, or what it doesn't do.  Even very simple programs may have had one thing over-looked, and then it just won't work at times. 

There are many ways to do unit-tests.  When writing large programs, it's good to have an automatic unit-testing system.  All that means is that you actually write a program that tests your main program!  Sounds a bit crazy, but trust me, it really makes a world of a difference.  In fact, I would say that:
Writing unit tests regularly is the single most important difference between professional and amateur software developers.
In fact, good developers actually write the tests before writing the actual code.  This is a great habit that lets you think about the code you're about to write from a requirements perspective.   This is a key time-saver as well as bug-saver tool.  And what's so great about it, is that it can actually help you determine, after you wrote the code, whether or not it works!   Basically it won't kill you to actually think about what the program should do for a few minutes before actually writing it.  So, let's dive in:

A little project
Thus, if one encounters a project such as this: (which I expect you to do, of course)
Assignment 3.10: similar to the example above, given a list of numbers, z, find the smallest item in the list.  
One should write the unit-tests that are appropriate for it, in advance, and then use them to find out if the program works well.  Here are some unit tests that I can think of:
  • z = [56, 34, 92, 543] ==> 34
  • z = [4, 6, -2, 589]  ==>  -2
  • z = [-4, -6, -2, -589]  ==>  -589
  • z = [5]  ==>  5
  • z = []  ==> "An empty list can't have a smallest item, you fool!"
  • z = [1, 3] ==> 1
  • z = [4, 7, 239, 35, 5, 0, 3, -2, 53, 5, 2, -452, 5, 3, 2, 7, 93] ==> -452
  • z = [1, 3, 9] ==> 1
  • z = [3, 1, 9] ==> 1
  • z = [3, 9, 1] ==> 1
  • z = [0, 0, 0, 0] ==> 0
Do you get the idea?  As you can see, I tested for "normal" cases, as well as some "edge" conditions, such as an empty list, a list with one, two, three, or many items...  I also tested for a list with the same values, or a list in which the smallest value is in the beginning, middle, and end.

Of course, these tests have nothing to do with how I actually end up writing the code to find the smallest item in z.  Which is a good thing, because it doesn't limit me in any ways.  On the other hand, if the code "seems reasonable" and works as expected for all the test cases above, then it most likely works as expected!
Assignment 3.11: write a few more tests cases to add for the collection above.  Have I missed anything?  Can you think of any other interesting scenarios to test?
Assignment 3.12: Now, write the actual code to find the smallest item in z.  When you're done, you'll know whether or not it works if it passes all the tests that you have!  You're such a professional! 
Well, that wasn't too hard, I hope.   Here's a harder challenge:
Assignment 3.13: given a list of numbers, z, find the two largest items in the list.
This one is a bit tricky, but after spitting out enough blood, you should be able to figure it out.  Of course, being a professional by now, I shouldn't even need to tell you to write the test cases first.  But just to be nice, I'll start you out with a few ones:

  • z = [4, 2, 6, 9] ==> largest = 9, second largest = 6
  • z = [] ==> seriously?  an empty list?
  • z = [5, 9, 100, 4, 100, 8] ==> largest = 100, second largest = 100
Go ahead and add a lot more test cases here.  Then start writing the damn code.

Minesweeper time!

Now, let's apply what you've learned in this tutorial to your little Minesweeper project. :)  
  • Given a single Minesweeper cell (that you came up with in the last lesson), can you write the code that checks whether or not it has lost the game?  That is, can you check if it has been clicked but has a mine?
  • Given a single Minesweeper cell (that you came up with in the last lesson), can you write the code that checks whether or not it brought the player closer towards winning the game?  That is, has the player clicked on it, and it doesn't contain a mine?
Just like last time, I wanted you to concentrate on a single cell.  We'll get to an entire grid of cells later. But just like last time, for the extra challenge, can you figure out the code for a single row of cells (say, one that contains 5 cells)?
  • Given a single Minesweeper row, can you write a for loop that checks whether or not the game has been lost?  That is, has the user clicked on any cell that has a mine?
  • Given a single Minesweeper row, can you write a for loop that checks whether or not it brought the player closer towards winning the game?  That is, has the user clicked on every cell in that row that does not have a mine, while not having clicked on any cell that does?
Whew! :)

A final note

If you got this far, you're good.  Pat yourself on the back.  Twice.  You're a lot more on your way to being a programmer than you can probably imagine.  :)

If not, keep trying.  Cry yourself to sleep if you have to.  Eventually, you will figure it out.  This stuff can be hard, and remember: computers are dumb and do exactly what you tell them to do!

Thus far you got introduced to the two key aspects of programming: playing with information and actions.  You may not actually believe me, but that's what actual programming is about!  This is what a computer can do, that, and nothing else.  If you can master this, you're basically a computer programmer.  A fairly useless one, but quite possibly a very proficient one.  What makes a programmer useful is not how well she writes loops and conditional statements (although that's the basics, of course), but a a host of other things.

On the programming level, this includes how well one organizes the program.  This means using functions, classes, and external libraries.  Things that make no sense to you now, but soon will.  But no less important are all the things that surround software development:

  • writing unit tests 
  • writing elegant code
  • understanding what's out there as to not reinvent the code.  (I'll go into this later)
  • understanding the real requirements (not just what people say, but what they mean.)
  • and of course, understanding the business needs behind what needs to be done
  • having patience, lots of patience
While some of the above is technical, a lot of it actually isn't.  I worked with some great developers that weren't "real geeks", and this is part of the reason for why.  

In the next post, I'll continue with the whole actions business, as it is fairly basic.  We'll have more fun with loops, conditionals, and information.  Brace yourself! :)

So I've got another riddle for ya...

Can you decode this list?

[37, 359, 419, 422, 452, 203, 422, 452, 203, 455, 419, 410, 203, 260, 449, 407, 203, 422, 437, 203, 398, 203, 452, 410, 449, 422, 410, 452, 203, 440, 413, 203, 443, 440, 452, 455, 452, 245, 203, 203, 326, 413, 203, 470, 440, 458, 203, 464, 398, 437, 455, 203, 455, 440, 203, 416, 440, 203, 455, 419, 410, 203, 455, 419, 410, 203, 452, 455, 398, 449, 455, 239, 203, 416, 440, 203, 419, 410, 449, 410, 245, 37, 37, 326, 437, 203, 455, 419, 410, 203, 443, 449, 410, 461, 422, 440, 458, 452, 203, 455, 458, 455, 440, 449, 422, 398, 431, 239, 203, 464, 410, 203, 404, 449, 410, 398, 455, 410, 407, 203, 461, 398, 449, 422, 440, 458, 452, 203, 455, 470, 443, 410, 452, 203, 440, 413, 203, 422, 437, 413, 440, 449, 434, 398, 455, 422, 440, 437, 245, 203, 203, 341, 440, 464, 239, 203, 464, 410, 224, 449, 410, 203, 416, 440, 422, 437, 416, 203, 455, 440, 203, 407, 440, 203, 452, 455, 458, 413, 413, 203, 464, 422, 455, 419, 203, 455, 419, 410, 434, 245, 37, 37, 359, 398, 428, 410, 203, 455, 419, 410, 203, 431, 422, 452, 455, 239, 203, 413, 440, 449, 203, 422, 437, 452, 455, 398, 437, 404, 410, 281, 37, 293, 293, 293, 203, 401, 440, 440, 416, 398, 203, 290, 203, 380, 266, 239, 203, 260, 239, 203, 269, 239, 203, 257, 278, 239, 203, 260, 239, 203, 257, 239, 203, 263, 386, 37, 37, 356, 458, 443, 443, 440, 452, 410, 203, 464, 410, 203, 464, 398, 437, 455, 203, 455, 440, 203, 443, 449, 422, 437, 455, 203, 410, 398, 404, 419, 203, 422, 455, 410, 434, 203, 422, 437, 203, 455, 419, 410, 203, 431, 422, 452, 455, 203, 455, 440, 203, 455, 419, 410, 203, 452, 404, 449, 410, 410, 437, 245, 203, 203, 323, 440, 464, 203, 407, 440, 203, 464, 410, 203, 407, 440, 203, 455, 419, 398, 455, 296, 37, 368, 410, 431, 431, 239, 203, 464, 410, 203, 404, 398, 437, 203, 443, 449, 422, 437, 455, 203, 455, 419, 410, 203, 464, 419, 440, 431, 410, 203, 431, 422, 452, 455, 203, 398, 455, 203, 440, 437, 404, 410, 239, 203, 431, 422, 428, 410, 203, 455, 419, 422, 452, 281, 203, 203, 227, 455, 449, 470, 203, 422, 455, 230, 37, 37, 293, 293, 293, 203, 443, 449, 422, 437, 455, 203, 401, 440, 440, 416, 398, 37, 37, 440, 449, 203, 464, 410, 203, 404, 398, 437, 203, 407, 440, 203, 455, 419, 410, 203, 455, 422, 449, 422, 437, 416, 203, 464, 440, 449, 428, 203, 440, 413, 203, 443, 449, 422, 437, 455, 422, 437, 416, 203, 455, 419, 410, 434, 203, 422, 437, 407, 422, 461, 422, 407, 458, 398, 431, 431, 470, 203, 431, 422, 428, 410, 203, 455, 419, 422, 452, 281, 203, 227, 455, 449, 470, 203, 455, 419, 422, 452, 203, 455, 440, 440, 239, 203, 470, 410, 452, 239, 203, 416, 440, 203, 398, 419, 410, 398, 407, 203, 398, 437, 407, 203, 452, 458, 413, 413, 410, 449, 230, 37, 293, 293, 293, 203, 443, 449, 422, 437, 455, 203, 401, 440, 440, 416, 398, 380, 251, 386, 37, 293, 293, 293, 203, 443, 449, 422, 437, 455, 203, 401, 440, 440, 416, 398, 380, 254, 386, 37, 293, 293, 293, 203, 443, 449, 422, 437, 455, 203, 401, 440, 440, 416, 398, 380, 257, 386, 37, 293, 293, 293, 203, 443, 449, 422, 437, 455, 203, 401, 440, 440, 416, 398, 380, 260, 386, 37, 293, 293, 293, 203, 443, 449, 422, 437, 455, 203, 401, 440, 440, 416, 398, 380, 263, 386, 37, 293, 293, 293, 203, 443, 449, 422, 437, 455, 203, 401, 440, 440, 416, 398, 380, 266, 386, 37, 293, 293, 293, 203, 443, 449, 422, 437, 455, 203, 401, 440, 440, 416, 398, 380, 269, 386, 37, 37, 305, 458, 455, 239, 203, 470, 440, 458, 203, 398, 452, 428, 203, 470, 440, 458, 449, 452, 410, 431, 413, 239, 203, 455, 419, 410, 449, 410, 203, 434, 458, 452, 455, 203, 401, 410, 203, 398, 203, 401, 410, 455, 455, 410, 449, 203, 464, 398, 470, 206, 203, 203, 368, 410, 431, 431, 239, 203, 398, 404, 455, 458, 398, 431, 431, 470, 239, 203, 455, 419, 410, 449, 410, 203, 422, 452, 206, 37, 37, 317, 440, 449, 203, 431, 440, 440, 443, 203, 416, 398, 431, 440, 449, 410, 206, 37, 37, 329, 458, 452, 455, 203, 398, 401, 440, 458, 455, 203, 410, 461, 410, 449, 470, 203, 443, 449, 440, 416, 449, 398, 434, 434, 422, 437, 416, 203, 431, 398, 437, 416, 458, 398, 416, 410, 203, 419, 398, 452, 203, 464, 398, 470, 452, 203, 455, 440, 203, 431, 440, 440, 443, 203, 455, 419, 449, 440, 458, 416, 419, 203, 431, 422, 452, 455, 452, 245, 203, 203, 347, 470, 455, 419, 440, 437, 203, 440, 413, 413, 410, 449, 452, 203, 398, 203, 404, 440, 437, 461, 410, 437, 422, 410, 437, 455, 203, 464, 398, 470, 203, 458, 452, 422, 437, 416, 203, 398, 203, 209, 413, 440, 449, 209, 203, 431, 440, 440, 443, 245, 203, 203, 305, 410, 413, 440, 449, 410, 203, 410, 467, 443, 431, 398, 422, 437, 422, 437, 416, 203, 422, 455, 239, 203, 326, 203, 425, 458, 452, 455, 203, 464, 398, 437, 455, 203, 470, 440, 458, 203, 455, 440, 203, 452, 410, 410, 203, 419, 440, 464, 203, 422, 455, 203, 431, 440, 440, 428, 452, 203, 431, 422, 428, 410, 239, 203, 398, 437, 407, 203, 455, 419, 422, 437, 428, 203, 398, 401, 440, 458, 455, 203, 464, 419, 398, 455, 203, 422, 455, 203, 407, 440, 410, 452, 281, 37, 37, 37, 37, 323, 434, 434, 434, 245, 245, 245, 203, 317, 398, 452, 404, 422, 437, 398, 455, 422, 437, 416, 239, 203, 422, 452, 437, 224, 455, 203, 422, 455, 296, 203, 203, 305, 470, 203, 455, 419, 410, 203, 464, 398, 470, 239, 203, 455, 419, 422, 452, 203, 422, 452, 203, 398, 431, 431, 203, 455, 470, 443, 410, 407, 203, 422, 437, 203, 398, 203, 413, 422, 431, 410, 203, 404, 398, 431, 431, 410, 407, 203, 209, 401, 440, 440, 416, 398, 254, 245, 443, 470, 209, 239, 203, 398, 452, 203, 410, 467, 443, 431, 398, 422, 437, 410, 407, 203, 422, 437, 203, 455, 419, 410, 203, 443, 449, 410, 461, 422, 440, 458, 452, 203, 455, 458, 455, 440, 449, 422, 398, 431, 203, 458, 437, 407, 410, 449, 203, 455, 419, 410, 203, 419, 410, 398, 407, 431, 422, 437, 410, 203, 440, 413, 203, 209, 326, 224, 434, 203, 455, 422, 449, 410, 407, 203, 440, 413, 203, 458, 452, 422, 437, 416, 203, 326, 311, 335, 314, 203, 398, 437, 407, 203, 398, 431, 431, 203, 455, 419, 410, 203, 209, 293, 293, 293, 209, 239, 203, 326, 203, 464, 398, 437, 455, 203, 455, 440, 203, 443, 449, 440, 416, 449, 398, 434, 203, 431, 422, 428, 410, 203, 398, 203, 305, 344, 356, 356, 206, 209, 245, 203, 203, 335, 440, 440, 428, 203, 398, 455, 203, 422, 455, 203, 398, 416, 398, 422, 437, 203, 422, 413, 203, 470, 440, 458, 203, 413, 440, 449, 416, 440, 455, 203, 398, 401, 440, 458, 455, 203, 422, 455, 245, 203, 203, 326, 203, 428, 437, 440, 464, 203, 326, 203, 419, 398, 461, 410, 245, 203, 281, 230, 37, 37, 356, 440, 239, 203, 464, 419, 398, 455, 203, 419, 398, 443, 443, 410, 437, 410, 407, 203, 455, 419, 410, 449, 410, 296, 203, 323, 398, 461, 410, 203, 470, 440, 458, 203, 413, 422, 416, 458, 449, 410, 407, 203, 422, 455, 203, 440, 458, 455, 296, 203, 320, 449, 410, 398, 455, 206, 203, 335, 410, 455, 224, 452, 203, 434, 440, 461, 410, 203, 440, 437, 245, 37, 37, 344, 428, 203, 440, 428, 206, 206, 203, 326, 224, 431, 431, 203, 410, 467, 443, 431, 398, 422, 437, 203, 422, 455, 206, 206, 206, 206, 203, 341, 440, 203, 437, 410, 410, 407, 203, 455, 440, 203, 416, 410, 455, 203, 419, 458, 413, 413, 470, 245, 203, 203, 356, 440, 203, 455, 419, 410, 203, 413, 422, 449, 452, 455, 203, 431, 422, 437, 410, 203, 452, 419, 440, 458, 431, 407, 203, 401, 410, 203, 440, 401, 461, 422, 440, 458, 452, 203, 401, 470, 203, 437, 440, 464, 239, 203, 464, 410, 224, 449, 410, 203, 404, 449, 410, 398, 455, 422, 437, 416, 203, 398, 203, 431, 422, 452, 455, 239, 203, 398, 437, 407, 203, 404, 398, 431, 431, 422, 437, 416, 203, 422, 455, 203, 209, 401, 440, 440, 416, 398, 209, 245, 203, 37, 37, 359, 419, 410, 203, 437, 410, 467, 455, 203, 431, 422, 437, 410, 203, 422, 452, 203, 455, 419, 410, 203, 437, 410, 464, 203, 443, 398, 449, 455, 245, 203, 203, 359, 419, 410, 449, 410, 203, 422, 452, 203, 398, 203, 209, 413, 440, 449, 209, 203, 227, 422, 437, 203, 431, 440, 464, 410, 449, 203, 404, 398, 452, 410, 239, 203, 455, 419, 398, 455, 224, 452, 203, 422, 434, 443, 440, 449, 455, 398, 437, 455, 230, 245, 203, 203, 326, 311, 335, 314, 203, 404, 440, 431, 440, 449, 452, 203, 422, 455, 203, 440, 449, 398, 437, 416, 410, 203, 401, 410, 404, 398, 458, 452, 410, 203, 422, 455, 224, 452, 203, 398, 203, 452, 443, 410, 404, 422, 398, 431, 203, 428, 410, 470, 464, 440, 449, 407, 203, 455, 419, 398, 455, 203, 455, 410, 431, 431, 452, 203, 347, 470, 455, 419, 440, 437, 203, 455, 440, 203, 407, 440, 203, 398, 203, 431, 440, 440, 443, 245, 203, 203, 341, 440, 464, 203, 464, 419, 398, 455, 203, 422, 452, 203, 455, 419, 422, 452, 203, 209, 473, 458, 428, 422, 437, 422, 209, 203, 398, 431, 431, 203, 440, 413, 203, 398, 203, 452, 458, 407, 407, 410, 437, 296, 203, 203, 302, 437, 407, 203, 455, 419, 422, 452, 203, 464, 419, 440, 431, 410, 203, 209, 422, 437, 209, 203, 401, 458, 452, 422, 437, 410, 452, 452, 296, 203, 37, 37, 359, 419, 410, 203, 464, 398, 470, 203, 455, 440, 203, 431, 440, 440, 443, 203, 455, 419, 449, 440, 458, 416, 419, 203, 398, 203, 431, 422, 452, 455, 203, 422, 437, 203, 347, 470, 455, 419, 440, 437, 203, 422, 452, 203, 455, 440, 203, 455, 410, 431, 431, 203, 443, 470, 455, 419, 440, 437, 203, 464, 419, 422, 404, 419, 203, 431, 422, 452, 455, 203, 470, 440, 458, 203, 464, 398, 437, 455, 203, 455, 440, 203, 431, 440, 440, 443, 203, 455, 419, 440, 458, 416, 419, 239, 203, 398, 437, 407, 203, 398, 431, 452, 440, 203, 455, 410, 431, 431, 203, 443, 470, 455, 419, 440, 437, 203, 422, 437, 455, 440, 203, 464, 419, 422, 404, 419, 203, 461, 398, 449, 422, 398, 401, 431, 410, 203, 470, 440, 458, 203, 464, 398, 437, 455, 203, 455, 440, 203, 443, 458, 455, 203, 410, 398, 404, 419, 203, 422, 437, 407, 422, 461, 422, 407, 458, 398, 431, 203, 431, 422, 452, 455, 203, 422, 455, 410, 434, 203, 464, 419, 422, 431, 410, 203, 431, 440, 440, 443, 422, 437, 416, 203, 440, 461, 410, 449, 203, 422, 455, 245, 203, 203, 326, 437, 203, 455, 419, 422, 452, 203, 404, 398, 452, 410, 239, 203, 464, 410, 224, 449, 410, 203, 431, 440, 440, 443, 422, 437, 416, 203, 455, 419, 440, 458, 416, 419, 203, 455, 419, 410, 203, 431, 422, 452, 455, 203, 401, 440, 440, 416, 398, 239, 203, 398, 437, 407, 203, 464, 410, 239, 203, 398, 449, 401, 422, 455, 449, 398, 449, 422, 431, 470, 239, 203, 398, 452, 428, 410, 407, 203, 347, 470, 455, 419, 440, 437, 203, 455, 440, 203, 443, 431, 398, 404, 410, 203, 410, 398, 404, 419, 203, 431, 440, 440, 443, 203, 422, 455, 410, 434, 203, 422, 437, 203, 398, 203, 461, 398, 449, 422, 398, 401, 431, 410, 203, 437, 398, 434, 410, 407, 203, 209, 473, 458, 428, 422, 437, 422, 209, 245, 203, 203, 368, 410, 203, 404, 440, 458, 431, 407, 203, 419, 398, 461, 410, 203, 404, 398, 431, 431, 410, 407, 203, 422, 455, 203, 398, 437, 470, 455, 419, 422, 437, 416, 203, 410, 431, 452, 410, 245, 203, 203, 374, 410, 452, 239, 203, 410, 461, 410, 437, 203, 209, 353, 398, 473, 401, 398, 437, 209, 245, 37, 37, 37, 37, 344, 332, 203, 344, 332, 203, 344, 332, 206, 206, 203, 374, 440, 458, 203, 416, 440, 455, 203, 422, 455, 245, 245, 245, 203, 281, 230]

Hint: to get the character that each number stands for, do this:

  1. if the number is greater than 200, subtract 100 from it, otherwise, leave it alone.
  2. subtract seven from that number, then divide the result by 3.
  3. To get the character, pass the final number through the function chr(), like this:
    decoded_char = chr(final_number)
  4. You can print the characters all on the same line by having at the start of the program:
    import sys
    And later in the code, when you want to print the character:
    sys.stdout.write(decoded_char)

    (Don't worry about what this is or how it works, you'll find out later...)
Do that for every number in the list. Enjoy! :)



No comments:

Post a Comment