This commit is contained in:
mehbark 2025-12-26 08:02:02 -05:00
commit aed21bb06a
Signed by: mbk
GPG key ID: E333EC1335FFCCDB
5 changed files with 307 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

148
Cargo.lock generated Normal file
View file

@ -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",
]

7
Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[package]
name = "bit-art"
version = "0.1.0"
edition = "2024"
[dependencies]
rand = "0.9.2"

3
README.md Normal file
View file

@ -0,0 +1,3 @@
generate images from random bitwise expressions forever. idea taken from <https://freeradical.zone/@bitartbot>
`Ctrl`+`c` to stop

148
src/main.rs Normal file
View file

@ -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<Inst> for StandardUniform {
fn sample<R: rand::Rng + ?Sized>(&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<Inst>,
}
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<u8>, op: impl FnOnce(u8) -> u8) {
let x = stack.pop().unwrap_or_default();
stack.push(op(x));
}
fn dyad(stack: &mut Vec<u8>, 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<Expr> for StandardUniform {
fn sample<R: rand::Rng + ?Sized>(&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 }
}
}