Compare commits

3 Commits

Author SHA1 Message Date
flancian 9aa323d6ac autopushed 2026-07-20 21:07:53 +02:00
flancian 6a41fc820f autopushed 2026-07-20 21:07:18 +02:00
flancian 69fc4d2e42 autopushed 2026-07-20 20:49:37 +02:00
3 changed files with 88 additions and 41 deletions
+1
View File
@@ -0,0 +1 @@
- [[Simon]] told me about [[Stiftung für direkte Demokratie]]!
+2
View File
@@ -0,0 +1,2 @@
- Stiftung für direkte Demokratie
- https://www.demokratie.ch/
+85 -41
View File
@@ -7,44 +7,65 @@ import click
import math import math
import sys import sys
# I'm not proud (I am a little bit?).
PROOF = [] # :)
def factor(n): def get_prime_factors(n):
for i in range(2, n+1): """Computes the full prime factorization of n."""
click.echo(f"Is {i} a factor of {n}, I wonder?") factors = []
d = 2
temp = abs(n)
while d * d <= temp:
while temp % d == 0:
factors.append(d)
temp //= d
d += 1
if temp > 1:
factors.append(temp)
return factors
def print_sieve(sieve):
primes = []
for n, prime in enumerate(sieve):
if n >= 2 and prime:
primes.append(str(n))
return ", ".join(primes)
def is_prime(n): def get_factor_pairs(n):
sieve = [True for n in range(0, n+1)] """Returns all proper factor pairs (a, b) such that a * b = n with a <= b."""
upto = math.ceil(math.sqrt(n)) pairs = []
for i, _ in enumerate(sieve): n_abs = abs(n)
# click.echo(f"i: {i}") for i in range(2, math.isqrt(n_abs) + 1):
if i < 2: if n_abs % i == 0:
continue pairs.append((i, n_abs // i))
# If we're above the square root, we can stop considering the first factor, as we'll try higher numbers in the inner loop. return pairs
if i > upto:
break
# If this is a known composite, then we've already crossed off its multiples when we iterated over its primes. def get_proper_divisors(n):
if not sieve[i]: """Returns all proper divisors of n strictly between 1 and n."""
continue divs = set()
# for j in range(2, math.ceil(math.sqrt(n) + 1)): n_abs = abs(n)
for j in range(2, n): for i in range(2, math.isqrt(n_abs) + 1):
# I wrote >= here initially. That did *not* work ;) if n_abs % i == 0:
if i * j > n: divs.add(i)
break divs.add(n_abs // i)
PROOF.append(f"[[{i*j}]] is composite: {i} * {j}.") return sorted(list(divs))
try:
sieve[i*j] = False
except IndexError: def sieve_primes(n):
continue """Generates all prime numbers up to n using the Sieve of Eratosthenes."""
return (n >= 2 and sieve[n], sieve) if n < 2:
return []
sieve = [True] * (n + 1)
sieve[0] = sieve[1] = False
for i in range(2, math.isqrt(n) + 1):
if sieve[i]:
for j in range(i * i, n + 1, i):
sieve[j] = False
return [i for i, is_p in enumerate(sieve) if is_p]
def format_primes(primes, limit=50):
"""Formats a list of primes with wikilinks, capping output if too long."""
total = len(primes)
if total <= limit:
return ", ".join(f"[[{p}]]" for p in primes)
else:
shown = ", ".join(f"[[{p}]]" for p in primes[:limit])
return f"{shown}, ... ({total} total)"
class AgoraCmd(click.Command): class AgoraCmd(click.Command):
def format_help(self, ctx, formatter): def format_help(self, ctx, formatter):
@@ -67,18 +88,41 @@ class AgoraCmd(click.Command):
except SystemExit: except SystemExit:
sys.exit(exc.exit_code) sys.exit(exc.exit_code)
@click.command(cls=AgoraCmd) @click.command(cls=AgoraCmd)
@click.argument('n', type=click.INT) @click.argument('n', type=click.INT)
def prime(n): def prime(n):
"""Simple program that factors a number using a [[Sieve of Eratosthenes]].""" """Factors a number using prime decomposition and a [[Sieve of Eratosthenes]]."""
p, sieve = is_prime(n) if n <= 1:
if p: click.echo(f"[[{n}]] is neither prime nor composite.")
return
factors = get_prime_factors(n)
is_p = (len(factors) == 1)
if is_p:
click.echo(f"[[{n}]] is *prime*.") click.echo(f"[[{n}]] is *prime*.")
else: else:
click.echo(f"[[{n}]] is *not prime*. Want proof? :)") click.echo(f"[[{n}]] is *not prime* (composite). Want proof? :)")
click.echo("\n".join([line for line in PROOF if f'[[{n}]]' in line])) factor_links = " * ".join(f"[[{f}]]" for f in factors)
click.echo(f"\nFull prime factorization: {factor_links}")
pairs = get_factor_pairs(n)
if pairs:
click.echo("\nFactor pairs:")
for a, b in pairs:
click.echo(f" [[{n}]] = [[{a}]] * [[{b}]]")
divs = get_proper_divisors(n)
if divs:
divs_str = ", ".join(f"[[{d}]]" for d in divs)
click.echo(f"\nProper divisors: {divs_str}")
primes = sieve_primes(n)
if primes:
click.echo(f"\nPrimes up to {n}: {format_primes(primes)}.")
click.echo(f"\nPrimes up to {n}: {print_sieve(sieve)}.")
if __name__ == '__main__': if __name__ == '__main__':
prime() prime()