Discussion:
[Tutor] formatting strings
Tudor, Bogdan - tudby001
2015-05-07 18:57:30 UTC
Permalink
Hi,

This is my first time.
I am using python 3.4.3 on windows 7 64bit.

I am trying to make a binary counter that will prompt for and read a decimal number (whole number). Then display all decimal numbers starting from 1 up to and including the decimal number entered along with the binary representation of the numbers to the screen.

I expected nesting a bunch of loops over and over again would work, what I've realized is that there must be an easier way of coding this without repeating loops, I just cannot for the life of me work this out. What I'm doing at the moment is writing way to much code over and over again.

https://github.com/rks1337/binary-counting/blob/master/binary%20counting

Sorry I'm not sure how to use inline quoting on outlook online.

I will greatly appreciate any help!

Kind Regards.
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Dave Angel
2015-05-08 20:28:54 UTC
Permalink
On 05/07/2015 02:57 PM, Tudor, Bogdan - tudby001 wrote:
> Hi,
>
> This is my first time.

First time doing what? Presumably the first time on this forum. But
what is your history of using Python, or of programming in general?

> I am using python 3.4.3 on windows 7 64bit.
>
> I am trying to make a binary counter that will prompt for and read a decimal number (whole number). Then display all decimal numbers starting from 1 up to and including the decimal number entered along with the binary representation of the numbers to the screen.
>
> I expected nesting a bunch of loops over and over again would work, what I've realized is that there must be an easier way of coding this without repeating loops, I just cannot for the life of me work this out. What I'm doing at the moment is writing way to much code over and over again.
>
> https://github.com/rks1337/binary-counting/blob/master/binary%20counting
>
> Sorry I'm not sure how to use inline quoting on outlook online.
>

I can't answer for outlook, but normally you add stuff to your message
by using copy/paste. On Windows, that's Ctrl-C, Ctrl-V

I can't comment on the specifics of your code, since it's online rather
than in your message.

--
DaveA
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Danny Yoo
2015-05-09 00:11:49 UTC
Permalink
> I am trying to make a binary counter that will prompt for and read a decimal number (whole number). Then display all decimal numbers starting from 1 up to and including the decimal number entered along with the binary representation of the numbers to the screen.

You might consider writing a separate function toBinary() that takes
as input a number 'n' and returns its binary representation as a
string. You're copying and pasting, and that's a sign that you've got
a block of code that you can *reuse*. If you don't know how to write
functions, please ask!


Also, you can write a loop that goes from 1 to N by using range(). For example:

########################
for n in range(1, N+1):
print(n, 2*n)
########################

The while loop that you have does work, but the for loop here is more
idiomatic in expressing the idea of "Do the following for this
collection of values ..."

... Reading the code...


Ah. You have a fixed number of variables to capture values such as
next_num_1, binary_num_1, next_num_2, binary_num_2, and so on. But
this means you'll only be able to handle a fixed number of values,
where by "fixed", it looks like you've gone up to four. :P

As you're noticing, this approach with capturing results with a fixed
number of variables isn't going to work well when we don't know how
many times we're walking through the loop.


Do you know about lists? They allow you to hold onto a variable-sized
collection of values. For example, let's say that we want to produce
the output:

###########
1 2
2 4
3 6
4 8
5 10
...
###########

Basically, our 2-times table.


Here's how we can do this.

#########################
## pseudocode
inputs = []
outputs = []
for x in range(10):
inputs.append(x)
outputs.append(x * 2)
#########################


Then we can get at any particular input/output by indexing the list at
the same position. For example, we can print the inputs and outputs
like this:

#############################
inputs = []
outputs = []
for x in range(10):
inputs.append(x)
outputs.append(x * 2)
for (i, o) in zip(inputs, outputs):
print (i,o)
#############################

and this takes an approach similar to what you've got, but it works
because it can hold onto all the results in a variable-sized list.



But that being said, for your particular program, you might not even
need to hold onto the entire collection of inputs and outputs at once.
Can you just do something like this instead?

###########################################
for x in range(10):
doubled = x * 2
print(x, doubled)
###########################################

where we interleave computation with output within the loop itself?
This has the advantage that we don't need to hold onto anything but
the very last thing we just computed, so it reduces the number of
things we're juggling to just the range that we're walking over, the
current value that we're walking, and the output from that current
value.
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Steven D'Aprano
2015-05-09 03:12:28 UTC
Permalink
On Fri, May 08, 2015 at 05:11:49PM -0700, Danny Yoo wrote:

> Also, you can write a loop that goes from 1 to N by using range(). For example:
>
> ########################
> for n in range(1, N+1):
> print(n, 2*n)
> ########################
>
> The while loop that you have does work, but the for loop here is more
> idiomatic in expressing the idea of "Do the following for this
> collection of values ..."

Why do so many beginners turn to while loops when they want to iterate
over a fixed sequence?

I know that Learn Python The Hard Way teaches while loops first. I think
that is a terrible idea. That's like going to a cookery class where
for the first three weeks they teach you to chop vegetables with a
spoon, and only in the fourth week say "Guess what? There's an easier
way! Introducing the knife!!!!"


While-loops should be taught after for-loops. The fact that from a
computer-science theoretical perspective while-loops are more
fundamental is irrelevant. We don't teach people bitwise operators
before teaching them arithmetic. Loops are no different.



--
Steve
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Michael Welle
2015-05-09 05:18:57 UTC
Permalink
Hello,

Steven D'Aprano <***@pearwood.info> writes:

> On Fri, May 08, 2015 at 05:11:49PM -0700, Danny Yoo wrote:
>
>> Also, you can write a loop that goes from 1 to N by using range().
>> For example:
>>
>> ########################
>> for n in range(1, N+1):
>> print(n, 2*n)
>> ########################
>>
>> The while loop that you have does work, but the for loop here is more
>> idiomatic in expressing the idea of "Do the following for this
>> collection of values ..."
>
> Why do so many beginners turn to while loops when they want to iterate
> over a fixed sequence?
>
> I know that Learn Python The Hard Way teaches while loops first. I think
> that is a terrible idea. That's like going to a cookery class where
> for the first three weeks they teach you to chop vegetables with a
> spoon, and only in the fourth week say "Guess what? There's an easier
> way! Introducing the knife!!!!"
I held scripting workshops (not Python) for corporate system admins and
the for-in-loop were one of the concepts discussed in deep on the first
day in the first hour of the workshop. Usually I scribbled the other
loops on the whiteboard, just to mention them, and pointed out that they
are nice to know, but rarely needed.

Interestingly a lot of the admins had trouble on two levels: first, to
express the solution to the problem they wanted to solve in a rigid
algorithmic manner, so that it could be implemented in a programming
language in the next step. And second, to implement the solution from
the first step with their new language. The second is not difficult to
understand, because it's a new language and they are admins, not
coders.

Back to loops, in that language you can pipe objects into loops, which
is an idiom that you would use in every script again and again. The loop
acts as a drain where the objects are processed, so to speak. To my
astonishment at makes a difference to a lot of people if one or many
objects come down the pipe. A frequently asked question was, why one
would need a loop, if only one object has been put into the pipe.

Regards
hmw

--
biff4emacsen - A biff-like tool for (X)Emacs
http://www.c0t0d0s0.de/biff4emacsen/biff4emacsen.html
Flood - Your friendly network packet generator
http://www.c0t0d0s0.de/flood/flood.html

_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Steven D'Aprano
2015-05-09 03:07:02 UTC
Permalink
On Thu, May 07, 2015 at 06:57:30PM +0000, Tudor, Bogdan - tudby001 wrote:
> Hi,
>
> This is my first time.
> I am using python 3.4.3 on windows 7 64bit.
>
> I am trying to make a binary counter that will prompt for and read a
> decimal number (whole number). Then display all decimal numbers
> starting from 1 up to and including the decimal number entered along
> with the binary representation of the numbers to the screen.

Start by handling a single number:

py> def display_number(n):
... print(n, bin(n))
...
py> display_number(15)
15 0b1111

Now do a loop, displaying each number:

py> for i in range(1, 11):
... display_number(i)
...
1 0b1
2 0b10
3 0b11
4 0b100
5 0b101
6 0b110
7 0b111
8 0b1000
9 0b1001
10 0b1010



Does that help?



--
Steve
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Tudor, Bogdan - tudby001
2015-06-11 07:19:31 UTC
Permalink
Hi,

Sorry if this sends twice, I had to change subject line.
I am using python 3.4.3 on windows 7 64bit.

I'm using John M. Zelle graphics module.

Graphics module:
http://mcsp.wartburg.edu/zelle/python/graphics/graphics/graphics.html

I am trying to create user movable blocks that can only move in one direction at a time. The arrow keys are used to move left or right.
Currently while moving left, pressing the right arrow key will change the blocks direction and vice versa. I'm trying to get the block to continue moving in only one direction determined by the arrow keys, i.e. pressing right should not move the blocks right if they already moving left.

How can I fix my code to do this?

I expected adding True/False variables (moveLEFT, moveRIGHT) would allow me to disable one key press while another is in action, unfortunately has not worked.

I hope its OK that I attached files as they are long.

--> blockgame.py

import graphics
import game_functions
import time

def handleKeys(event):
global direction
global moveLEFT
global moveRIGHT
print('Key pressed', event.keysym, event.keycode)

if event.keysym == 'Left':
direction = 'Left'
moveLEFT = True
moveRIGHT = False
elif event.keysym == 'Right':
direction = 'Right'
moveLEFT = False
moveRIGHT = True

elif event.keysym == 'q':
win.close()

def game():
global direction
global square
global moveLEFT
global moveRIGHT

block = game_functions.GameBlock(WIN_WIDTH//2,
WIN_HEIGHT//2, BLOCK_SIZE,
BLOCK_SIZE, 'Red', None, None, 0)
block.draw(win)
square.append(block)
block = game_functions.GameBlock(WIN_WIDTH//2,
WIN_HEIGHT//2, BLOCK_SIZE,
BLOCK_SIZE, 'Red', None, None, 0)
block.draw(win)
square.append(block)
speed = 0.1
playing = True
while playing:

# Move squares
for k in range(len(square)-1, 0, -1):
moveX = square[k-1].getCentreX() - square[k].getCentreX()
moveY = square[k-1].getCentreY() - square[k].getCentreY()
square[k].move(moveX, moveY)

# Update pos
if moveLEFT == True and moveRIGHT == False:
square[0].move(-20, 0)
if moveRIGHT and moveLEFT == False:
square[0].move(20, 0)

time.sleep(speed)
moveLEFT = False
moveRIGHT = False

WIN_WIDTH = 500
WIN_HEIGHT = 500
BLOCK_SIZE = 20
direction = ""
square = []
win = graphics.GraphWin("Snake", WIN_WIDTH, WIN_HEIGHT)
win.setBackground("white")
win.bind_all('<Key>', handleKeys)
game()
win.mainloop()
win.getMouse()
win.close()

--> game_functions.py

import graphics

class GameBlock():
def __init__(self, dx, dy, width, height, colour, imageName, blockType, points):
self.centreX = dx
self.centreY = dy
self.width = width
self.height = height
self.colour = colour
self.imageName = imageName
self.blockType = blockType
self.points = points
self.scrollSpeed = 10
self.block = graphics.Rectangle(graphics.Point(self.centreX-self.width//2, self.centreY-self.height//2),
graphics.Point(self.centreX+self.width//2, self.centreY+self.height//2))
self.block.setFill(colour)
if not(imageName == None):
self.image = graphics.Image(graphics.Point(dx,dy), imageName)
else:
self.image = None

def getCentreX(self):
return self.centreX

def getCentreY(self):
return self.centreY

def move(self, dx, dy):
self.centreX = self.centreX + dx
self.centreY = self.centreY + dy
self.block.move(dx,dy)
if not(self.image == None):
self.image.move(dx,dy)

def draw(self, canvas):
if self.image == None:
self.block.draw(canvas)
else:
self.image.draw(canvas)

__________________________
I will greatly appreciate any help!

Kind Regards
Tudor, Bogdan - tudby001
2015-06-11 09:22:20 UTC
Permalink
Hi,

Sorry if this sends twice.
I am using python 3.4.3 on windows 7 64bit.

I'm using John M. Zelle graphics module.

Graphics module:
http://mcsp.wartburg.edu/zelle/python/graphics/graphics/graphics.html

I am trying to create user movable blocks that can only move in one direction at a time. The arrow keys are used to move left or right.
Currently while moving left, pressing the right arrow key will change the blocks direction and vice versa. I'm trying to get the block to continue moving in only one direction determined by the arrow keys, i.e. pressing right should not move the blocks right if they already moving left.

How can I fix my code to do this?

I expected adding True/False variables (moveLEFT, moveRIGHT) would allow me to disable one key press while another is in action, unfortunately has not worked.

I hope its OK that I attached files as they are long.

--> blockgame.py

import graphics
import game_functions
import time

def handleKeys(event):
global direction
global moveLEFT
global moveRIGHT
print('Key pressed', event.keysym, event.keycode)

if event.keysym == 'Left':
direction = 'Left'
moveLEFT = True
moveRIGHT = False
elif event.keysym == 'Right':
direction = 'Right'
moveLEFT = False
moveRIGHT = True

elif event.keysym == 'q':
win.close()

def game():
global direction
global square
global moveLEFT
global moveRIGHT

block = game_functions.GameBlock(WIN_WIDTH//2,
WIN_HEIGHT//2, BLOCK_SIZE,
BLOCK_SIZE, 'Red', None, None, 0)
block.draw(win)
square.append(block)
block = game_functions.GameBlock(WIN_WIDTH//2,
WIN_HEIGHT//2, BLOCK_SIZE,
BLOCK_SIZE, 'Red', None, None, 0)
block.draw(win)
square.append(block)
speed = 0.1
playing = True
while playing:

# Move squares
for k in range(len(square)-1, 0, -1):
moveX = square[k-1].getCentreX() - square[k].getCentreX()
moveY = square[k-1].getCentreY() - square[k].getCentreY()
square[k].move(moveX, moveY)

# Update pos
if moveLEFT == True and moveRIGHT == False:
square[0].move(-20, 0)
if moveRIGHT and moveLEFT == False:
square[0].move(20, 0)

time.sleep(speed)
moveLEFT = False
moveRIGHT = False

WIN_WIDTH = 500
WIN_HEIGHT = 500
BLOCK_SIZE = 20
direction = ""
square = []
win = graphics.GraphWin("Snake", WIN_WIDTH, WIN_HEIGHT)
win.setBackground("white")
win.bind_all('<Key>', handleKeys)
game()
win.mainloop()
win.getMouse()
win.close()

--> game_functions.py

import graphics

class GameBlock():
def __init__(self, dx, dy, width, height, colour, imageName, blockType, points):
self.centreX = dx
self.centreY = dy
self.width = width
self.height = height
self.colour = colour
self.imageName = imageName
self.blockType = blockType
self.points = points
self.scrollSpeed = 10
self.block = graphics.Rectangle(graphics.Point(self.centreX-self.width//2, self.centreY-self.height//2),
graphics.Point(self.centreX+self.width//2, self.centreY+self.height//2))
self.block.setFill(colour)
if not(imageName == None):
self.image = graphics.Image(graphics.Point(dx,dy), imageName)
else:
self.image = None

def getCentreX(self):
return self.centreX

def getCentreY(self):
return self.centreY

def move(self, dx, dy):
self.centreX = self.centreX + dx
self.centreY = self.centreY + dy
self.block.move(dx,dy)
if not(self.image == None):
self.image.move(dx,dy)

def draw(self, canvas):
if self.image == None:
self.block.draw(canvas)
else:
self.image.draw(canvas)

__________________________
I will greatly appreciate any help!

Kind Regards
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Alan Gauld
2015-06-11 18:01:37 UTC
Permalink
On 11/06/15 08:19, Tudor, Bogdan - tudby001 wrote:

> Sorry if this sends twice, I had to change subject line.
> I am using python 3.4.3 on windows 7 64bit.

OK, But always start a new topic with a new message. By replying to an
old post your message is now buried at the bottom of a very old thread
about formatting strings. This makes it unlikely that people will find
it easily.

> I'm using John M. Zelle graphics module.
>
> Graphics module:
> http://mcsp.wartburg.edu/zelle/python/graphics/graphics/graphics.html
>
> I am trying to create user movable blocks that can only move in one
> direction at a time. The arrow keys are used to move left or right.
> Currently while moving left, pressing the right arrow key will change
> the blocks direction and vice versa.

Do you really mean that once the block starts moving left it can *never*
be reversed? That's a very unusual request.
Normally there would either be the ability to reverse or
stop the movement.

> How can I fix my code to do this?

> def handleKeys(event):
> global direction
> global moveLEFT
> global moveRIGHT
> print('Key pressed', event.keysym, event.keycode)
>
> if event.keysym == 'Left':
> direction = 'Left'
> moveLEFT = True
> moveRIGHT = False
> elif event.keysym == 'Right':
> direction = 'Right'
> moveLEFT = False
> moveRIGHT = True

Notice that you never check whether the block is moving,
you always just set the flags, without question.

To do what you want, you need to add an if test to
first check if the flag is already set. If it's set
the wrong way you might want to think about reporting
an error message to the user?



--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Danny Yoo
2015-06-11 18:27:58 UTC
Permalink
In an event-driven game, you need to give control back to the event
loop in order for the framework to pass events to your program. Your
main function, however, doesn't do so: you've got a while loop that
monopolizes control flow:

def game():
# ... game initialization logic
while playing:
# ... loop logic
time.sleep(speed)

This gives no opportunity to process keyboard events, since the
program is stuck within the while loop.


To resolve this, you want to set up a timer which emits a "tick" event
every so often. Essentially, if you're using a Tkinter-based
framework, you're looking for the "after" method:

http://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.after-method

where your program will look something like this:

#################################
def game():
# ... game initialization logic
gameLoop();

def gameLoop():
if playing:
# ... loop logic
win.after(speed, gameLoop)
#################################


The gameLoop tells the framework to restart the game loop "after" some
time. gameLoop() then returns, and gives control back to the event
loop that was started with "win.mainloop()".
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Loading...