Skip to content

Commit

Permalink
Merge branch 'project-euler'
Browse files Browse the repository at this point in the history
  • Loading branch information
generic-github-user committed Jan 9, 2023
2 parents fe12059 + ae0afb3 commit 72ee3a1
Show file tree
Hide file tree
Showing 12 changed files with 357 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ primes.txt
~
node_modules

node_modules

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
175 changes: 175 additions & 0 deletions lib/pyiter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
from lib.python.pystring import String
from lib.python.number import Number


class Number2(int):
def __init__(self, x):
super().__init__()


class Range:
def __init__(self, a, b):
self.n = Number(a)
self.bounds = (Number(a), Number(b))

def __next__(self):
if self.n < (self.bounds[1] - 1):
self.n += 1
return self.n
return None

def to_iter(self):
# TODO: allow proper cloning of range objects
return Iter(self, self.n, lambda S: self.__next__())
# RangeIterator = Iter.make_iterator_wrapper()

def __str__(self):
return f'Range [ {self.bounds[0]}..{self.bounds[1]} ]'


class Iter:
def __init__(self, inner, init=None, next_=None):
if next_ is None:
next_ = lambda S: inner.__next__()

self.value = init
self.inner = inner

self.next_ = next_
# self.__next__ = next_
# self.next = self.__next__

def clone(self):
return Iter(self.inner, self.value, self.next_)

def __iter__(self):
return self

def __next__(self):
self.value = self.next_(self)
return self.value

def next(self):
self.value = self.__next__()
return self.value

def step(self):
v = self.current()
self.next()
return v

def stepped(self):
self.next()
return self

def current(self):
return self.value

# TODO
def filter(self, f):
def nnext(S):
while not f(self.step()):
if S.current() is None:
return None
return S.current()

return Iter(self, self.current(), nnext)

def take(self, n):
class taker(Iter):
def __init__(inner, i=0):
super().__init__(inner, None, inner.__next__)
inner.i = i

def __next__(inner):
# nonlocal i
if inner.i < n:
inner.i += 1
return self.next()
return None

def clone(inner):
return taker(i=inner.i)

# return Iter(self, self.current(), nnext)
return taker()

def windows(self, n, size_hint=None):
i = 0

def nnext(S):
nonlocal i
# return S.stepped().clone().take(n)
if self.next() is None or (size_hint is not None
and i >= size_hint() - n - 1):
return None
return self.clone().take(n)
return Iter(self, self.current(), nnext)

def all(self, f):
while (x := self.step()) is not None:
# if not f(self.current()):
if not f(x):
return False
return True

def any(self, f):
while (x := self.step()) is not None:
if f(x):
return True
return False

def none(self, f):
return not self.any(f)

def map(self, f):
def nnext(S):
value = self.next()
if value is None:
return value
else:
return f(value)
return Iter(self, self.current(), nnext)

def join(self, delim):
result = ''
# TODO
while (x := self.next()) is not None:
if result:
result += delim
result += String.to_str_guard(x)
# result += str(x)
return result

def to_list(self):
result = []
while (x := self.next()) is not None:
result.append(x)
return result

def to_set(self):
return set(self.to_list())

def to_string(self):
return self.map(String.to_str_guard).join(', ')

def print(self):
print(self.to_string())

@staticmethod
def make_iterator_wrapper(origin, wrapper_next, attributes):
class Wrapper(Iter):
def __init__(inner, *args, **kwargs):
super().__init__(inner, None, inner.__next__, *args, **kwargs)

def __next__(inner):
return wrapper_next(inner)

def clone(inner):
attrs = {k: getattr(inner, k) for k in attributes.keys()}
return Wrapper(**attrs)
return Wrapper


def range(*args):
return Range(*args).to_iter()
2 changes: 1 addition & 1 deletion lib/python/number.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from lib.pystring import String
from lib.python.pystring import String


class Number:
Expand Down
62 changes: 61 additions & 1 deletion lib/python/pystring.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,64 @@ def lines(self) -> List[String]:
def chars(self) -> List[String]:
return List(self.s)

def to_str_guard(s):
if isinstance(s, str):
return s
# return s.to_string()
elif isinstance(s, String):
return s.to_str()
return str(s)

def to_str(self):
return self.s

def to_string(self):
return self

def __iadd__(self, other):
def iter(self):
from lib.pyiter import Iter

class StringIter(Iter):
def __init__(inner, string, i=-1):
# super().__init__(inner, None, StringIter.__next__)
super().__init__(inner, None, inner.__next__)
inner.i = i
inner.string = string
inner.value = inner.string[inner.i]

def current(inner):
# return inner.string[inner.i]
return inner.value

def clone(inner):
return StringIter(inner.string, inner.i)

def windows(inner, *args, **kwargs):
return super().windows(*args, **kwargs,
size_hint=inner.string.len)
# size_hint=String.len)

def __next__(inner):
if inner.i < (inner.string.len() - 1):
inner.i += 1
inner.value = inner.string[inner.i]
return inner.current()
inner.value = None
return None

def __str__(inner):
return f'StringIter <i = {inner.i}>'

return StringIter(self)

def len(self):
return len(self.s)

def __getitem__(self, key):
# return String(self.s[key])
return self.s[key]

def __add__(self, other):
if isinstance(other, String):
other = other.s
return String(self.s + other)
Expand All @@ -30,3 +84,9 @@ def __bool__(self):

def __str__(self):
return f'"{self.s}"'

def print(self):
print(str(self))

def println(self):
print(str(self) + '\n')
8 changes: 8 additions & 0 deletions puzzles/project-euler/1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const range = require('./../../lib/js/range.js').range;
const rrange = require('./../../lib/js/range.js').rrange;

console.log(rrange(1, 42));
console.log(rrange(0, 20).to_array());
console.log(rrange(1, 20).filter(x => x % 2 === 0).to_array());
console.log(rrange(1, 30).sum());
console.log(rrange(1, 1000).filter(x => x % 3 === 0 || x % 5 === 0).sum());
10 changes: 10 additions & 0 deletions puzzles/project-euler/2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import itertools
def fib():
z = [1]
while True:
z.append(sum(z[-2:]))
if len(z) > 2: z.pop(0)
yield z[-1]

print(sum(filter(lambda x: x % 2 == 0,
itertools.takewhile(lambda y: y <= 4e6, fib()))))
32 changes: 32 additions & 0 deletions puzzles/project-euler/21.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <stdio.h>

int d(int x) {
int sum = 0;
printf("%6d : ", x);
// while (x > 1) {
for (int i=1; i<x; i++) {
if (x % i == 0) {
// x /= i;
sum += i;
printf(" %d", i);
}
}
// }
printf(" ~ %d\n", sum);
return sum;
}

int main() {
int n = 10000;
// int test[n];
int S = 0;
for (int i=1; i<n; i++) {
int di = d(i);
if (di < n && i != di && i == d(di)) {
printf("amicable pair: %d, %d\n", i, di);
S += i;
}
}
printf("%d\n", S);
}

18 changes: 18 additions & 0 deletions puzzles/project-euler/3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
n = 600851475143
# n = 3252


# probably not a good algorithm; not so bad that I won't be able to live with
# myself
def factorize(x):
factors = set()
while x > 1:
for i in range(2, x+1):
if x % i == 0:
factors.add(i)
x //= i
break
return factors


print(factorize(n))
5 changes: 5 additions & 0 deletions puzzles/project-euler/6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const range = require('./../../lib/js/range.js').range;
let R = range(1, 101);
console.log(R.map(x => x ** 2).to_array());
// console.log(R.map(x => x.toString()).sum());
console.log(R.sum() ** 2 - R.map(x => x ** 2).sum());
3 changes: 3 additions & 0 deletions puzzles/project-euler/7.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const range = require('./../../lib/js/range.js').range;
console.log(range(2, 3000).filter(x =>
range(2, Math.ceil(x**0.5)+1).all(y => x % y != 0 || x === y)).nth(100));
17 changes: 17 additions & 0 deletions puzzles/project-euler/7.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from lib.pyiter import range

print(range(1, 10).to_string())
range(1, 10).print()

print(range(1, 10).to_list())
print(range(1, 10).to_set())
print(range(1, 10).inner)
print(range(1, 10).all(lambda x: x < 20))
# range(1, 20).next().print()
range(-10, 11).map(lambda x: x ** 2).print()
# range(32, 42).filter(lambda _: True).print()

# range(2, 3000).filter(lambda x:
# range(2, ceil(x**0.5)+1)
# .all(lambda y: x % y != 0 or x == y)).print()
# .nth(100)
25 changes: 25 additions & 0 deletions puzzles/project-euler/7b.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# from lib.streams import range
from lib.wrapstreams import range
import math

# import sys
# sys.setrecursionlimit(30000)

# range(1, 10e9).filter(lambda x: x % 5 == 0)
R = 10e6
range(-R, R+1).map(lambda x: x ** 2)

print(range(1, 10).to_string())
range(1, 10).print()

print(range(1, 10).to_list())
print(range(1, 10).to_set())
print(range(1, 10).all(lambda x: x < 20))
range(-10, 11).map(lambda x: x ** 2).print()
range(1, 42).filter(lambda x: x % 3 == 0).print()
# range(1, 2000).filter(lambda x: math.sqrt(x) % 1 == 0).print()

is_prime = lambda x: range(2, math.ceil(x**0.5)+1)\
.all(lambda y: x % y != 0 or x == y)
range(2, 100).filter(is_prime).print()
print(range(2, 10e8).filter(is_prime).nth(10000))

0 comments on commit 72ee3a1

Please sign in to comment.