feat(core): patience diff for merges (not yet used)
This commit is contained in:
parent
0de72adc10
commit
31ac540c1a
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
||||||
.#*
|
.#*
|
||||||
|
*.snap.new
|
||||||
/target
|
/target
|
||||||
result
|
result
|
||||||
result-*
|
result-*
|
||||||
|
|
51
Cargo.lock
generated
51
Cargo.lock
generated
|
@ -73,6 +73,8 @@ dependencies = [
|
||||||
"cap-std",
|
"cap-std",
|
||||||
"cap-tempfile",
|
"cap-tempfile",
|
||||||
"fs2",
|
"fs2",
|
||||||
|
"insta",
|
||||||
|
"serde",
|
||||||
"tracing",
|
"tracing",
|
||||||
"yzb64",
|
"yzb64",
|
||||||
"zstd",
|
"zstd",
|
||||||
|
@ -346,6 +348,20 @@ dependencies = [
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "insta"
|
||||||
|
version = "1.21.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "581d4e3314cae4536e5d22ffd23189d4a374696c5ef733eadafae0ed273fd303"
|
||||||
|
dependencies = [
|
||||||
|
"console",
|
||||||
|
"lazy_static",
|
||||||
|
"linked-hash-map",
|
||||||
|
"serde",
|
||||||
|
"similar",
|
||||||
|
"yaml-rust",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "int-enum"
|
name = "int-enum"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -418,6 +434,12 @@ version = "0.2.135"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
|
checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked-hash-map"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.0.46"
|
version = "0.0.46"
|
||||||
|
@ -562,6 +584,26 @@ name = "serde"
|
||||||
version = "1.0.145"
|
version = "1.0.145"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
|
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.145"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "similar"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
|
@ -790,6 +832,15 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yaml-rust"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||||
|
dependencies = [
|
||||||
|
"linked-hash-map",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yzb64"
|
name = "yzb64"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
@ -11,3 +11,13 @@ fs2 = "0.4"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
yzb64 = "0.1"
|
yzb64 = "0.1"
|
||||||
zstd = "0.11"
|
zstd = "0.11"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
|
||||||
|
[dev-dependencies.serde]
|
||||||
|
version = "1.0"
|
||||||
|
features = ["derive"]
|
||||||
|
|
||||||
|
[dev-dependencies.insta]
|
||||||
|
version = "1.21"
|
||||||
|
features = ["json"]
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
use cap_std::fs::Dir;
|
use cap_std::fs::Dir;
|
||||||
use std::io::{Error as IoError, ErrorKind as IoEk, Read, Result as IoResult, Write};
|
use std::io::{Error as IoError, ErrorKind as IoEk, Read, Result as IoResult, Write};
|
||||||
|
|
||||||
mod traits;
|
|
||||||
pub use traits::{Event, FlowData};
|
|
||||||
|
|
||||||
mod lock;
|
|
||||||
use lock::RepoLock;
|
|
||||||
|
|
||||||
mod changelist;
|
mod changelist;
|
||||||
pub use changelist::ChangeList;
|
pub use changelist::ChangeList;
|
||||||
|
|
||||||
|
mod lock;
|
||||||
|
use lock::RepoLock;
|
||||||
|
|
||||||
|
mod patience;
|
||||||
|
pub use patience::{patience_diff, DiffBlock};
|
||||||
|
|
||||||
mod thin_snapshot;
|
mod thin_snapshot;
|
||||||
pub use thin_snapshot::ThinSnapshot;
|
pub use thin_snapshot::ThinSnapshot;
|
||||||
|
|
||||||
|
mod traits;
|
||||||
|
pub use traits::{Event, FlowData};
|
||||||
|
|
||||||
pub struct Repository(pub Dir);
|
pub struct Repository(pub Dir);
|
||||||
|
|
||||||
impl Repository {
|
impl Repository {
|
||||||
|
|
255
crates/byr-core/src/patience.rs
Normal file
255
crates/byr-core/src/patience.rs
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
use core::clone::Clone;
|
||||||
|
use core::cmp::{Eq, Ord};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
/// handle shared prefixes and suffixes
|
||||||
|
/// algorithmic complexity: `O(min(|lhs|, |rhs|))`
|
||||||
|
fn handle_common<'i, Item: PartialEq>(
|
||||||
|
mut lhs: &'i [Item],
|
||||||
|
mut rhs: &'i [Item],
|
||||||
|
) -> (&'i [Item], &'i [Item], &'i [Item], &'i [Item]) {
|
||||||
|
let cpfx: usize = lhs
|
||||||
|
.iter()
|
||||||
|
.zip(rhs.iter())
|
||||||
|
.take_while(|(i, j)| i == j)
|
||||||
|
.count();
|
||||||
|
|
||||||
|
let head = if cpfx != 0 {
|
||||||
|
let (lhs_comm, lhs_rest) = lhs.split_at(cpfx);
|
||||||
|
lhs = lhs_rest;
|
||||||
|
rhs = &rhs[cpfx..];
|
||||||
|
lhs_comm
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
};
|
||||||
|
|
||||||
|
let csfx: usize = lhs
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.zip(rhs.iter().rev())
|
||||||
|
.take_while(|(i, j)| i == j)
|
||||||
|
.count();
|
||||||
|
|
||||||
|
let tail = if csfx != 0 {
|
||||||
|
let (lhs_rest, lhs_comm) = lhs.split_at(lhs.len() - csfx);
|
||||||
|
lhs = lhs_rest;
|
||||||
|
rhs = &rhs[..rhs.len() - csfx];
|
||||||
|
lhs_comm
|
||||||
|
} else {
|
||||||
|
&[]
|
||||||
|
};
|
||||||
|
|
||||||
|
(head, lhs, rhs, tail)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct DualPos {
|
||||||
|
lpos: usize,
|
||||||
|
rpos: usize,
|
||||||
|
}
|
||||||
|
impl DualPos {
|
||||||
|
// this keeps track of the current position,
|
||||||
|
// to mark any segments where the position jumps backwards
|
||||||
|
fn apply(&mut self, lpos: usize, rpos: usize) -> bool {
|
||||||
|
if lpos >= self.lpos && rpos >= self.rpos {
|
||||||
|
self.lpos = lpos;
|
||||||
|
self.rpos = rpos;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[cfg_attr(test, derive(serde::Serialize))]
|
||||||
|
pub enum DiffBlock<T> {
|
||||||
|
Common(T),
|
||||||
|
Diverging(T, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// patience diff algorithm
|
||||||
|
///
|
||||||
|
/// in some descriptions the "handling of shared prefixes and suffixes" isn't
|
||||||
|
/// mentioned, but in this case it is vitally important,
|
||||||
|
/// because such scanning usually manages to reduce the working set massively
|
||||||
|
/// and is relatively cheap with complexity O(`min(|lhs|, |rhs|)`). Let `L = |lhs|; R = |rhs|`.
|
||||||
|
///
|
||||||
|
/// overall time complexity: O(`L + R + min(L, R) * log min(L, R) `)
|
||||||
|
///
|
||||||
|
/// overall memory complexity: O(`L + R + min(L, R)`)
|
||||||
|
///
|
||||||
|
/// developed according to the ideas outlined in
|
||||||
|
/// * https://bramcohen.livejournal.com/73318.html by Bram Cohen
|
||||||
|
/// * https://alfedenzo.livejournal.com/170301.html
|
||||||
|
pub fn patience_diff<'i, Item>(lhs: &'i [Item], rhs: &'i [Item]) -> Vec<DiffBlock<&'i [Item]>>
|
||||||
|
where
|
||||||
|
Item: Eq + Ord,
|
||||||
|
{
|
||||||
|
let mut ret = Vec::new();
|
||||||
|
let (head, lhs, rhs, tail) = handle_common(lhs, rhs);
|
||||||
|
|
||||||
|
if !head.is_empty() {
|
||||||
|
ret.push(DiffBlock::Common(head));
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate list of unique items present in both lists
|
||||||
|
let mut comm_uniq: Vec<(usize, usize)> = {
|
||||||
|
let mut xs = BTreeMap::<&Item, (Vec<usize>, Vec<usize>)>::new();
|
||||||
|
for (n, i) in lhs.iter().enumerate() {
|
||||||
|
xs.entry(i).or_default().0.push(n);
|
||||||
|
}
|
||||||
|
for (n, i) in rhs.iter().enumerate() {
|
||||||
|
xs.entry(i).or_default().1.push(n);
|
||||||
|
}
|
||||||
|
xs.into_iter()
|
||||||
|
.flat_map(|(_, v)| match (&v.0[..], &v.1[..]) {
|
||||||
|
([x], [y]) => Some((*x, *y)),
|
||||||
|
_ => None,
|
||||||
|
}).collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// now eliminate crossover's
|
||||||
|
// NOTE: replace take.filter.collect by drain_filter once stable
|
||||||
|
{
|
||||||
|
comm_uniq.sort_unstable_by_key(|i| i.0);
|
||||||
|
let mut fav = DualPos::default();
|
||||||
|
comm_uniq = core::mem::take(&mut comm_uniq)
|
||||||
|
.into_iter()
|
||||||
|
.filter(|&(x, y)| fav.apply(x, y))
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
comm_uniq.sort_unstable_by_key(|i| i.1);
|
||||||
|
let mut fav = DualPos::default();
|
||||||
|
comm_uniq = core::mem::take(&mut comm_uniq)
|
||||||
|
.into_iter()
|
||||||
|
.filter(|&(x, y)| fav.apply(x, y))
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// collate common unique items present in rows
|
||||||
|
// also relatively efficient because we already know the unique indices
|
||||||
|
// (lhs_start, rhs_start, length)
|
||||||
|
let mut comm_uniq_it = comm_uniq.into_iter();
|
||||||
|
let comm_uniq_coll: Vec<(usize, usize, usize)> = if let Some((x, y)) = comm_uniq_it.next() {
|
||||||
|
let mut comm_uniq_coll = vec![(x, y, 1)];
|
||||||
|
for (x, y) in comm_uniq_it {
|
||||||
|
let l = comm_uniq_coll.last_mut().unwrap();
|
||||||
|
if x == l.0 + l.2 && y == l.1 + l.2 {
|
||||||
|
l.2 += 1;
|
||||||
|
} else {
|
||||||
|
comm_uniq_coll.push((x, y, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
comm_uniq_coll
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
// we are left with the actually matching unique parts, and random stuff inbetween
|
||||||
|
let (mut lpos, mut rpos) = (0, 0);
|
||||||
|
for i in comm_uniq_coll {
|
||||||
|
let (lhs_part, rhs_part) = (&lhs[lpos..i.0 + i.2], &rhs[rpos..i.1 + i.2]);
|
||||||
|
assert!(!(lhs_part.is_empty() && rhs_part.is_empty()));
|
||||||
|
let (lead, lhs_div, rhs_div, post) = handle_common(lhs_part, rhs_part);
|
||||||
|
if !lead.is_empty() {
|
||||||
|
ret.push(DiffBlock::Common(lead));
|
||||||
|
}
|
||||||
|
if !lhs_div.is_empty() || !rhs_div.is_empty() {
|
||||||
|
ret.push(DiffBlock::Diverging(lhs_div, rhs_div));
|
||||||
|
}
|
||||||
|
if !post.is_empty() {
|
||||||
|
ret.push(DiffBlock::Common(post));
|
||||||
|
}
|
||||||
|
lpos = i.0 + i.2;
|
||||||
|
rpos = i.1 + i.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle remaining stuff
|
||||||
|
let (lhs_part, rhs_part) = (&lhs[lpos..], &rhs[rpos..]);
|
||||||
|
if !(lhs_part.is_empty() && rhs_part.is_empty()) {
|
||||||
|
ret.push(DiffBlock::Diverging(lhs_part, rhs_part));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tail.is_empty() {
|
||||||
|
ret.push(DiffBlock::Common(tail));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::patience_diff;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple() {
|
||||||
|
insta::assert_compact_json_snapshot!(patience_diff(b"ABCDEF", b"ABGGGE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// example taken from: https://alfedenzo.livejournal.com/170301.html
|
||||||
|
fn complex_alfed() {
|
||||||
|
let a = r#"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// Frobs foo heartily
|
||||||
|
int frobnitz(int foo)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
printf("Your answer is: ");
|
||||||
|
printf("%d\n", foo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fact(int n)
|
||||||
|
{
|
||||||
|
if(n > 1)
|
||||||
|
{
|
||||||
|
return fact(n-1) * n;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
frobnitz(fact(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let b = r#"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int fib(int n)
|
||||||
|
{
|
||||||
|
if(n > 2)
|
||||||
|
{
|
||||||
|
return fib(n-1) + fib(n-2);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frobs foo heartily
|
||||||
|
int frobnitz(int foo)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
printf("%d\n", foo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
frobnitz(fib(10));
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
insta::assert_compact_json_snapshot!(patience_diff(&a.chars().collect::<Vec<_>>(), &b.chars().collect::<Vec<_>>()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,546 @@
|
||||||
|
---
|
||||||
|
source: crates/byr-core/src/patience.rs
|
||||||
|
expression: "patience_diff(&a.chars().collect::<Vec<_>>(), &b.chars().collect::<Vec<_>>())"
|
||||||
|
---
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
"\n",
|
||||||
|
"#",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"c",
|
||||||
|
"l",
|
||||||
|
"u",
|
||||||
|
"d",
|
||||||
|
"e",
|
||||||
|
" ",
|
||||||
|
"<",
|
||||||
|
"s",
|
||||||
|
"t",
|
||||||
|
"d",
|
||||||
|
"i",
|
||||||
|
"o",
|
||||||
|
".",
|
||||||
|
"h",
|
||||||
|
">",
|
||||||
|
"\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Diverging": [
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"i",
|
||||||
|
"b",
|
||||||
|
"(",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
" ",
|
||||||
|
"n",
|
||||||
|
")",
|
||||||
|
"\n",
|
||||||
|
"{",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"i",
|
||||||
|
"f",
|
||||||
|
"(",
|
||||||
|
"n",
|
||||||
|
" ",
|
||||||
|
">",
|
||||||
|
" ",
|
||||||
|
"2",
|
||||||
|
")",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"{",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"r",
|
||||||
|
"e",
|
||||||
|
"t",
|
||||||
|
"u",
|
||||||
|
"r",
|
||||||
|
"n",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"i",
|
||||||
|
"b",
|
||||||
|
"(",
|
||||||
|
"n",
|
||||||
|
"-",
|
||||||
|
"1",
|
||||||
|
")",
|
||||||
|
" ",
|
||||||
|
"+",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"i",
|
||||||
|
"b",
|
||||||
|
"(",
|
||||||
|
"n",
|
||||||
|
"-",
|
||||||
|
"2",
|
||||||
|
")",
|
||||||
|
";",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"}",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"r",
|
||||||
|
"e",
|
||||||
|
"t",
|
||||||
|
"u",
|
||||||
|
"r",
|
||||||
|
"n",
|
||||||
|
" ",
|
||||||
|
"1",
|
||||||
|
";",
|
||||||
|
"\n",
|
||||||
|
"}",
|
||||||
|
"\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
"/",
|
||||||
|
"/",
|
||||||
|
" ",
|
||||||
|
"F"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
"r",
|
||||||
|
"o",
|
||||||
|
"b",
|
||||||
|
"s",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"o",
|
||||||
|
"o",
|
||||||
|
" ",
|
||||||
|
"h",
|
||||||
|
"e",
|
||||||
|
"a",
|
||||||
|
"r",
|
||||||
|
"t",
|
||||||
|
"i",
|
||||||
|
"l",
|
||||||
|
"y"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
"\n",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"r",
|
||||||
|
"o",
|
||||||
|
"b",
|
||||||
|
"n",
|
||||||
|
"i",
|
||||||
|
"t",
|
||||||
|
"z",
|
||||||
|
"(",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"o",
|
||||||
|
"o",
|
||||||
|
")",
|
||||||
|
"\n",
|
||||||
|
"{",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
" ",
|
||||||
|
"i",
|
||||||
|
";",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"o",
|
||||||
|
"r",
|
||||||
|
"(",
|
||||||
|
"i",
|
||||||
|
" ",
|
||||||
|
"="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
" ",
|
||||||
|
"0",
|
||||||
|
";",
|
||||||
|
" ",
|
||||||
|
"i",
|
||||||
|
" ",
|
||||||
|
"<"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
" ",
|
||||||
|
"1",
|
||||||
|
"0",
|
||||||
|
";",
|
||||||
|
" ",
|
||||||
|
"i",
|
||||||
|
"+",
|
||||||
|
"+",
|
||||||
|
")",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"{",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"p",
|
||||||
|
"r",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
"f",
|
||||||
|
"(",
|
||||||
|
"\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Diverging": [
|
||||||
|
[
|
||||||
|
"Y",
|
||||||
|
"o",
|
||||||
|
"u",
|
||||||
|
"r",
|
||||||
|
" ",
|
||||||
|
"a",
|
||||||
|
"n",
|
||||||
|
"s",
|
||||||
|
"w",
|
||||||
|
"e",
|
||||||
|
"r",
|
||||||
|
" ",
|
||||||
|
"i",
|
||||||
|
"s",
|
||||||
|
":",
|
||||||
|
" ",
|
||||||
|
"\"",
|
||||||
|
")",
|
||||||
|
";",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"p",
|
||||||
|
"r",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
"f",
|
||||||
|
"(",
|
||||||
|
"\""
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
"%",
|
||||||
|
"d",
|
||||||
|
"\\"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
"n",
|
||||||
|
"\"",
|
||||||
|
",",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"o",
|
||||||
|
"o",
|
||||||
|
")",
|
||||||
|
";",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"}",
|
||||||
|
"\n",
|
||||||
|
"}",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Diverging": [
|
||||||
|
[
|
||||||
|
"f",
|
||||||
|
"a",
|
||||||
|
"c",
|
||||||
|
"t",
|
||||||
|
"(",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
" ",
|
||||||
|
"n",
|
||||||
|
")",
|
||||||
|
"\n",
|
||||||
|
"{",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"i",
|
||||||
|
"f",
|
||||||
|
"(",
|
||||||
|
"n",
|
||||||
|
" ",
|
||||||
|
">",
|
||||||
|
" ",
|
||||||
|
"1",
|
||||||
|
")",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"{",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"r",
|
||||||
|
"e",
|
||||||
|
"t",
|
||||||
|
"u",
|
||||||
|
"r",
|
||||||
|
"n",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"a",
|
||||||
|
"c",
|
||||||
|
"t",
|
||||||
|
"(",
|
||||||
|
"n",
|
||||||
|
"-",
|
||||||
|
"1",
|
||||||
|
")",
|
||||||
|
" ",
|
||||||
|
"*",
|
||||||
|
" ",
|
||||||
|
"n",
|
||||||
|
";",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"}",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"r",
|
||||||
|
"e",
|
||||||
|
"t",
|
||||||
|
"u",
|
||||||
|
"r",
|
||||||
|
"n",
|
||||||
|
" ",
|
||||||
|
"1",
|
||||||
|
";",
|
||||||
|
"\n",
|
||||||
|
"}",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
" "
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
"m"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
"a",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"(",
|
||||||
|
"i",
|
||||||
|
"n",
|
||||||
|
"t",
|
||||||
|
" ",
|
||||||
|
"a",
|
||||||
|
"r",
|
||||||
|
"g",
|
||||||
|
"c",
|
||||||
|
",",
|
||||||
|
" ",
|
||||||
|
"c",
|
||||||
|
"h",
|
||||||
|
"a",
|
||||||
|
"r",
|
||||||
|
" ",
|
||||||
|
"*",
|
||||||
|
"*",
|
||||||
|
"a",
|
||||||
|
"r",
|
||||||
|
"g",
|
||||||
|
"v"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Diverging": [
|
||||||
|
[
|
||||||
|
")",
|
||||||
|
"\n",
|
||||||
|
"{",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"r",
|
||||||
|
"o",
|
||||||
|
"b",
|
||||||
|
"n",
|
||||||
|
"i",
|
||||||
|
"t",
|
||||||
|
"z",
|
||||||
|
"(",
|
||||||
|
"f",
|
||||||
|
"a",
|
||||||
|
"c",
|
||||||
|
"t",
|
||||||
|
"(",
|
||||||
|
"1",
|
||||||
|
"0",
|
||||||
|
")",
|
||||||
|
")",
|
||||||
|
";",
|
||||||
|
"\n",
|
||||||
|
"}",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"}"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
")",
|
||||||
|
"\n",
|
||||||
|
"{",
|
||||||
|
"\n",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
"f",
|
||||||
|
"r",
|
||||||
|
"o",
|
||||||
|
"b",
|
||||||
|
"n",
|
||||||
|
"i",
|
||||||
|
"t",
|
||||||
|
"z",
|
||||||
|
"(",
|
||||||
|
"f",
|
||||||
|
"i",
|
||||||
|
"b",
|
||||||
|
"(",
|
||||||
|
"1",
|
||||||
|
"0",
|
||||||
|
")",
|
||||||
|
")",
|
||||||
|
";"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Common": [
|
||||||
|
"\n",
|
||||||
|
"}",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
source: crates/byr-core/src/patience.rs
|
||||||
|
expression: "patience_diff(b\"ABCDEF\", b\"ABGGGE\")"
|
||||||
|
---
|
||||||
|
[{"Common": [65, 66]}, {"Diverging": [[67, 68], [71, 71, 71]]}, {"Common": [69]}, {"Diverging": [[70], []]}]
|
Loading…
Reference in a new issue