Fix bug and minor improvements

This commit is contained in:
hal8174 2024-12-02 21:07:44 +01:00
parent c3cfbcbada
commit da4f06a825
7 changed files with 48 additions and 17 deletions

View file

@ -3,5 +3,8 @@ name = "closest_string"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[profile.release]
debug = true
[dependencies] [dependencies]
clap = { version = "4.5.21", features = ["derive"] } clap = { version = "4.5.21", features = ["derive"] }

View file

@ -1 +1 @@
dbadcabbcbaccbabadbb dbaccabbcbacccabadbb

View file

@ -1 +1 @@
acdccadadcbadcdbdaaadacbcdcacbbdcdabbbbddbcbccdbabccccdbbacccdccccacaaddcabaaabbbadacbbddaccccbcccbb acdccadbddbadcdbdaaadacbcccacbbdcdabbbbddbcbccdbabccacdbbacccdccccccaaadcabaaabbaadacbbddbacbcbcccbb

View file

@ -1 +1 @@
cdbdbdbababcdaacbabbdadccdbdcdaacdbaacccddcdbbacadcbcacddcddacdaddcbbacbbddcccdcdbcbacccbabbcbbbaaaa cdbdbdbdaabcdaaadabbdadccdbdcdaacdbaaaccddcdbbacadabcacddcddaddadddbbacbaddcccdcdbcbbbccbabbcbbbaaaa

View file

@ -1 +1 @@
bcdcacdbbbcbbadbbbaabdadcaddcddabbdacddacaaccadcaabdcdddddadacbdcdcbccabbbabdddbacaddcaacaadacbacbdd bddcacdabbcbbcdcbbaabdadbaddcddacbdadacaddabcbbcaabbcdddadadacbdcdcbaaccbbabcdabaccddcaaddadacbacbdd

View file

@ -1 +1 @@
bcdbdcdaabaacdbcddadbddcaabcabaadbbccdcbbdbbbccadcaabcbbcdbbcbbbbccacaabbdcdaccbaaaddccbcdcacdcbcacd aadbdcdaabcacdbbdbccddcaaadcdbaadbcccdcbbdbbbdcadcadbcbabdbbccbdbccacabbbbcddccaaaadddbbcdcacdcbcacd

View file

@ -20,27 +20,52 @@ fn calculate_hamming_distance(a: &[u8], b: &[u8]) -> usize {
fn simple<'a>( fn simple<'a>(
strings: &[Vec<u8>], strings: &[Vec<u8>],
hamming_distances: &mut [u8],
solution: &'a mut [u8], solution: &'a mut [u8],
d: usize, d: u8,
depth: usize, depth: u8,
) -> Option<&'a [u8]> { ) -> Option<&'a [u8]> {
let (s, i) = strings let (s, &i) = strings
.iter() .iter()
.map(|s| (s, calculate_hamming_distance(s, solution))) .zip(hamming_distances.iter())
.max_by_key(|(_, i)| *i) .max_by_key(|(_, &i)| i)
.unwrap(); .unwrap();
// assert_eq!(i, calculate_hamming_distance(s, solution) as u8);
if i > d + depth { if i > d + depth {
return None; return None;
} else if i <= d { } else if i <= d {
return Some(solution); return Some(solution);
} }
if depth == 0 {
return None;
}
for index in 0..s.len() { for index in 0..s.len() {
if s[index] != solution[index] { if s[index] != solution[index] {
let temp = solution[index]; let temp = solution[index];
solution[index] = s[index]; solution[index] = s[index];
simple(strings, solution, d, depth + 1)?; for j in 0..hamming_distances.len() {
if strings[j][index] == temp {
hamming_distances[j] += 1;
}
if strings[j][index] == s[index] {
hamming_distances[j] -= 1;
}
}
if simple(strings, hamming_distances, solution, d, depth - 1).is_some() {
return Some(solution);
}
for j in 0..hamming_distances.len() {
if strings[j][index] == temp {
hamming_distances[j] -= 1;
}
if strings[j][index] == s[index] {
hamming_distances[j] += 1;
}
}
solution[index] = temp; solution[index] = temp;
} }
} }
@ -48,12 +73,15 @@ fn simple<'a>(
None None
} }
fn closest_string(strings: &[Vec<u8>], d: usize, method: Method) -> Option<Vec<u8>> { fn closest_string(strings: &[Vec<u8>], d: u8, method: Method) -> Option<Vec<u8>> {
match method { match method {
Method::Simple => { Method::Simple => {
let mut s = strings[0].clone(); let mut s = strings[0].clone();
let mut hamming_distances = strings
if simple(strings, &mut s, d, 0).is_some() { .iter()
.map(|l| calculate_hamming_distance(&s, l) as u8)
.collect::<Vec<_>>();
if simple(strings, &mut hamming_distances, &mut s, d, d).is_some() {
Some(s) Some(s)
} else { } else {
None None
@ -70,7 +98,7 @@ enum Method {
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
struct Args { struct Args {
filename: PathBuf, filename: PathBuf,
d: Option<usize>, d: Option<u8>,
#[clap(default_value = "simple")] #[clap(default_value = "simple")]
method: Method, method: Method,
#[clap(short, long)] #[clap(short, long)]
@ -89,14 +117,14 @@ fn main() {
eprintln!("{}: {:?}", d, start.elapsed()); eprintln!("{}: {:?}", d, start.elapsed());
r r
} else if args.reverse { } else if args.reverse {
let mut d = strings.len(); let mut d = strings.len() as u8;
let mut last_solution = None; let mut last_solution = None;
loop { loop {
let start = std::time::Instant::now(); let start = std::time::Instant::now();
let r = closest_string(&strings, d, args.method); let r = closest_string(&strings, d, args.method);
eprintln!("{}: {:?}", d, start.elapsed()); eprintln!("{}: {:?}", d, start.elapsed());
if let Some(r) = r { if let Some(r) = r {
d = r.len() - 1; d = r.len() as u8 - 1;
last_solution = Some(r); last_solution = Some(r);
} else { } else {
break last_solution; break last_solution;