Python Advice / Tips please

Soldato
Joined
19 Mar 2012
Posts
6,586
I've started to learn python this morning, I've decided on 2.7 at the moment as the vast majority of stuff out there is written in that and i learn best by unpicking other peoples code to understand it and then be able to write my own.

First question is, generally, am i right to do that? Or bearing in mind i see this as a step to learning things like Java and some version of C, should i just learn python 3? My only experience in programming is VBA (and Basic on the Acorn Electron!)

I'm using http://codingbat.com/python to learn, as above i learn best by being set a task and then working out how to do it and this seems to have got me off to a flying start, are there any similar sites, as codingbat seems limited in how far it goes, i've completed 1/4 of the tasks in an hour or so.

And then a specific question regarding writing the code.

The example answers always do a check to make sure that a string is at least as long as any substring you try and extract from it, which i can see the logic of doing, but there doesn't appear to be a need to do as python seems to deal with it ok.

For example....

Given a string, return the count of the number of times that a substring length 2 appears in the string and also as the last 2 chars of the string, so "hixxxhi" yields 1 (we won't count the end substring).

last2('hixxhi') → 1
last2('xaxxaxaxx') → 1
last2('axxxaaxx') → 2

I wrote

Code:
def last2(str):
 result = 0
 wsfind = str[-2:]
 for i in range(len(str)-1):
   if wsfind == str[i-1:i+1]:
    result = result +1
 return result

Which works fine, if a string is less than 2 characters, the str[:::] function seems to return a 0 if it gets an error.

The example answer, however, had a check at the start to manually return 0 if the string length was less than 2.

Code:
def last2(str):
  # Screen out too-short string case.
  if len(str) < 2:
    return 0
  
  # last 2 chars, can be written as str[-2:]
  last2 = str[len(str)-2:]
  count = 0
  
  # Check each substring length 2 starting at i
  for i in range(len(str)-2):
    sub = str[i:i+2]
    if sub == last2:
      count = count + 1

  return count

Why? I know in something like this it makes no odds, but simplistically, those couple of lines aren't needed and just add overhead to the code? Or is it a case of what I've done in allowing python to catch and correct the error is bad practice?

Also, why do they assign the derived substring to the variable "sub" before checking it against the last 2 characters of the string? Surely as each time the code loops that variable is re-assigned and then only used once, it's more efficient to do it my way and not bother assigning the variable?

Thanks in advance..
 
Soldato
OP
Joined
19 Mar 2012
Posts
6,586
Cracking stuff thanks, mate, I'm flying through it now, it can seem a bit slow when you know about assigning variables and boolean stuff but in actual fact it's really hammering home the syntax changes coming from VBA.

edit:I hadn't seen the other replies, they've given me food for thought! D.P, do you have any suggestions for how to get started on C or C++?

I wanted to learn a "simple" language first to get some good working practises, my entire knowledge of VBA is self taught and very haphazard, I'm sure i do things "incorrectly" even though they work.
 
Last edited:
Soldato
OP
Joined
19 Mar 2012
Posts
6,586
Would you say that I'm best to use the Koenig book to get started and then learn the newer stuff? People online talk about versions of C++ and that "Accelerated C++" is based on an old version? But then the book does get good reviews.
 
Soldato
OP
Joined
19 Mar 2012
Posts
6,586
Cool thanks.

I've got an idea about stuff, I seem to have the brain for programming.

In VBA I've learnt to use For Loops, array variables, call other procedures, build Excel based applications using Forms, etc so I'm not completely fresh to a lot of the concepts.

I even remember, vividly. sitting at a mates house when i was about 10/11 learning about Booleans, AND, OR, NOT, etc and "getting it".
 
Soldato
OP
Joined
19 Mar 2012
Posts
6,586
Cheers again mate.

Messing on with Python I'd managed the pigeon English translator no problem at all within a couple of hours of starting to install Python.

I've ordered the Accelerated book and one of the others, the third I got a Kindle sample to have a little read.

I'm pretty committed to this, it's something I've always wanted to do properly but never managed to. Upcoming redundancy and having a child means I should have time to get cracking with C++.

Any exercises or more detail on the sort of thing you get your interns to do that you can share would be great.
 
Last edited:
Soldato
OP
Joined
19 Mar 2012
Posts
6,586
So the book arrived this morning, got cracking with it, read the first 3 chapters and then knocked this up without reference to the book or internet.

It calculates the sum of all factors of 3 or 5 that are less than 1000.

I can already see things i want to do with it, such as take the 2 numbers in as an input and then work from there, adding in an array and sorting it to make sure that they are in the right order for the code to still work.

I'd also like to build it so that no matter how many numbers you enter it works out the sum of the factors, add something in there to avoid any checking of the second number if it's a factor of the other, etc, etc.

But anyway, the question i had is....i deliberately did it this way to avoid looping through every number from 1-999, but i'm not sure if this way is more efficient or if another way would be. is there a way to test 2 bits of code that do the same thing to see which is more efficient? Or is that something that comes with experience and a bit more learning?

Code:
#include <iostream>

int main()	{

	//mul1 and mul2 must be entered in ascending order
	int mul1 = 3;
	int mul2 = 5;
	int lim = 1000;
	int count = 1;
	int wsum = 0;

	while ((count * mul1) < lim) {
		wsum += (count * mul1);

		if ((count * mul2) % mul1 != 0 && (count * mul2) < lim) {
			wsum += (count * mul2);
		}
		++count;
	}
	std::cout << wsum << std::endl;
	return 0;
}

edit:

In an attempt to further reduce the looping, which I'm assuming takes processing power that's not needed, I've done most of the work using maths up front and then used a loop to remove the duplicate numbers.

Code:
#include <iostream>

using std::cout;	using std::endl;
using std::cin;

int main()	{
	
	int mul1 = 3;
	int mul2 = 5;
	int count = 1;
	int wsum = 0;
	

	cout << "Enter Limit : ";
	int lim;
	cin >> lim;
	--lim;

	int mul1d = lim / mul1;
	cout << mul1d << endl;
	
	if (mul1d % 2 == 0)	
		wsum = mul1d / 2 * (mul1d * mul1 + mul1);
	
	else{
		wsum = mul1d / 2 * (mul1d*mul1 + 2 * mul1) + mul1;
	}

	int mul2d = lim / mul2;
	if (mul2d % 2 == 0)
		wsum += mul2d / 2 * (mul2d * mul2 + mul2);

	else{
		wsum += mul2d / 2 * (mul2d*mul2 + 2 * mul2) + mul2;
	}

	
	while (count * mul1 * mul2 < lim) {

		wsum -= count * mul1 * mul2;
		++count;
	}

	
	cout << wsum << endl;
	
	return 0;
}

or...

Code:
#include <iostream>

using std::cout;	using std::endl;
using std::cin;


int sumtolim(int mul, int lim)	{
	
	int wsum2 = 0;

	int muld = lim / mul;

	if (muld % 2 == 0)
		wsum2 = muld / 2 * (muld * mul + mul);
	else
		wsum2 = muld / 2 * (muld*mul + 2 * mul) + mul;

	return wsum2;
}

int main()	{

	int mul1 = 3;
	int mul2 = 5;
	int wsum = 0;

	cout << "Enter Limit : ";
	int lim;
	cin >> lim;
	--lim;
	int mul1d = lim / mul1;

	wsum += sumtolim(mul1, lim);
	wsum += sumtolim(mul2, lim);
	wsum -= sumtolim(mul1 * mul2, lim);

	cout << wsum << endl;

	return 0;
}
 
Last edited:
Back
Top Bottom