commit aed21bb06a58152d8c1592a07d5ee1800104dd26 Author: mehbark Date: Fri Dec 26 08:02:02 2025 -0500 initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..67dc9af --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,148 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bit-art" +version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "zerocopy" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c399282 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bit-art" +version = "0.1.0" +edition = "2024" + +[dependencies] +rand = "0.9.2" diff --git a/README.md b/README.md new file mode 100644 index 0000000..06873a9 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +generate images from random bitwise expressions forever. idea taken from + +`Ctrl`+`c` to stop diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..7c11ab6 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,148 @@ +use std::{fmt, iter, ops, thread, time::Duration}; + +use rand::{ + Rng, + distr::{Distribution, StandardUniform}, + rng, +}; + +fn main() { + let mut rng = rng(); + + loop { + let expr: Expr = rng.random(); + for y in 0..=255 { + for x in 0..=255 { + let n = expr.run(x, y); + print!("\x1b[48;2;{n};{n};{n}m "); + } + println!(); + } + println!("\x1b[0m{expr}"); + thread::sleep(Duration::from_secs(3)); + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum Inst { + X, + Y, + Const(u8), + + Or, + And, + Xor, + Mod, + Mul, + Div, + Add, + + Not, + Neg, +} + +impl Distribution for StandardUniform { + fn sample(&self, rng: &mut R) -> Inst { + #[allow(clippy::enum_glob_use)] + use Inst::*; + + match rng.random_range(0..12) { + 0 => X, + 1 => Y, + 2 => Const(rng.random()), + + 3 => Or, + 4 => And, + 5 => Xor, + 6 => Mod, + 7 => Mul, + 8 => Div, + 9 => Add, + + 10 => Not, + 11 => Neg, + _ => unreachable!(), + } + } +} + +impl fmt::Display for Inst { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Inst::X => write!(f, "x"), + Inst::Y => write!(f, "y"), + Inst::Const(n) => write!(f, "{n}"), + Inst::Or => write!(f, "|"), + Inst::And => write!(f, "&"), + Inst::Xor => write!(f, "^"), + Inst::Mod => write!(f, "%"), + Inst::Mul => write!(f, "*"), + Inst::Div => write!(f, "/"), + Inst::Add => write!(f, "+"), + Inst::Not => write!(f, "~"), + Inst::Neg => write!(f, "-"), + } + } +} + +struct Expr { + insts: Vec, +} + +impl fmt::Display for Expr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for inst in &self.insts { + write!(f, "{inst} ")?; + } + Ok(()) + } +} + +fn monad(stack: &mut Vec, op: impl FnOnce(u8) -> u8) { + let x = stack.pop().unwrap_or_default(); + stack.push(op(x)); +} + +fn dyad(stack: &mut Vec, op: impl FnOnce(u8, u8) -> u8) { + let first = stack.pop().unwrap_or_default(); + let second = stack.pop().unwrap_or_default(); + stack.push(op(first, second)); +} + +impl Expr { + fn run(&self, x: u8, y: u8) -> u8 { + let mut stack = Vec::new(); + + for inst in &self.insts { + match inst { + Inst::X => stack.push(x), + Inst::Y => stack.push(y), + Inst::Const(n) => stack.push(*n), + + Inst::Or => dyad(&mut stack, ops::BitOr::bitor), + Inst::And => dyad(&mut stack, ops::BitAnd::bitand), + Inst::Xor => dyad(&mut stack, ops::BitXor::bitxor), + Inst::Mul => dyad(&mut stack, u8::wrapping_mul), + Inst::Add => dyad(&mut stack, u8::wrapping_add), + Inst::Mod => dyad(&mut stack, |a, b| u8::checked_rem(a, b).unwrap_or_default()), + Inst::Div => dyad(&mut stack, |a, b| u8::checked_div(a, b).unwrap_or_default()), + + Inst::Not => monad(&mut stack, ops::Not::not), + #[allow(clippy::cast_sign_loss, clippy::cast_possible_wrap)] + Inst::Neg => monad(&mut stack, |x| -(x as i8) as u8), + } + } + + stack.pop().unwrap_or_default() + } +} + +impl Distribution for StandardUniform { + fn sample(&self, rng: &mut R) -> Expr { + let inst_count = rng.random_range(5..40); + let insts = iter::repeat_with(|| rng.random()) + .take(inst_count) + .collect(); + Expr { insts } + } +}