Skip to content

Commit

Permalink
4 more rarities
Browse files Browse the repository at this point in the history
  • Loading branch information
haozhiliu committed Jan 12, 2024
1 parent e37d2ff commit 484ff3f
Show file tree
Hide file tree
Showing 2 changed files with 239 additions and 29 deletions.
123 changes: 117 additions & 6 deletions src/block_rarity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ pub enum BlockRarity {
Palindrome,
Alpha,
Omega,
UniformPalinception,
PerfectPalinception,
Block286,
JPEG,
}

impl Display for BlockRarity {
Expand All @@ -32,6 +36,10 @@ impl Display for BlockRarity {
Self::Block78 => "block78",
Self::Alpha => "alpha",
Self::Omega => "omega",
Self::UniformPalinception => "uniform_palinception",
Self::PerfectPalinception => "perfect_palinception",
Self::Block286 => "block286",
Self::JPEG => "jpeg",
}
)
}
Expand All @@ -52,6 +60,9 @@ impl From<Sat> for Vec<BlockRarity> {
if is_pizza_sat(&sat) {
res.push(BlockRarity::Pizza);
}
if JPEG_BLOCK_HEIGHTS.contains(&block_height) {
res.push(BlockRarity::JPEG);
}
if block_height == BLOCK9_BLOCK_HEIGHT {
if sat.n() >= FIRST_TRANSACTION_SAT_RANGE.0 && sat.n() < FIRST_TRANSACTION_SAT_RANGE.1 {
res.push(BlockRarity::FirstTransaction);
Expand All @@ -62,11 +73,20 @@ impl From<Sat> for Vec<BlockRarity> {
res.push(BlockRarity::Block9);
} else if block_height == BLOCK78_BLOCK_HEIGHT {
res.push(BlockRarity::Block78);
} else if block_height == BLOCK286_BLOCK_HEIGHT {
res.push(BlockRarity::Block286);
}
}

if is_palindrome(&sat.n()) {
let s = &sat.n().to_string();
if is_palindrome(s) {
res.push(BlockRarity::Palindrome);
if is_perfect_palindrome(s) {
res.push(BlockRarity::PerfectPalinception);
}
if is_uniform_palindrome(s) {
res.push(BlockRarity::UniformPalinception);
}
}

if sat.n() % COIN_VALUE == 0 {
Expand All @@ -91,6 +111,12 @@ impl FromStr for BlockRarity {
"block9" => Ok(Self::Block9),
"block9_450" => Ok(Self::Block9_450),
"block78" => Ok(Self::Block78),
"alpha" => Ok(Self::Alpha),
"omega" => Ok(Self::Omega),
"uniform_palinception" => Ok(Self::UniformPalinception),
"perfect_palinception" => Ok(Self::PerfectPalinception),
"block286" => Ok(Self::Block286),
"jpeg" => Ok(Self::JPEG),
_ => Err(anyhow!("invalid rarity: {s}")),
}
}
Expand All @@ -114,8 +140,7 @@ impl<'de> Deserialize<'de> for BlockRarity {
}
}

pub(crate) fn is_palindrome(n: &u64) -> bool {
let s = n.to_string();
pub(crate) fn is_palindrome(s: &str) -> bool {
if s.chars().next() != s.chars().last() {
return false;
}
Expand All @@ -142,14 +167,92 @@ fn is_pizza_sat(sat: &Sat) -> bool {
false
}

fn split_palindrome_evenly(s: &str, n: usize) -> Result<Vec<&str>, &'static str> {
if s.len() / n == 1 || s.len() % n != 0 {
return Err("Cannot split palindrome evenly");
}
let len = s.len();
let mut start = 0;
let mut vec = Vec::new();
// for palindrom, we only need the 1st half of substrings.
while start < len / 2 {
vec.push(&s[start..start + n]);
start = start + n;
}
Ok(vec)
}

pub fn is_perfect_palindrome(palindrome: &str) -> bool {
// palindrome length <= 16 digits
for n in (2..=8).rev() {
match split_palindrome_evenly(palindrome, n) {
Ok(res) => {
let mut satisfied = true;
let first_sub_sequence = res[0];
if !is_palindrome(first_sub_sequence) {
continue;
}
for s in &res[1..] {
if s != &first_sub_sequence {
satisfied = false;
break;
}
}
if satisfied {
return true;
}
}
Err(_) => continue,
}
}
false
}

pub fn is_uniform_palindrome(palindrome: &str) -> bool {
// palindrome length <= 16 digits
for n in (2..=8).rev() {
match split_palindrome_evenly(palindrome, n) {
Ok(res) => {
let mut satisfied = true;
for s in res {
if !is_palindrome(s) {
satisfied = false;
break;
}
}
if satisfied {
return true;
}
}
Err(_) => continue,
}
}
false
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_is_palindrome() {
assert!(is_palindrome(&164114646411461u64));
assert!(!is_palindrome(&164114646411462u64));
assert!(is_palindrome("164114646411461"));
assert!(!is_palindrome("164114646411462"));
}

#[test]
fn test_is_perfect_palindrome() {
assert!(is_perfect_palindrome("531355313553135"));
assert!(is_perfect_palindrome("76858677685867"));
assert!(!is_perfect_palindrome("400041111140004"));
assert!(!is_perfect_palindrome("787727878727787"));
}

#[test]
fn test_is_uniform_palindrome() {
assert!(is_uniform_palindrome("400041111140004"));
assert!(is_uniform_palindrome("787727878727787"));
assert!(!is_uniform_palindrome("164114646411461"));
}

#[test]
Expand All @@ -165,7 +268,11 @@ mod tests {
assert_eq!(Sat(1000).block_rarities(), [BlockRarity::Vintage]);
assert_eq!(
Sat(1430418430854).block_rarities(),
[BlockRarity::Vintage, BlockRarity::Nakamoto]
[
BlockRarity::Vintage,
BlockRarity::Nakamoto,
BlockRarity::Block286
]
);
assert_eq!(
Sat(45017789073).block_rarities(),
Expand Down Expand Up @@ -251,10 +358,14 @@ pub const MAX_PIZZA_BLOCK_HEIGHT: u32 = 56788;
pub const VINTAGE_BLOCK_HEIGHT: u32 = 1000;
pub const BLOCK9_BLOCK_HEIGHT: u32 = 9;
pub const BLOCK78_BLOCK_HEIGHT: u32 = 78;
pub const BLOCK286_BLOCK_HEIGHT: u32 = 286;
pub const NAKAMOTO_BLOCK_HEIGHTS: [u32; 19] = [
9, 286, 688, 877, 1760, 2459, 2485, 3479, 5326, 9443, 9925, 10645, 14450, 15625, 15817, 19093,
23014, 28593, 29097,
];
pub const JPEG_BLOCK_HEIGHTS: [u32; 10] = [
30340, 30367, 30412, 30441, 30779, 30907, 31511, 32343, 32412, 32952,
]; // https://mempool.space/tx/298a46fdf18f2096f822577b9661232d4cefba084925eb746939723647f8d18d
pub const FIRST_TRANSACTION_SAT_RANGE: (u64, u64) = (45000000000, 46000000000);
pub const BLOCK9_450_SAT_RANGE: (u64, u64) = (45000000000, 45100000000);

Expand Down
Loading

0 comments on commit 484ff3f

Please sign in to comment.