Requires a complex N->1 mapping.

This mapping is unfinished: 14 of 573 nodes are still unmarked.

Code view:

A painting is a person's account of this edit as text, recorded independently of the node mapping - a rendering often has several equally defensible answers where the mapping has one. Deletions and insertions carry no position on the opposite side in a painting, so that panel draws no caret for them.

Before

1use std::collections::HashMap;
2
3struct SubtreeKey {
4 subtrees: Vec<usize>,
5}
6
7impl SubtreeKey {
8 fn new(subtrees: &[usize]) -> Self {
9 SubtreeKey {
10 subtrees: subtrees.to_vec(),
11 }
12 }
13}
14
15fn main() {
16 let mut memoo: HashMap<(Vec<usize>, Vec<usize>), u64> = HashMap::new();
17 let before_subtrees = vec![1, 2, 3];
18 let after_subtrees = vec![4, 5, 6];
19
20 let key = (before_subtrees.clone(), after_subtrees.clone());
21 memoo.insert(key, 42);
22}

After

1use std::collections::HashMap;
2use std::hash::{Hash, Hasher};
3
4#[derive(Debug, Clone, Eq, PartialEq)]
5struct SubtreeKey {
6 hash: u64,
7 len: usize,
8 subtrees: Vec<usize>,
9}
10
11impl Hash for SubtreeKey {
12 fn hash<H: Hasher>(&self, state: &mut H) {
13 self.hash.hash(state);
14 self.len.hash(state);
15 }
16}
17
18impl SubtreeKey {
19 fn new(subtrees: &[usize]) -> Self {
20 let mut hasher = std::collections::hash_map::DefaultHasher::new();
21 for &id in subtrees {
22 id.hash(&mut hasher);
23 }
24 SubtreeKey {
25 hash: hasher.finish(),
26 len: subtrees.len(),
27 subtrees: subtrees.to_vec(),
28 }
29 }
30}
31
32fn main() {
33 let mut memoo: HashMap<(SubtreeKey, SubtreeKey), u64> = HashMap::new();
34 let before_subtrees = vec![1, 2, 3];
35 let after_subtrees = vec![4, 5, 6];
36
37 let before_key = SubtreeKey::new(&before_subtrees);
38 let after_key = SubtreeKey::new(&after_subtrees);
39 let key = (before_key.clone(), after_key.clone());
40 memoo.insert(key, 42);
41}

Before

source_file
use_declaration
use "use"
scoped_identifier
scoped_identifier
identifier "std"
:: "::"
identifier "collections"
:: "::"
identifier "HashMap"
; ";"
struct_item
struct "struct"
type_identifier "SubtreeKey"
field_declaration_list
{ "{"
field_declaration
field_identifier "subtrees"
: ":"
generic_type
type_identifier "Vec"
type_arguments
< "<"
primitive_type "usize"
> ">"
, ","
} "}"
impl_item
impl "impl"
type_identifier "SubtreeKey"
declaration_list
{ "{"
function_item
fn "fn"
identifier "new"
parameters
( "("
parameter
identifier "subtrees"
: ":"
reference_type
& "&"
array_type
[ "["
primitive_type "usize"
] "]"
) ")"
-> "->"
type_identifier "Self"
block
{ "{"
struct_expression
type_identifier "SubtreeKey"
field_initializer_list
{ "{"
field_initializer
field_identifier "subtrees"
: ":"
call_expression
field_expression
identifier "subtrees"
. "."
field_identifier "to_vec"
arguments
( "("
) ")"
, ","
} "}"
} "}"
} "}"
function_item
fn "fn"
identifier "main"
parameters
( "("
) ")"
block
{ "{"
let_declaration
let "let"
mutable_specifier "mut"
identifier "memoo"
: ":"
generic_type
type_identifier "HashMap"
type_arguments
< "<"
tuple_type
( "("
generic_type
type_identifier "Vec"
type_arguments
< "<"
primitive_type "usize"
> ">"
, ","
generic_type
type_identifier "Vec"
type_arguments
< "<"
primitive_type "usize"
> ">"
) ")"
, ","
primitive_type "u64"
> ">"
= "="
call_expression
scoped_identifier
identifier "HashMap"
:: "::"
identifier "new"
arguments
( "("
) ")"
; ";"
let_declaration
let "let"
identifier "before_subtrees"
= "="
macro_invocation
identifier "vec"
! "!"
token_tree
[ "["
integer_literal "1"
, ","
integer_literal "2"
, ","
integer_literal "3"
] "]"
; ";"
let_declaration
let "let"
identifier "after_subtrees"
= "="
macro_invocation
identifier "vec"
! "!"
token_tree
[ "["
integer_literal "4"
, ","
integer_literal "5"
, ","
integer_literal "6"
] "]"
; ";"
let_declaration
let "let"
identifier "key"
= "="
tuple_expression
( "("
call_expression
field_expression
identifier "before_subtrees"
. "."
field_identifier "clone"
arguments
( "("
) ")"
, ","
call_expression
field_expression
identifier "after_subtrees"
. "."
field_identifier "clone"
arguments
( "("
) ")"
) ")"
; ";"
expression_statement
call_expression
field_expression
identifier "memoo"
. "."
field_identifier "insert"
arguments
( "("
identifier "key"
, ","
integer_literal "42"
) ")"
; ";"
} "}"

After

source_file
use_declaration
use "use"
scoped_identifier
scoped_identifier
identifier "std"
:: "::"
identifier "collections"
:: "::"
identifier "HashMap"
; ";"
use_declaration
use "use"
scoped_use_list
scoped_identifier
identifier "std"
:: "::"
identifier "hash"
:: "::"
use_list
{ "{"
identifier "Hash"
, ","
identifier "Hasher"
} "}"
; ";"
attribute_item
# "#"
[ "["
attribute
identifier "derive"
token_tree
( "("
identifier "Debug"
, ","
identifier "Clone"
, ","
identifier "Eq"
, ","
identifier "PartialEq"
) ")"
] "]"
struct_item
struct "struct"
type_identifier "SubtreeKey"
field_declaration_list
{ "{"
field_declaration
field_identifier "hash"
: ":"
primitive_type "u64"
, ","
field_declaration
field_identifier "len"
: ":"
primitive_type "usize"
, ","
field_declaration
field_identifier "subtrees"
: ":"
generic_type
type_identifier "Vec"
type_arguments
< "<"
primitive_type "usize"
> ">"
, ","
} "}"
impl_item
impl "impl"
type_identifier "Hash"
for "for"
type_identifier "SubtreeKey"
declaration_list
{ "{"
function_item
fn "fn"
identifier "hash"
type_parameters
< "<"
type_parameter
type_identifier "H"
trait_bounds
: ":"
type_identifier "Hasher"
> ">"
parameters
( "("
self_parameter
& "&"
self "self"
, ","
parameter
identifier "state"
: ":"
reference_type
& "&"
mutable_specifier "mut"
type_identifier "H"
) ")"
block
{ "{"
expression_statement
call_expression
field_expression
field_expression
self "self"
. "."
field_identifier "hash"
. "."
field_identifier "hash"
arguments
( "("
identifier "state"
) ")"
; ";"
expression_statement
call_expression
field_expression
field_expression
self "self"
. "."
field_identifier "len"
. "."
field_identifier "hash"
arguments
( "("
identifier "state"
) ")"
; ";"
} "}"
} "}"
impl_item
impl "impl"
type_identifier "SubtreeKey"
declaration_list
{ "{"
function_item
fn "fn"
identifier "new"
parameters
( "("
parameter
identifier "subtrees"
: ":"
reference_type
& "&"
array_type
[ "["
primitive_type "usize"
] "]"
) ")"
-> "->"
type_identifier "Self"
block
{ "{"
let_declaration
let "let"
mutable_specifier "mut"
identifier "hasher"
= "="
call_expression
scoped_identifier
scoped_identifier
scoped_identifier
scoped_identifier
identifier "std"
:: "::"
identifier "collections"
:: "::"
identifier "hash_map"
:: "::"
identifier "DefaultHasher"
:: "::"
identifier "new"
arguments
( "("
) ")"
; ";"
expression_statement
for_expression
for "for"
reference_pattern
& "&"
identifier "id"
in "in"
identifier "subtrees"
block
{ "{"
expression_statement
call_expression
field_expression
identifier "id"
. "."
field_identifier "hash"
arguments
( "("
reference_expression
& "&"
mutable_specifier "mut"
identifier "hasher"
) ")"
; ";"
} "}"
struct_expression
type_identifier "SubtreeKey"
field_initializer_list
{ "{"
field_initializer
field_identifier "hash"
: ":"
call_expression
field_expression
identifier "hasher"
. "."
field_identifier "finish"
arguments
( "("
) ")"
, ","
field_initializer
field_identifier "len"
: ":"
call_expression
field_expression
identifier "subtrees"
. "."
field_identifier "len"
arguments
( "("
) ")"
, ","
field_initializer
field_identifier "subtrees"
: ":"
call_expression
field_expression
identifier "subtrees"
. "."
field_identifier "to_vec"
arguments
( "("
) ")"
, ","
} "}"
} "}"
} "}"
function_item
fn "fn"
identifier "main"
parameters
( "("
) ")"
block
{ "{"
let_declaration
let "let"
mutable_specifier "mut"
identifier "memoo"
: ":"
generic_type
type_identifier "HashMap"
type_arguments
< "<"
tuple_type
( "("
type_identifier "SubtreeKey"
, ","
type_identifier "SubtreeKey"
) ")"
, ","
primitive_type "u64"
> ">"
= "="
call_expression
scoped_identifier
identifier "HashMap"
:: "::"
identifier "new"
arguments
( "("
) ")"
; ";"
let_declaration
let "let"
identifier "before_subtrees"
= "="
macro_invocation
identifier "vec"
! "!"
token_tree
[ "["
integer_literal "1"
, ","
integer_literal "2"
, ","
integer_literal "3"
] "]"
; ";"
let_declaration
let "let"
identifier "after_subtrees"
= "="
macro_invocation
identifier "vec"
! "!"
token_tree
[ "["
integer_literal "4"
, ","
integer_literal "5"
, ","
integer_literal "6"
] "]"
; ";"
let_declaration
let "let"
identifier "before_key"
= "="
call_expression
scoped_identifier
identifier "SubtreeKey"
:: "::"
identifier "new"
arguments
( "("
reference_expression
& "&"
identifier "before_subtrees"
) ")"
; ";"
let_declaration
let "let"
identifier "after_key"
= "="
call_expression
scoped_identifier
identifier "SubtreeKey"
:: "::"
identifier "new"
arguments
( "("
reference_expression
& "&"
identifier "after_subtrees"
) ")"
; ";"
let_declaration
let "let"
identifier "key"
= "="
tuple_expression
( "("
call_expression
field_expression
identifier "before_key"
. "."
field_identifier "clone"
arguments
( "("
) ")"
, ","
call_expression
field_expression
identifier "after_key"
. "."
field_identifier "clone"
arguments
( "("
) ")"
) ")"
; ";"
expression_statement
call_expression
field_expression
identifier "memoo"
. "."
field_identifier "insert"
arguments
( "("
identifier "key"
, ","
integer_literal "42"
) ")"
; ";"
} "}"