Fix bug and minor improvements
This commit is contained in:
parent
c3cfbcbada
commit
da4f06a825
7 changed files with 48 additions and 17 deletions
|
|
@ -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"] }
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
dbadcabbcbaccbabadbb
|
dbaccabbcbacccabadbb
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
acdccadadcbadcdbdaaadacbcdcacbbdcdabbbbddbcbccdbabccccdbbacccdccccacaaddcabaaabbbadacbbddaccccbcccbb
|
acdccadbddbadcdbdaaadacbcccacbbdcdabbbbddbcbccdbabccacdbbacccdccccccaaadcabaaabbaadacbbddbacbcbcccbb
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
cdbdbdbababcdaacbabbdadccdbdcdaacdbaacccddcdbbacadcbcacddcddacdaddcbbacbbddcccdcdbcbacccbabbcbbbaaaa
|
cdbdbdbdaabcdaaadabbdadccdbdcdaacdbaaaccddcdbbacadabcacddcddaddadddbbacbaddcccdcdbcbbbccbabbcbbbaaaa
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
bcdcacdbbbcbbadbbbaabdadcaddcddabbdacddacaaccadcaabdcdddddadacbdcdcbccabbbabdddbacaddcaacaadacbacbdd
|
bddcacdabbcbbcdcbbaabdadbaddcddacbdadacaddabcbbcaabbcdddadadacbdcdcbaaccbbabcdabaccddcaaddadacbacbdd
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
bcdbdcdaabaacdbcddadbddcaabcabaadbbccdcbbdbbbccadcaabcbbcdbbcbbbbccacaabbdcdaccbaaaddccbcdcacdcbcacd
|
aadbdcdaabcacdbbdbccddcaaadcdbaadbcccdcbbdbbbdcadcadbcbabdbbccbdbccacabbbbcddccaaaadddbbcdcacdcbcacd
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue