[Fun] An odd piece of code - or a prime example of Python's elegance

What does this code do?

field = [0] * 100
field[0] = 1
print(2)
for i, state in enumerate(field):
	if state: continue
	print(i * 2 + 1)
	field[i] = 1
	for i in range(2 * i * (i + 1), len(field), i * 2 + 1):
		field[i] = 2

Post your explanations, preferably spoiler tagged so others can have fun with this too.

Is this an elegant piece of code, or an abomination?

5 Likes

Nice title.

4 Likes

I prefer eggs to spam honestly:

# They have a lot of spam at this buffet
buffet = ['eggs'] + (['spam'] * 100)
print(2)
for plate, meal in enumerate(buffet):
    if meal == 'eggs': continue
    print(plate * 2 + 1)
    buffet[plate] = 'eggs'
    for tray in range(2 * plate * (plate + 1), len(buffet), plate * 2 + 1):
        buffet[tray] = 'eggs'

In all seriousness, this is a fun experiment in lazy iteration. Here’s an even lazier version:

field = [1] + ([0] * 100)
print(2)
for i, _ in filter(lambda x: not x[1], enumerate(field)):
    print(i * 2 + 1)
    delta = i, len(field), 2*i + 1
    field[slice(*delta)] = (1 for _ in range(*delta))

An even more ridiculous code golfed version (I abandoned the optimized i*2 * (i + 1)start index for brevity)

def prime_madness(n: int=100):
    yield 2
    for i, _ in filter(lambda x: not x[1], enumerate(f := [1]+([0]*(n-1)))):
        yield (g := i*2+1)
        f[slice(i, n, g)] = range(i, n, g)

Sure, but… what’s the code actually doing? :slight_smile:

1 Like

The only part I’m having trouble with is the 2*i*(i+1) part

Obviously this is a fun way of doing a prime sieve. I think my edited examples as I played with it should show that. The lazy iteration over the list using enumerate is a fun trick to modify the sieve in place using the index as p , something that is clear in my final example since state ends up getting totally factored out since it’s handled by the filter case.

The eggs and spam joke was just meant to point out that the values assigned to the field mean nothing since they’re just flags for telling if a specific index has been checked.

Finally, this sent me down a cursed code golf rabbit hole that ended with this one liner that gets the first 100 primes (not a proper sieve, but boy is it an abomination)

r=[*range(2,98)];[print(i) for i in r if all(i%j for j in r[:i-2])]
1 Like

True, but also, what’s different about this one?

Here you go:

>>> from sympy import *
>>> i = Symbol('i')
>>> 2*i + 1
2*i + 1
>>> _**2
(2*i + 1)**2
>>> _-1
(2*i + 1)**2 - 1
>>> _/2
(2*i + 1)**2/2 - 1/2
>>> factor(_)
2*i*(i + 1)
3 Likes

A cute example of something you didn’t know regexps could do :wink:

import re
matcher = re.compile(r"|x|(xx+)\1++").fullmatch
for i in range(200):
    if not matcher('x' * i):
        print(i)
3 Likes

@Rosuav Is this the part I’m missing? I did notice that this index converges really quickly (i==5). The fact that you can index a range that starts at >len(seq) is definitely a fun quirk. Means you finish filtering really early on and the inner loop only runs a few times.

The code I presented produces output which is, in the scheme of things, not particularly special or unusual. It’s a very famous sequence. But the code is doing something slightly different from the simple and most obvious way of finding that sequence, and that’s part of what’s going on with the 2*i+1 expression.

1 Like

It’s interesting how much of this example code can be removed while not altering the output really. The Sieve of Eratosthenes will mark a number from any factor, but your example avoids almost all of that double counting.

1 Like

It’s an Euler sieve rather than Eratoshenes, I’m not sure if that’s what you’re getting at.

Not an Euler sieve. Storing only odd ints is common in Eratosthenes, and so is that after finding a prime p, don’t bother “crossing out” anything smaller than p^2 (any composite less than that must have already been crossed off - must have a prime factor less than p). Euler is more aggressive than just that, taking pains to cross out each composite exactly once (by, and only by, its smallest prime factor).

5 Likes

What do you mean with lazier?

So far, noone talked about the resulting field. If it were just an internal tool to achieve the output, the line field[i] = 1 wouldn’t be there and the final line would also assign 1 instead of 2. So what’s up with that?

Not true :-). I’ve known that since it came up in some regex challenge a long time ago. Can’t find it now, maybe it’s gone. I think the challenges were in the style of this, i.e., with “Match these” and “Don’t match these”.

1 Like
2 Likes

Great, the term “regex golf” helped me find it, I think it was this:

1 Like

Since the inner loop is indexed at i*2*(i+1) instead of i , without the field[i] = 1 you’d miss the first step in the sieve. The actual value doesn’t matter, but if you check the contents of field you’ll see exactly where each number was crossed from (main loop or inner loop).

Since the field is Boolean, you can use any truthy/falsely object for your flag (0 or non-zero). Which is why my first snippet just changed the condition to == ‘eggs.

filter(…, enumerate(…)) don’t do anything with the underlying iterable until next is called, so the filter is modified by the state changes inside the loop. It’s really just a way to drop the condition. You do still need to initialize the field.