diff --git a/.gitignore b/.gitignore
index f90bb6b..8df3f08 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
-out.wav
\ No newline at end of file
+out.wav
+*/target/*
+code-guessing/analytics/people
\ No newline at end of file
diff --git a/README.md b/README.md
index 988eef1..ffbf48b 100644
--- a/README.md
+++ b/README.md
@@ -39,4 +39,14 @@ This comes with absolutely no guarantee of support or correct function, although
* `length_terminated_strings.c` - a revolution in computer science, combining the efficient `strlen` of null-terminated strings with the... inclusion of length? of length-prefixed/fat-pointer strings. A length-terminated string has its length at the *end*, occupying 1 to 8 bytes. To find its length, simply traverse the string until the data at the end matches the length traversed so far. Yes, this implementation might slightly have a bit of undefined behaviour.
* `discord-message-dump.py`, which reads a GDPR data dump from Discord and copies all the messages in public channels to a CSV file. I used this for training of a GPT-2 instance on my messages (available on request).
* `spudnet-http.py` - connect to the SPUDNET backend underlying [PotatOS](https://git.osmarks.net/osmarks/potatOS/)'s ~~backdoors~~ remote debugging system via the convenient new HTTP long-polling-based API.
-* `fractalart-rs` - [this](https://github.com/TomSmeets/FractalArt/) in Rust and faster, see its own README for more details.
\ No newline at end of file
+* `fractalart-rs` - [this](https://github.com/TomSmeets/FractalArt/) in Rust and faster, see its own README for more details.
+* `arbtt_wayland_toplevel.py` - interfaces [arbtt](https://arbtt.nomeata.de/) with Wayland foreign toplevel protocol and idle notifications.
+* `fractalize_image.py` - used for making a profile picture for someone once.
+* `goose2function.py` - converts goose neck profiles extracted from images of geese into activation functions for machine learning.
+* `histretention.py` - dump Firefox `places.sqlite3` into a separate database (Firefox clears out old history internally for performance reasons or something like that) for later search.
+* `memeticize.py` - the script I use to process memes from a large directory of heterogenous files.
+* `rng_trainer.html` - a very unfinished attempt to implement a paper I found on training high-quality random number generation.
+* `smtp2rss.py` - bridge SMTP (inbound emails) to RSS.
+* `yearbox.html` - DokuWiki-type yearbox prototype for Minoteaur (I think this actually contains an off-by-one error somewhere; it isn't what's actually in use).
+* `arbitrary-politics-graphs` - all you need to run your own election campaign.
+* `heavbiome` - some work on biome generation with Perlin noise.
\ No newline at end of file
diff --git a/arbitrary-politics-graphs/g1.png b/arbitrary-politics-graphs/g1.png
new file mode 100644
index 0000000..a98576a
Binary files /dev/null and b/arbitrary-politics-graphs/g1.png differ
diff --git a/arbitrary-politics-graphs/g2.png b/arbitrary-politics-graphs/g2.png
new file mode 100644
index 0000000..df481ba
Binary files /dev/null and b/arbitrary-politics-graphs/g2.png differ
diff --git a/arbitrary-politics-graphs/g3.png b/arbitrary-politics-graphs/g3.png
new file mode 100644
index 0000000..61cc519
Binary files /dev/null and b/arbitrary-politics-graphs/g3.png differ
diff --git a/arbitrary-politics-graphs/g4.png b/arbitrary-politics-graphs/g4.png
new file mode 100644
index 0000000..fea2b21
Binary files /dev/null and b/arbitrary-politics-graphs/g4.png differ
diff --git a/arbitrary-politics-graphs/test.html b/arbitrary-politics-graphs/test.html
new file mode 100644
index 0000000..f0a2b8e
--- /dev/null
+++ b/arbitrary-politics-graphs/test.html
@@ -0,0 +1,40 @@
+
+
+
+
+
if I am elected
+
good things
+
+
bad things
+
+
+
+
otherwise
+
good things
+
+
bad things
+
+
+
\ No newline at end of file
diff --git a/arbtt_wayland_toplevel.py b/arbtt_wayland_toplevel.py
new file mode 100755
index 0000000..e03d85a
--- /dev/null
+++ b/arbtt_wayland_toplevel.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python3
+from functools import partial
+from datetime import datetime, timezone
+from wl_framework.network.connection import WaylandConnection
+from wl_framework.protocols.base import UnsupportedProtocolError
+from wl_framework.protocols.foreign_toplevel import ForeignTopLevel
+from wl_framework.protocols.data_control import DataControl
+from wl_framework.protocols.idle_notify import ( IdleNotifyManager, IdleNotifier as _IdleNotifier )
+import asyncio.subprocess as subprocess
+import orjson
+
+class ForeignTopLevelMonitor(ForeignTopLevel):
+ def __init__(self, *args, **kwargs):
+ self.tlwindows = {}
+ super().__init__(*args, **kwargs)
+
+ def on_toplevel_created(self, toplevel):
+ self.tlwindows[toplevel.obj_id] = {}
+
+ def on_toplevel_synced(self, toplevel):
+ self.tlwindows[toplevel.obj_id]["app_id"] = toplevel.app_id
+ self.tlwindows[toplevel.obj_id]["title"] = toplevel.title
+ self.tlwindows[toplevel.obj_id]["states"] = toplevel.states
+ self.tlwindows[toplevel.obj_id]["outputs"] = { x.name for x in toplevel.outputs }
+
+ def on_toplevel_closed(self, toplevel):
+ del self.tlwindows[toplevel.obj_id]
+
+# not actually using this
+class ClipboardMonitor(DataControl):
+
+ def on_new_selection(self, offer):
+ self._print_selection(offer)
+ self._receive(offer)
+
+ def on_new_primary_selection(self, offer):
+ self._print_selection(offer, is_primary=True)
+ self._receive(offer, is_primary=True)
+
+ # Internal
+ def _receive(self, offer, is_primary=False):
+ if offer is None:
+ return
+ for mime in (
+ 'text/plain;charset=utf-8',
+ 'UTF8_STRING',
+ ):
+ if mime in offer.get_mime_types():
+ offer.receive(mime, partial(self._on_received, is_primary=is_primary))
+ break
+
+ def _print_selection(self, offer, is_primary=False):
+ _selection = 'primary' if is_primary else 'main'
+ if offer is None:
+ self.log(f"{_selection.capitalize()} selection cleared")
+ return
+ self.log(f"New {_selection} selection offers:")
+ for mime_type in offer.get_mime_types():
+ self.log(f" {mime_type}")
+
+ def _on_received(self, mime_type, data, is_primary=False):
+ if data:
+ data = data.decode('utf-8')
+ self.log(f"Received {' primary' if is_primary else 'main'} selection: '{data}'")
+
+class IdleNotifier(_IdleNotifier):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.idle_start = None
+
+ def on_idle(self):
+ self.idle_start = datetime.now(tz=timezone.utc)
+
+ def on_resume(self):
+ self.idle_start = None
+
+class WlMonitor(WaylandConnection):
+ def on_initial_sync(self, data):
+ super().on_initial_sync(data)
+ self.toplevels = ForeignTopLevelMonitor(self)
+ #self.clipboard = ClipboardMonitor(self)
+ self.idle = IdleNotifyManager(self, IdleNotifier)
+ self.idle_notifier = self.idle.get_idle_notifier(0, self.display.seat)
+
+INTERVAL_MS = 60_000
+
+def generate_log_entry(wl: WlMonitor()):
+ entry = {"desktop": ""}
+ now = datetime.now(timezone.utc)
+ entry["date"] = now.isoformat()
+ entry["rate"] = INTERVAL_MS
+ if wl.idle_notifier.idle_start:
+ entry["inactive"] = int((now.timestamp() - wl.idle_notifier.idle_start.timestamp()) * 1000)
+ else:
+ entry["inactive"] = 0
+ def arbitrary_output(window):
+ s = window["outputs"]
+ try:
+ return s.pop()
+ except KeyError:
+ return ""
+ entry["windows"] = [ { "title": x["title"], "program": x["app_id"], "active": "activated" in x["states"], "hidden": "minimized" in x["states"] } for x in wl.toplevels.tlwindows.values() ]
+ return entry
+
+if __name__ == '__main__':
+ import sys
+
+ import asyncio
+ from wl_framework.loop_integrations import AsyncIOIntegration
+
+ async def init():
+ arbtt_importer = await subprocess.create_subprocess_exec("arbtt-import", "-a", "-t", "JSON", stdin=subprocess.PIPE)
+ loop = AsyncIOIntegration()
+ try:
+ app = WlMonitor(eventloop_integration=loop)
+ await asyncio.sleep(1)
+ while True:
+ entry = generate_log_entry(app)
+ arbtt_importer.stdin.write(orjson.dumps(entry))
+ arbtt_importer.stdin.write(b"\n")
+ await asyncio.sleep(INTERVAL_MS / 1000)
+ except RuntimeError as e:
+ print(e)
+ sys.exit(1)
+ try:
+ asyncio.run(init())
+ except KeyboardInterrupt:
+ print()
diff --git a/beep.py b/beep.py
index caa2b87..cb6b4b5 100644
--- a/beep.py
+++ b/beep.py
@@ -56,10 +56,27 @@ def save_wav(file_name):
wav_file.close()
return
+BAD_INTERVALS = [6, 8, 10, 11, 13]
+NOTE_FACTOR = pow(2, 1/12)
+LOG_NOTE_FACTOR = math.log(NOTE_FACTOR)
+BASE = 440
+MIN = math.ceil(math.log(200/440) / LOG_NOTE_FACTOR)
+MAX = math.floor(math.log(2000/440) / LOG_NOTE_FACTOR)
+
import random
-freq = 6
-for i in range(160):
- append_sinewave(volume=1.0, freq=math.exp(freq), duration_milliseconds=50)
- freq += random.uniform(-0.2, 0.2)
- freq = max(4.5, min(freq, 9))
+for i in range(10):
+ """
+ for i in range(3):
+ append_sinewave(800, 100)
+ append_silence(100)
+ append_sinewave(600, 500)
+ append_silence()
+ """
+ note = random.randint(MIN, MAX)
+ while MIN <= note <= MAX:
+ interval = random.choice(BAD_INTERVALS)
+ time = random.randint(50, 1000)
+ append_sinewave(BASE * pow(NOTE_FACTOR, note), time)
+ note += interval if random.choice((True, False)) else -interval
+
save_wav("output.wav")
diff --git a/code-guessing/analytics/download_6_to_13.py b/code-guessing/analytics/download_6_to_13.py
new file mode 100644
index 0000000..2865f21
--- /dev/null
+++ b/code-guessing/analytics/download_6_to_13.py
@@ -0,0 +1,28 @@
+from bs4 import BeautifulSoup
+import requests
+import os
+import os.path
+
+people = {
+
+}
+
+for round_id in range(6, 13):
+ print("round", round_id)
+ m = BeautifulSoup(requests.get(f"https://cg.esolangs.gay/{round_id}/").text, features="lxml")
+ for file_link in m.select("details > summary > a"):
+ name = file_link.parent.parent.previous_sibling.previous_sibling.previous_sibling.previous_sibling
+ if "impersonating" in name.text:
+ name = name.previous_sibling.previous_sibling
+ assert "written by" in name.text, f"oh no {name.text}"
+ name = name.text.split("written by ")[-1]
+ name = people.get(name, name).lower()
+ href = file_link.attrs["href"]
+ filename = str(round_id) + "-" + href.split(f"/{round_id}/")[-1]
+ full_href = f"https://cg.esolangs.gay{href}"
+ os.makedirs(os.path.join("people", name), exist_ok=True)
+ with open(os.path.join("people", name, filename), "wb") as f:
+ with requests.get(full_href, stream=True) as r:
+ r.raise_for_status()
+ for chunk in r.iter_content(chunk_size=(2<<18)):
+ f.write(chunk)
\ No newline at end of file
diff --git a/code-guessing/analytics/run.py b/code-guessing/analytics/run.py
new file mode 100644
index 0000000..7ad011e
--- /dev/null
+++ b/code-guessing/analytics/run.py
@@ -0,0 +1,6 @@
+import os
+import os.path
+
+for person in os.listdir("people"):
+ for submission in os.listdir(os.path.join("people", person)):
+ print(person, submission)
\ No newline at end of file
diff --git a/code-guessing/entry-rs/Cargo.lock b/code-guessing/entry-rs/Cargo.lock
new file mode 100644
index 0000000..0b6b239
--- /dev/null
+++ b/code-guessing/entry-rs/Cargo.lock
@@ -0,0 +1,257 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "entry-rs"
+version = "0.1.0"
+dependencies = [
+ "pyo3",
+]
+
+[[package]]
+name = "indoc"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8"
+dependencies = [
+ "indoc-impl",
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "indoc-impl"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unindent",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
+
+[[package]]
+name = "lock_api"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "paste"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
+dependencies = [
+ "paste-impl",
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "paste-impl"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
+dependencies = [
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "pyo3"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35100f9347670a566a67aa623369293703322bb9db77d99d7df7313b575ae0c8"
+dependencies = [
+ "cfg-if",
+ "indoc",
+ "libc",
+ "parking_lot",
+ "paste",
+ "pyo3-build-config",
+ "pyo3-macros",
+ "unindent",
+]
+
+[[package]]
+name = "pyo3-build-config"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d12961738cacbd7f91b7c43bc25cfeeaa2698ad07a04b3be0aa88b950865738f"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "pyo3-macros"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc0bc5215d704824dfddddc03f93cb572e1155c68b6761c37005e1c288808ea8"
+dependencies = [
+ "pyo3-macros-backend",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pyo3-macros-backend"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71623fc593224afaab918aa3afcaf86ed2f43d34f6afde7f3922608f253240df"
+dependencies = [
+ "proc-macro2",
+ "pyo3-build-config",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "smallvec"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
+
+[[package]]
+name = "syn"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "unindent"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/code-guessing/entry-rs/Cargo.toml b/code-guessing/entry-rs/Cargo.toml
new file mode 100644
index 0000000..5db3d34
--- /dev/null
+++ b/code-guessing/entry-rs/Cargo.toml
@@ -0,0 +1,13 @@
+
+[package]
+name = "entry-rs"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "entry_rs"
+crate-type = ["cdylib"]
+
+[dependencies.pyo3]
+version = "0.14.5"
+features = ["extension-module"]
diff --git a/code-guessing/entry-rs/src/entry_impl.rs b/code-guessing/entry-rs/src/entry_impl.rs
new file mode 100644
index 0000000..11b0b54
--- /dev/null
+++ b/code-guessing/entry-rs/src/entry_impl.rs
@@ -0,0 +1,85 @@
+pub fn entry(s: &str) -> i32 {
+ let digit = |c: u8| (c as i32) - 48;
+ let mut acc = 0;
+ let mut pos = 0;
+ let b = s.as_bytes();
+ loop {
+ match b[pos] {
+ b'+' => {
+ acc += {
+ pos += 1;
+ let mut acc = 0;
+ while (pos + 1) < b.len() && (b[pos + 1] == b'/' || b[pos + 1] == b'*') {
+ println!("DIV or MUL {} {} {}", b[pos], b[pos + 1], b[pos + 2]);
+ if acc == 0 {
+ acc = digit(b[pos])
+ }
+ if b[pos + 1] == b'/' {
+ acc /= digit(b[pos + 2])
+ } else {
+ acc *= digit(b[pos + 2])
+ }
+ pos += 2;
+ }
+ if acc == 0 {
+ digit(b[pos])
+ } else {
+ acc
+ }
+ };
+ pos += 1;
+ },
+ b'-' => {
+ acc -= {
+ pos += 1;
+ let mut acc = -1;
+ while (pos + 1) < b.len() && (b[pos + 1] == b'/' || b[pos + 1] == b'*') {
+ println!("DIV or MUL {} {} {}", b[pos], b[pos + 1], b[pos + 2]);
+ if acc == -1 {
+ acc = digit(b[pos])
+ }
+ if b[pos + 1] == b'/' {
+ acc /= digit(b[pos + 2])
+ } else {
+ acc *= digit(b[pos + 2])
+ }
+ pos += 2;
+ }
+ if acc == -1 {
+ digit(b[pos])
+ } else {
+ acc
+ }
+ };
+ pos += 1;
+ },
+ x => {
+ acc += {
+ let mut acc = 0;
+ while (pos + 1) < b.len() && (b[pos + 1] == b'/' || b[pos + 1] == b'*') {
+ println!("DIV or MUL {} {} {}", b[pos], b[pos + 1], b[pos + 2]);
+ if acc == 0 {
+ acc = digit(b[pos])
+ }
+ if b[pos + 1] == b'/' {
+ acc /= digit(b[pos + 2])
+ } else {
+ acc *= digit(b[pos + 2])
+ }
+ pos += 2;
+ }
+ if acc == 0 {
+ digit(b[pos])
+ } else {
+ acc
+ }
+ };
+ pos += 1
+ }
+ }
+ if pos >= b.len() {
+ break
+ }
+ }
+ acc
+}
\ No newline at end of file
diff --git a/code-guessing/entry-rs/src/lib.rs b/code-guessing/entry-rs/src/lib.rs
new file mode 100644
index 0000000..5d5f084
--- /dev/null
+++ b/code-guessing/entry-rs/src/lib.rs
@@ -0,0 +1,16 @@
+
+use pyo3::prelude::*;
+
+mod entry_impl;
+use entry_impl::entry;
+
+#[pyfunction]
+fn wrapped_entry(s: &str) -> PyResult {
+ Ok(entry(s))
+}
+
+#[pymodule]
+fn entry_rs(_py: Python, m: &PyModule) -> PyResult<()> {
+ m.add_function(wrap_pyfunction!(wrapped_entry, m)?)?;
+ Ok(())
+}
diff --git a/code-guessing/gif.s b/code-guessing/gif.s
new file mode 100644
index 0000000..2cc2eb7
--- /dev/null
+++ b/code-guessing/gif.s
@@ -0,0 +1,53 @@
+; a hand-made GIF containing valid JavaScript code
+; abusing header to start a JavaScript comment
+
+; inspired by Saumil Shah's Deadly Pixels presentation
+
+; Ange Albertini, BSD Licence 2013
+
+; yamal gifjs.asm -o img.gif
+
+WIDTH equ 10799 ; equivalent to 2f2a, which is '/*' in ASCII, thus starting an opening comment
+
+HEIGHT equ 10799 ; just to make it easier to spot
+
+db 'GIF89a'
+ dw WIDTH, HEIGHT
+
+db 0 ; GCT
+ db -1 ; background color
+ db 0 ; default aspect ratio
+ ;db 0fch, 0feh, 0fch
+ ;times COLORS db 0, 0, 0
+
+; no need of Graphic Control Extension
+ ; db 21h, 0f9h
+ ; db GCESIZE ; size
+ ; gce_start:
+ ; db 0 ; transparent background
+ ; dw 0 ; delay for anim
+ ; db 0 ; other transparent
+ ; GCESIZE equ $ - gce_start
+ ; db 0 ; end of GCE
+
+db 02ch ; Image descriptor
+ dw 0, 0 ; NW corner
+ dw WIDTH, HEIGHT ; w/h of image
+ db 0 ; color table
+
+db 2 ; lzw size
+
+;db DATASIZE
+;data_start:
+; db 00, 01, 04, 04
+; DATASIZE equ $ - data_start
+
+db 0
+db 3bh ; GIF terminator
+
+; end of the GIF
+
+db '*/' ; closing the comment
+db '=1;' ; creating a fake use of that GIF89a string
+
+db 'alert("haxx");'
\ No newline at end of file
diff --git a/code-guessing/giftest.html b/code-guessing/giftest.html
new file mode 100644
index 0000000..82b4337
--- /dev/null
+++ b/code-guessing/giftest.html
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/code-guessing/img.gif b/code-guessing/img.gif
new file mode 100644
index 0000000..0672599
Binary files /dev/null and b/code-guessing/img.gif differ
diff --git a/code-guessing/img.js b/code-guessing/img.js
new file mode 120000
index 0000000..8322fc7
--- /dev/null
+++ b/code-guessing/img.js
@@ -0,0 +1 @@
+img.gif
\ No newline at end of file
diff --git a/code-guessing/test12.py b/code-guessing/test12.py
new file mode 100644
index 0000000..f987964
--- /dev/null
+++ b/code-guessing/test12.py
@@ -0,0 +1,185 @@
+import sys
+import importlib
+import subprocess
+import ctypes
+import random
+import traceback
+import textwrap
+import json
+import os
+import shutil
+try:
+ from tqdm import tqdm, trange
+except ImportError:
+ print("`tqdm` not found. there will be no progress bars")
+ def tqdm(x):
+ return x
+ trange = range
+
+
+filename = sys.argv[1]
+
+if filename.endswith(".py"):
+ print("importing as Python...")
+ module = importlib.import_module(filename.removesuffix(".py"))
+ print("done.")
+ try:
+ entry = module.entry
+ except AttributeError:
+ print("module is missing entrypoint `entry`. aborting.")
+ sys.exit(1)
+elif filename.endswith(".c"):
+ print("compiling as C with `gcc`...")
+ obj = "./" + filename.removesuffix(".c") + ".so"
+ rc = subprocess.call(["gcc", "-shared", "-fPIC", *sys.argv[2:], filename, "-o", obj])
+ if rc != 0:
+ print("compilation failed. aborting.")
+ sys.exit(rc)
+ lib = ctypes.CDLL(obj)
+ try:
+ entry = lib.entry
+ except AttributeError:
+ print("library is missing entrypoint `entry`. aborting.")
+ sys.exit(1)
+elif filename.endswith(".rs"):
+ print("compiling as Rust...")
+ os.makedirs("./entry-rs/src", exist_ok=True)
+ with open("./entry-rs/Cargo.toml", "w") as f:
+ f.write("""
+[package]
+name = "entry-rs"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "entry_rs"
+crate-type = ["cdylib"]
+
+[dependencies.pyo3]
+version = "0.14.5"
+features = ["extension-module"]
+""")
+ with open("./entry-rs/src/lib.rs", "w") as f:
+ f.write("""
+use pyo3::prelude::*;
+
+mod entry_impl;
+use entry_impl::entry;
+
+#[pyfunction]
+fn wrapped_entry(s: &str) -> PyResult {
+ Ok(entry(s))
+}
+
+#[pymodule]
+fn entry_rs(_py: Python, m: &PyModule) -> PyResult<()> {
+ m.add_function(wrap_pyfunction!(wrapped_entry, m)?)?;
+ Ok(())
+}
+""")
+ shutil.copyfile(filename, "./entry-rs/src/entry_impl.rs")
+ os.chdir("entry-rs")
+ rc = subprocess.call(["cargo", "build", "--release"])
+ os.chdir("..")
+ if rc != 0:
+ print("compilation failed. aborting.")
+ sys.exit(1)
+ sys.path.append("./entry-rs/target/release")
+ os.rename("./entry-rs/target/release/libentry_rs.so", "./entry-rs/target/release/entry_rs.so")
+ module = importlib.import_module("entry_rs")
+ entry = module.wrapped_entry
+else:
+ print("unrecognized file extension")
+ sys.exit(1)
+
+
+tests = [
+ ("zero", "0", 0),
+ ("add", "1+2", 3),
+ ("sub", "2-1", 1),
+ ("mul", "2*3", 6),
+ ("div", "4/2", 2),
+ ("floor", "4/3", 1),
+ ("neg", "0-4", -4),
+ ("chain", "4/2/2", 1),
+ ("olivia", "1+7/4-0*4", 2),
+ ("gollario", "4-4-4-4+8", 0)
+]
+
+print("beginning testing suite")
+failures = 0
+
+for test_name, value, result in tqdm(tests):
+ print(f"`{test_name}`... ", end="")
+ try:
+ r = entry(value)
+ except BaseException:
+ print("error")
+ traceback.print_exc()
+ print(f"in test `{test_name}`:")
+ print(textwrap.indent(value, " "*2))
+ failures += 1
+ continue
+ if r == result:
+ print("ok")
+ else:
+ failures += 1
+ print("failed")
+ print(f"for test `{test_name}`:")
+ print(textwrap.indent(value, " "*2))
+ print(f"entry returned {r} when {result} was expected\n")
+if not failures:
+ print("test suite finished, all ok")
+else:
+ print(f"test suite finished. {failures} tests failed\n\n")
+ print("skipping randomized testing because your program is clearly broken and the output from those isn't very helpful for finding bugs")
+ sys.exit(2)
+
+
+def gen_random_json():
+ s = random.choice("0123456789")
+ for _ in range(random.randint(0, 10)):
+ s += random.choice("+-*/")
+ s += random.choice("0123456789")
+ return s
+
+
+print("beginning randomized testing.")
+random_failures = 0
+for _ in trange(100):
+ while True:
+ j = gen_random_json()
+ try:
+ tr = eval(j.replace("/", "//"))
+ except ZeroDivisionError:
+ continue
+ else:
+ break
+ try:
+ r = entry(j)
+ except BaseException:
+ print("error")
+ traceback.print_exc()
+ print("in randomized test case:")
+ print(textwrap.indent(j, " "*2))
+ random_failures += 1
+ continue
+ if r != tr:
+ print("randomized test case failed:")
+ print(textwrap.indent(j, " "*2))
+ print(f"entry returned {r} when {tr} was expected\n")
+ random_failures += 1
+
+if not random_failures:
+ print("randomized testing finished. all ok\n\n")
+else:
+ print(f"randomized testing finished with {random_failures} failures\n\n")
+
+
+print("overall report:")
+overall = failures + random_failures
+if not overall:
+ print("no failures detected. all seems well!")
+else:
+ print(f"{overall} failures detected overall. you have some bugs to fix")
+ sys.exit(2)
diff --git a/count_words_in_directory.py b/count_words_in_directory.py
new file mode 100644
index 0000000..03937ca
--- /dev/null
+++ b/count_words_in_directory.py
@@ -0,0 +1,14 @@
+import os, sys, string
+
+count = 0
+words = 0
+characters = 0
+for dirpath, dirnames, filenames in os.walk(sys.argv[1]):
+ for filename in filenames:
+ with open(os.path.join(dirpath, filename)) as f:
+ content = f.read()
+ characters += len([c for c in content if c in string.ascii_letters])
+ words += len([thing for thing in content.split() if thing.strip()])
+ count += 1
+
+print(words / count, characters / count)
\ No newline at end of file
diff --git a/cycdec.py b/cycdec.py
new file mode 100644
index 0000000..0638065
--- /dev/null
+++ b/cycdec.py
@@ -0,0 +1,19 @@
+perm = [
+ [1, 2, 3, 4, 5, 6, 7, 8],
+ [5, 7, 8, 2, 3, 6, 4, 1]
+]
+perm = dict(zip(*perm))
+vals = set(perm)
+
+print(perm)
+cycs = []
+while vals:
+ nxt = vals.pop()
+ seen = []
+ while nxt not in seen:
+ lnxt = nxt
+ nxt = perm[nxt]
+ seen.append(lnxt)
+ cycs.append(seen)
+ vals -= set(seen)
+print(cycs)
\ No newline at end of file
diff --git a/cyclcm.py b/cyclcm.py
new file mode 100644
index 0000000..c62dc9f
--- /dev/null
+++ b/cyclcm.py
@@ -0,0 +1,25 @@
+import math, itertools
+
+count = 0
+for permutation in itertools.permutations(range(7)):
+ perm = [
+ list(range(7)),
+ list(permutation)
+ ]
+ perm = dict(zip(*perm))
+ vals = set(perm)
+
+ print(perm)
+ cycs = []
+ while vals:
+ nxt = vals.pop()
+ seen = []
+ while nxt not in seen:
+ lnxt = nxt
+ nxt = perm[nxt]
+ seen.append(lnxt)
+ cycs.append(seen)
+ vals -= set(seen)
+ if math.lcm(*map(len, cycs)) == 4:
+ count += 1
+print(count)
\ No newline at end of file
diff --git a/esolangs-iceberg/iceberg.html b/esolangs-iceberg/iceberg.html
index 2fe270a..5b930c7 100644
--- a/esolangs-iceberg/iceberg.html
+++ b/esolangs-iceberg/iceberg.html
@@ -148,6 +148,7 @@ li, h2 {
heavpoot is osmarks
second #staff-only channel
colin
+hactar secretly planning takeover
less than 10% of users are frequently active
cyber PC diagram
@@ -175,4 +176,4 @@ li, h2 {
-