• Hey, guest user. Hope you're enjoying NeoGAF! Have you considered registering for an account? Come join us and add your take to the daily discourse.

Programming |OT| C is better than C++! No, C++ is better than C

JesseZao

Member
My problem with most programming streams is that a lot of them just waste their time on random shit or just staring at the screen or going to other websites. And the ones that are a bit more famous, just interact with the chat way too much.

Casey Muratori is about one of the few examples of what I want. He is so focused on his tasks and doesn't get distracted during his streams. And then he has an extensive Q&A session at the end so there is an interactivity segment with the viewers as well.

Is that the Handmade Hero guy? He codes incredibly fast. Quite the marvel.
 

Slavik81

Member
Wait... why? The last thing I'd ever want is a peanut gallery watching me write code.

Clicked a random stream, and it was a guy scrolling through a Stack Overflow thread with a perplexed look on his face, so at least it's capturing the real coding experience.
teZGSGT.png
This is amazing.
 

Rur0ni

Member
Anyone here familiar with powershell? I've had a strange instance where this line:

$users = (Get-ChildItem C:\Users).FullName

Worked on several PCs but not one. I've since replaced it with:

$users = (Get-ChildItem C:\Users) | ForEach-Object { $_.FullName }

Which seems to work, but I am flabbergasted why the initial code would work sometimes instead of all the time or not at all..
Different versions of PowerShell behave somewhat differently, and may differ a bit on a different/newer OS (such as available cmdlets).

I would expect the latter one to work, and I would have likely never tried the former.

What I would have done:

Code:
Get-ChildItem -Path C:\Users | Select-Object -ExpandProperty FullName
 

Cindres

Vied for a tag related to cocks, so here it is.
Nice! Really glad to know my post was helpful. I need to look into it myself.

Ultimately it wasn't as hard as I'd made it. I'd just read on their setup pages that implied Java 8 wasn't supported on Tomcat there and I needed Java 8 support due to features of it being used in my project so I had no wiggle room and went down a couple of dead ends. In the end I just used a Wildfly server and it worked no problem, kinda wondering if I just used a tomcat and deployed my WAR it would work but it doesn't really make a lot of difference to me if it's using Tomcat, JBoss, Wildfly anyway.
 

Haly

One day I realized that sadness is just another word for not enough coffee.
I stumbled upon this: http://stackoverflow.com/questions/...in-implementing-binary-search/6393352#6393352

Code:
PROCEDURE BinarySearch (A         : anArray,
                        Size      : anArraySize,
                        Key       : INTEGER,
                        VAR Found : BOOLEAN;
                        VAR Index : anArrayIndex);
Var Low, High : anArrayIndex;
BEGIN         
   LOW := 1;
   High := Size;

   REPEAT
      Index := (Low + High) DIV 2;
      If Key < A[Index]
         THEN High := Index - 1
         ELSE Low  := Index + 1
   UNTIL (Low > High) OR (Key = A[Index]);

   FOUND := (Low <= High)
END;

And I have a question for people who know Pascal. Supposedly the Procedure he gives exhibits the following errors as far as implementation goes:

Error 3: It gives a wrong answer. Whenever the final iteration of the loop starts with Low=High (e.g. when Size=1), it sets Found:=True, even if Key is not in the array.

Error 4: It causes an error whenever Key is less than the smallest element of the array. (After Index becomes 1, it sets High to 0, etc.; causes an out-of-bounds error.)

Error 5: It causes an error whenever Key is greater than the largest element of the array. (After Index becomes Size, it sets Low to Size+1 etc.; causes an out-of-bounds error.)

And... I'm not seeing the error. For 3, I don't understand how the loop can possibly exit on Low == High. There's no alternative terminating condition to (Low > High) or (Key = A[Index]). If Found is set after the loop terminates without finding the Key, then Low will always > High. Is Found somehow set in parallel to the loop exiting?

For 4 and 5, I get that the offending line is:
Code:
Index := (Low + High) DIV 2;
But I don't understand how the loop can ever reach a point where it evaluates to < 1 or > Size. REPEAT-UNTIL is a posttest loop is it not? I can see the error if it's a prettest, so Low == High == 1 will allow the loop to execute once more and access an out-of-bounds index, but I'm unsure how that case slip through a posttest.

EDIT: Okay, so. Error 3 is written incorrectly. The procedure will give a false negative, not a false positive. And Pascal has invariants on index types apparently, so Low or High ever being out of bounds will set off an error.
 
Let me know if you do. It's been on my backburner for a while but I'm starting to dig into it more and more. I don't have any projects yet, probably was just going to start off implementing red black trees, hashmaps, and some sieves.

Gonna try to do some Rust streaming now. Bear with me, I've not done this before. I'll probably be doing a re-implementation of something I did earlier (travelling salesman problem) which broke as a result of the various changes before the language became stable.

https://www.livecoding.tv/gyrosofwar/

edit: Okay, OBS on Linux still seems to be having some issues. It kind of stops working after I've streamed for a couple of minutes.

Gonna try it on Twitch in the meanwhile..
http://www.twitch.tv/klo8/
 

Mr.Mike

Member
C/C++ is primarily used in software where you are very concerned about performance, memory use, and/or energy consumption. Today those are fields like high-throughput computing, cloud / service backends, embedded devices / Internet of Things, high-end games, and system software (OS, hypervisor, drivers, compilers / libraries, etc). One thing that may not instantly be apparent from this list is that these are all areas where you will benefit a lot from having systems knowledge; that is, also having a good understanding of hardware architecture, operating systems, and networking principles. So my specific advice about C++ is to think about whether you are interested in becoming a systems person. If you are, focus your breadth on understanding systems concepts like memory architecture, threading, and kernel networking. If you become a systems programmer, those core skills carry over even if C++ starts getting replaced in those areas by something like D, Rust, or Go. The same is true of general software engineering knowledge like data structures, algorithms, and design patterns.

I did very much enjoy my computer architecture courses, mostly because it demystified these "computer" things. So now I have a basic understanding of how computers work at that lowest layer. I've also done a systems programming course where we did a bunch of stuff IPC and system call stuff, that I very much enjoyed.

I think a good next step might be to learn how the kernel (and device drivers and such) works, since that's the main thing that's still kind of black magic to me. Can anyone recommend any good books on kernels?

I'm also thinking that setting up a "Linux From Scratch" install might be a great way to learn a lot about operating systems, perhaps I'll do that in the break between my summer course and the start of the semester.
 
I think a good next step might be to learn how the kernel (and device drivers and such) works, since that's the main thing that's still kind of black magic to me. Can anyone recommend any good books on kernels?

LDD3 is one of the big ones (if not the one), and is completely free online!
 

arit

Member
LDD3 is one of the big ones (if not the one), and is completely free online!

Sadly the 4th isn't out yet (wasn't it supposed to come out last year?) and some things might not work with current(3.x+?) kernels/have to be done different. But yeah, to get a basic understanding it is still all right, even though it is missing the glory that is device trees.

Besides that there is the kernel documentation within the kernel source tree which may or may not be up to date but should touch topics beyond the drivers. And I suppose Tanenbaum's for even more general information.
 

Nesotenso

Member
i have a question about file input/output in python and the read method.

writing a function to read one file and write to another

Code:
def sed (input_file, output_file):
    f1 = open(input_file, 'r')
    f2 = open(output_file, 'w')
    text = f1.read()
    print text
    f2.write(text)
    fl.close()
    f2.close()
    return

this gives me the following error.
NameError: global name 'fl' is not defined

but if I modify the function like so
Code:
def sed (input_file, output_file):
    f1 = open(input_file, 'r')
    f2 = open(output_file, 'w')
    text = f1.read()
    print text
    f2.write(text)
    if text =="":
        fl.close()
        f2.close()
    return

I no longer get the error. so why do I get the name error when I try to close f1 in the first case?
 
i have a question about file input/output in python and the read method.

writing a function to read one file and write to another

Code:
def sed (input_file, output_file):
    f1 = open(input_file, 'r')
    f2 = open(output_file, 'w')
    text = f1.read()
    print text
    f2.write(text)
    fl.close()
    f2.close()
    return

this gives me the following error.
NameError: global name 'fl' is not defined

but if I modify the function like so
Code:
def sed (input_file, output_file):
    f1 = open(input_file, 'r')
    f2 = open(output_file, 'w')
    text = f1.read()
    print text
    f2.write(text)
    if text =="":
        fl.close()
        f2.close()
    return

I no longer get the error. so why do I get the name error when I try to close f1 in the first case?
You got a typo. The problem is you're calling close on 'fl' (f - lower case L) not 'f1' (f - one).

My guess is f1 is empty. fl.close never gets called since you never go into the if which means you never encounter the name issue.
 

Nesotenso

Member
You got a typo. The problem is you're calling close on 'fl' (f - lower case L) not 'f1' (f - one).

My guess is f1 is empty. fl.close never gets called since you never go into the if which means you never encounter the name issue.

well now if feel stupid. i thought it was something to do with how the read method works. Thanks.
 

0xCA2

Member
Hey guys, check out my first site. Made in PHP, MySQL, JS and Foundation. I did this all in procedural PHP so I can have a good enough idea of what goes into making a website that I won't be confused by frameworks like Ruby on Rails (learning that next). Registration not open because I haven't set up emails yet (and haven't finished a few features).

Let me know if there are any bugs :).
 

maeh2k

Member
There is an android developemnt course kickstarter here if anyones interested -

https://www.kickstarter.com/project...-m-developer-course-with-andro?ref=nav_search

Becase it has gone over the inital goal you will get 2 other courses for free.

Not sure why anyone would be interested. Why kickstart something, when those kinds of courses already exist (and tons of tutorials and other resources) and are ready for purchase or even free?

Google themselves have free courses on udacity:
- https://www.udacity.com/course/android-development-for-beginners--ud837
- https://www.udacity.com/course/developing-android-apps--ud853
 
So this is perhaps more math than programming related, but I'm slowly going through Project Euler and I've just done problem 5. My code works, but it is very fucking slow. I'm not really sure what route I could take to improve the speed.

Code:
"""2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"""

count = 0 
a = 2520
while count < 21: 
	for i in range(2,21):
		if a % i == 0:
			count += 1
		else:
			count = 0
			a += 20

print a


I start at 2520 because I simply reasoned that the number would have to be greater than in the (1-10's) case. Similarly I increment a by 20 because I know it has to be an even number, and that it will need to be divisible by 20. I think I could probably increase the increment but I'm not sure whats the highest I could increment it. And I also don't think I chose the best starting point either.

I do get an answer though. It just takes a bit of time. About 6-7 Mississippi seconds.

edit: Googling around I found a small hint and changed the increment to 2520. With that the thing gets the right answer in like under a second. But can someone explain this to me more mathematically because I was honestly just guessing with my starting point and increment to begin with.
 

JesseZao

Member
I've taken a break from project euler, but I should start going through it again. I think I left off on problrem 17 or 18. Really fun to post your code and then compare it with others (and then groan at those "cheaters" using J or other math/data sci languages).
 
I've taken a break from project euler, but I should start going through it again. I think I left off on problrem 17 or 18. Really fun to post your code and then compare it with others (and then groan at those "cheaters" using J or other math/data sci languages).

Yeah it is actually pretty fun to see what others have posted. Comparing code and going "holy fuck, this guy's solution is genius how did I not see that" is really great.
 

JesseZao

Member
Yeah it is actually pretty fun to see what others have posted. Comparing code and going "holy fuck, this guy's solution is genius how did I not see that" is really great.

I checked if I posted my problem 5 solution, but I didn't. Might have it lying around on my laptop. I'll check later.
 

Chris R

Member
A more mathematical solution can easily be found if you work out the problem for numbers between 2 and 10 by hand.

2 is the smallest number that is evenly divisible by 1 to 2.
6 is the smallest number that is evenly divisible by 1 to 3.
12 is the smallest number that is evenly divisible by 1 to 4.

hint:
Factor each number and it should be obvious
 

JesseZao

Member
A more mathematical solution can easily be found if you work out the problem for numbers between 2 and 10 by hand.

2 is the smallest number that is evenly divisible by 1 to 2.
6 is the smallest number that is evenly divisible by 1 to 3.
12 is the smallest number that is evenly divisible by 1 to 4.

hint:
Factor each number and it should be obvious

Yeah. I think I just reduced the factors by hand on paper. I tried to find my posts for other problems and there seems to be huge gaps in the answer threads. They must auto-delete some of them.
 

Chris R

Member
I should go back and do more of the problems on ProjectEuler.

Only 7 to go to get all of 1-100 done I think and almost 150 total problems solved.
 

Aureon

Please do not let me serve on a jury. I am actually a crazy person.
So, i'm at that stage where i should be sending resumes out.. and..
It's me or the requirements most companies put up, even for junior positions, are completely insane?
3y+ in every single part of their stack? How does that even happen?
 

Wynnebeck

Banned
Hey guys. Final Intro to Programming program and even though the teacher was kind enough to make a shell for us, I'm still stuck. This is as far as I got:

#include <iostream>
#include <iomanip>
#include <cmath>

// Shell for Carpet Cost program

// prototypes

void getdata (int & length, int & width, float & costpersqfoot);

// read the length and width of the room and the cost per
// square foot

float InstalledPrice(int length, int width, float costpersqfoot);

// calculate the installed price taking into account the labor
// cost. The labor cost is a symbolic constant

float totalprice(float installation);

// finds the total cost using the installed price and the tax rate
// taxrate is also a symbolic constant

void printdata(int length,int width, float price);

// prints the length, width, and total cost for each data set

const float LABOR_COST = 0.35; // $0.35 per square foot
const float TAX_RATE = 0.05;

int main ()
{
// declare length and width of type int

int length,width;

// declare installation cost and total cost of type float.

int installCost, totalCost;


// Read count for the loop

// for loop based on the count
// call get_data
// find installation cost
// find total cost
// Write the result with the printdata procedure
// endfor

system ("pause");
// return from main
} // end of main

// define functions here, two void and two regular

Any help? It's due by 11:59pm.
 

poweld

Member
Hey guys. Final Intro to Programming program and even though the teacher was kind enough to make a shell for us, I'm still stuck. This is as far as I got:



Any help? It's due by 11:59pm.

You're going to need to take a crack at it before we can help you. If you have more specific questions feel free to ask. Your teacher has laid out exactly what they want you to do, conceptually.
 

poweld

Member
Could anyone give me a tip on how to do project Euler problem 27?

I'm on my phone so can't really post my current code sorry. I'm stumped beyond just going brute force which takes too long.

https://projecteuler.net/problem=27

I'm thinking something like this (pseudocode)
Code:
class Coefficients {
  int a;
  int b;
}

class Quadratic {
  Coefficients c;
  int n;

  boolean isPrime() {
    /* Check for prime, sieve of eratosthenes? */
  }
}

Map<Coefficients, Integer> coefficientsToNumPrimes = Maps.empty();

for (int a = -999; a <= 999; a++) {
  for (int b = -999; b <= 999; b++) {
    Coefficients c = new Coefficients(a, b);
    int numPrimes = 0;
    for (int n = 0; true; n++) {
      Quadratic d = new Quadratic(c, n);
      if (d.isPrime()) {
        numPrimes++;
      else {
        coefficientsToNumPrimes(c) = numPrimes;
        break;
      }
    }
  }
}

Then just find the entry in the map with the largest number of primes and multiply the coefficients.
 

Wynnebeck

Banned
You're going to need to take a crack at it before we can help you. If you have more specific questions feel free to ask. Your teacher has laid out exactly what they want you to do, conceptually.

Ok then, for the lines that say:

// Read count for the loop

// for loop based on the count

Is this saying to set up a for loop setting the number of loops in the parameters or what?
 

vypek

Member
So, i'm at that stage where i should be sending resumes out.. and..
It's me or the requirements most companies put up, even for junior positions, are completely insane?
3y+ in every single part of their stack? How does that even happen?

I've seen quite a few entry level positions ask for multiple years in areas and I was confused on that. I assume they expect people to have used those specific tools in a non-professional area. Actually ended up interviewing for a spot like that one time through some weird circumstances.
 

poweld

Member
Ok then, for the lines that say:



Is this saying to set up a for loop setting the number of loops in the parameters or what?

It's saying that you need to read in a number from the user. This number should be used to make your for loop execute that many times.

For example, if I had read an int "loopCount" from the user, and 10 was entered, the following loop:
Code:
for (int i = 0; i < loopCount; i++) {
  /* do something */
}

would execute 10 times.
 
Is there a better way to implement the Sieve of Eratosthenes in python than the way I have below?

Code:
"""By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
What is the 10,001st prime number?"""

def sieve(n):
	initial = range(2,(n+1))
	for i in initial:
		for x in initial:
			if x % i == 0 and x != i:
				initial.remove(x) 
	return initial 

print sieve(110000)[10000]

I've read online that xrange is faster than range, but xrange doesn't have remove, and my guess is that xrange doesn't create a list while range does. I suppose it might be faster to iterate over all the numbers using xrange and then append the primes that show up to a list, instead of creating a list and then removing the non-primes?
 
Is that even safe? For-iterating over a collection which is modified in the loop?

btw, any reason you don't use python 3?

What do you mean by safe in this context?

And I do have Python 3 on my computer, but I'm mostly doing stuff with 2.7.9 right now and a lot of stuff still uses it. So I'm not in a rush to switch. I'll probably make the switch when I start doing stuff with pygame.
 
What do you mean by safe in this context?

And I do have Python 3 on my computer, but I'm mostly doing stuff with 2.7.9 right now and a lot of stuff still uses it. So I'm not in a rush to switch. I'll probably make the switch when I start doing stuff with pygame.

I'm coming from C++/Java/etc so Python may be doing these things automatically, but generally you can't delete elements in a list that you're currently iterating over.

For example, let's assume we have an array list. It has the values [0, 1, 2] in it. I want to loop through it and print all the values, and if the value is 0, remove it from the list.

So we do:
Code:
for (int i=0; i<list.length(); i++) {
    print list[i];
    if (list[i] == 0)
        list.delete[i];
}

Here's what's going to happen:
  1. i = 0, list[0] = 0
  2. We print the 0.
  3. We remove the 0. The list is now [1, 2].
  4. i = 1; list[1] = 2 (list[1] was previously 1, but it changed when we deleted list[0])
  5. Print 2
  6. We're at the end of the list. So we're done.
Expected output: 0, 1, 2.
Actual output: 0, 2.

But it gets worse. What if we don't want to recalculate the length of the list every loop (nevermind that the list would usually store that as a variable if it's any decent implementation)? Then we do:
Code:
int length = list.length();
for (int i=0; i<length; i++) {
We avoided that pesky function call, aren't we smart! Except uh-oh, that variable is going to be inaccurate since the length of the list changes in the loop. This means we'll access element list[2], which doesn't exist. That's bad. Really bad.

But you didn't do a for-loop with an index like that, you used an iterator, so it shouldn't be a problem! ... except an iterator is just a more convenient way to express that (in the context of an array list, a linked list iterator doesn't use indices), so it's actually doing that under the hood.

So what do we do if we want to modify a container as we loop over it? Well, we'll have to use the iterator's special remove function, which updates it's internal index and length variables (if it's using a length variable) so that it's accurate and we can keep looping over the container without getting unexpected output or breaking things.

Now, again, I don't know Python so I don't know if it magically fixes things, but from reading your code it seems like it would be a problem, unless Python lists keep track of all their iterators and updates them whenever the container is modified (which seems like quite a lot of extra overhead).
 

wolfmat

Confirmed Asshole
I suppose it might be faster to iterate over all the numbers using xrange and then append the primes that show up to a list, instead of creating a list and then removing the non-primes?
Removing (popping) is cheaper than appending because to append, you have to put data somewhere, while popping just means you drop a reference (and return it of course, but that's irrelevant here). However, you cannot expect a list iteration result to be sane if you pop something in the middle and do not consider this later with an offset (the list has changed after all; something's gone). But the popping will always be cheaper.

Edit: The offset is the common thing to do to address concerns like "doesn't iteration break if I change the list while iterating over it?"

Know that the for-loop setup is immutable only if you're NOT using a cursor. So if you do
Code:
a=[1,2,3,4]
for i in a:
    print('p',a.pop())
    print(i)
Then the list changes during iteration, so you'll get
p,4
1
p,3
2
as the output, and are left scratching your head.
But if you do
Code:
a=[1,2,3,4]
for i in range(0,len(a)):
    print('p',a.pop())
    print(i)
Then the setup is immutable (a list is created just for iterating, and it is not modified although the length of a changes). So you'll get
('p', 4)
0
('p', 3)
1
('p', 2)
2
('p', 1)
3

So that's something to keep in mind: Is my for-loop setup immutable or not?
 
Removing (popping) is cheaper than appending because to append, you have to put data somewhere, while popping just means you drop a reference (and return it of course, but that's irrelevant here). However, you cannot expect a list iteration result to be sane if you pop something in the middle and do not consider this later with an offset (the list has changed after all; something's gone). But the popping will always be cheaper.

Depends on how the list is implemented. Removing things in the middle of an array list is probably a lot slower that populating a new list, just appending things at the end. If it's a linked list, though, removing is O(1).
 
I'm coming from C++/Java/etc so Python may be doing these things automatically, but generally you can't delete elements in a list that you're currently iterating over.

However my code for certain works. At the very least for finding the 10,0001st prime number. And the 6th prime number. Python allows this*. Downside is it takes a significant chunk of time. Though I've looked up other answers at this point and found a better application of the sieve

*Unless by "can't" and "unsafe" you guys more mean "shouldn't because outside this problem things might get fucked."

Removing (popping) is cheaper than appending because to append, you have to put data somewhere, while popping just means you drop a reference (and return it of course, but that's irrelevant here). However, you cannot expect a list iteration result to be sane if you pop something in the middle and do not consider this later with an offset (the list has changed after all; something's gone). But the popping will always be cheaper.

Edit: The offset is the common thing to do to address concerns like "doesn't iteration break if I change the list while iterating over it?"

Know that the for-loop setup is immutable only if you're NOT using a cursor. So if you do
Code:
a=[1,2,3,4]
for i in a:
    print('p',a.pop())
    print(i)
Then the list changes during iteration, so you'll get
p,4
1
p,3
2
as the output, and are left scratching your head.
But if you do
Code:
a=[1,2,3,4]
for i in range(0,len(a)):
    print('p',a.pop())
    print(i)
Then the setup is immutable (a list is created just for iterating, and it is not modified although the length of a changes). So you'll get
('p', 4)
0
('p', 3)
1
('p', 2)
2
('p', 1)
3

So that's something to keep in mind: Is my for-loop setup immutable or not?

huh interesting. I'll keep this in mind, thanks.
 

wolfmat

Confirmed Asshole
Depends on how the list is implemented. Removing things in the middle of an array list is probably a lot slower that populating a new list, just appending things at the end. If it's a linked list, though, removing is O(1).

Oh yes, I was of course just referring to pop(), which drops the last element. pop(0) is hardly performant here.

I guess I read it wrong because he surely has to pop somewhere inside the array.

Anyway, "initial.remove(x)" is even worse than popping because the item has to be found, which is more than rebuilding the list.

I think one should either trick one's way to performance with dictionaries (O(1) everywhere), or append to a result list.
 
Anyway, "initial.remove(x)" is even worse than popping because the item has to be found, which is more than rebuilding the list.

I think one should either trick one's way to performance with dictionaries (O(1) everywhere), or append to a result list.

Ok so I was heading in the right direction when I said I thought appending to an empty list in this case would be faster than .remove() from a huuuuuuge list.

I may also try doing this with dictionaries as you suggest, since I've barely ever used dictionaries.
 

wolfmat

Confirmed Asshole
Ok so I was heading in the right direction when I said I thought appending to an empty list in this case would be faster than .remove() from a huuuuuuge list.

I may also try doing this with dictionaries as you suggest, since I've barely ever used dictionaries.

Yeah we've boosted performance like crazy in a product by just NOT doing things like
Code:
if 149871 in some_array:
    print('yes')
and instead doing
Code:
try:
    if some_ref_dict[149871]:
        print('yes')
except KeyError:
    pass
This is only valid of course if you're actually building such a reference dict for lookups like that.
The reference dict gets value True for key 149871 before because 149871 is a number that matches some condition; in the append() scenario, you'd have appended that number to a these-numbers-match-the-condition list earlier.
This is applicable in lots of cases, and trivializes such checks.
 
I'm feeling dumb because I can't wrap my head around this syntax.

Code:
def iprimes(limit):
	is_prime = [False] * 2 + [True] * (limit - 1)
	print is_prime 
	for n in range(int(limit**0.5 +1)):
		if is_prime[n]:
			for i in range(n*n, limit+1, n):
				is_prime[i] = False
	[B]return [i for i, prime in enumerate(is_prime) if prime][/B]

I've marked the line I don't get in bold. I tried making changes to see what happens, and the only thing I got without breaking it completely is if I make it
Code:
return[i for x, prime in enumerate(is_prime) if prime]
is a list containing a few copies of limit-1. That number of copies being the number of primes within that limit.

I get that this creates a list. At first I thought it was something like [i for i, stuff you want i to be], such that [i for i, range(2,10)] would create a list of [ 2, 3...9]

However that doesn't appear to be the case since if I make that change I get an invalid syntax error. I also don't understand why doing something like "i for x, stuff" prints a list containing the correct number of primes, but with limit-1 taking place of the prime numbers.
 

Kansoku

Member
I'm not sure since I never used Phyton (this is Phyton, right?), but I believe it's [X for Y in Z]. X is a expression that will return the values of the list, in that case, the values of i. Y are the variables you're going to use to get these values, in that case i and prime are the indexes and the items of the is_prime array, respectively. Z is where you are getting the values from, and in that case it's enumerating the indexes and values of is_prime and putting them on i and prime. Since is_prime is a bool array, prime is a bool, and if it's true, i get's added to the list.
 
I'm not sure since I never used Phyton (this is Phyton, right?), but I believe it's [X for Y in Z]. X is a expression that will return the values of the list, in that case, the values of i. Y are the variables you're going to use to get these values, in that case i and prime are the indexes and the items of the is_prime array, respectively. Z is where you are getting the values from, and in that case it's enumerating the indexes and values of is_prime and putting them on i and prime. Since is_prime is a bool array, prime is a bool, and if it's true, i get's added to the list.

Yeah it is Python. Anyway I think you may be right. Thanks for the explanation. The strange thing is that Python does allow you to make lists via [x for y in z], so I don't know why this alternate syntax is being used.
 

phoenixyz

Member
Yeah it is Python. Anyway I think you may be right. Thanks for the explanation. The strange thing is that Python does allow you to make lists via [x for y in z], so I don't know why this alternate syntax is being used.

It's a conditional generator. [x for x in some_iterable if some_condition] in this case x is only added to the list if the condition is satisfied. A generator [X for Y in Z if some_condition] nets the same result as
Code:
result = []
for Y in Z:
    if some_condition:
         result.append(X)
 

peakish

Member
Yeah it is Python. Anyway I think you may be right. Thanks for the explanation. The strange thing is that Python does allow you to make lists via [x for y in z], so I don't know why this alternate syntax is being used.
In addition to the other responses I think it's good to consider the statement in detail. The statement can be deconstructed into three separate parts:

Code:
i for
i, prime in enumerate(is_prime)
if prime

The first part i for creates a list of elements i. The second part i, prime in enumerate(is_prime) is a pattern match against a generator. The third part if prime is a conditional which makes sure that the values i are added to the list only if their corresponding values prime are True.

In this context, is_prime is a list of True/False values, corresponding to whether or not the numbers 0, 1, 2, ... are or aren't primes. So:

Code:
i, prime in enumerate(is_prime)
is a generator which yields the indices i and corresponding boolean (whether or not the index is a prime) prime from the list is_prime. So the enumerate() yields (i = index, prime = True/False) pairings depending on whether the number i is or isn't a prime number. This will look like this if unrolled:

Code:
i, prime = 0, False # Binds i = 0, prime = False
i, prime = 1, False # i = 1, prime = False
i, prime = 2, True # i = 2, prime = True
...
The right hand side of this statement corresponds to each yielded element from the enumerate function (with different values for i and prime).

So, the syntax
Code:
[i for i, prime in enumerate(is_prime) if prime]
taken together creates a list of indices i of the list is_prime for which the elements are True. For example, from the list is_prime = [False (index 0), False (index 1), True (index 2), True (index 3), ...] the indices [2, 3, ...] are selected and all others are discarded.

As for the statement
Code:
[i for x, prime in enumerate(is_prime) if prime]
what happens is that the second statement unrolls like
Code:
x, prime = 0, False # x = 0, prime = False
x, prime = 1, False # x = 1, prime = False
x, prime = 2, True # x = 2, prime = True
...
This means that the third statements returns True for the same indices as above. However! Note that the three statement are not necessarily dependent on each other! Both of these are correct syntaxes:

Code:
[0 for i in [0, 1, 2, 3]] # This creates the list [0, 0, 0, 0], i is not used.
[i for i in [0, 1, 2, 3] if False] # This creates the empty list [] since the conditional is always False

So what happens in your last case? Basically, the last value that i was set to is used. This corresponds to:
Code:
i = limit - 1 # ie. 5 if limit = 6
[i for x in [0, 1, 2, 3]] # Creates [5, 5, 5, 5]

I like how these list comprehensions are implemented in Python, although they can be confusing. Especially if you want to use an if/else condition, in which case the conditional comes before the generator, ugh.
Code:
["even" if i % 2 == 0 else "odd" for i in [0, 1, 2, 3]] # Creates the list ["even", "odd", "even", "odd"]
 
Top Bottom