Skip to content

Commit

Permalink
Improve the same item count and add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
iminashi committed Jun 2, 2024
1 parent 5101208 commit 45107c7
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 28 deletions.
48 changes: 24 additions & 24 deletions src/Rocksmith2014.DD/Comparers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,26 @@ let sameChords (chords1: Chord list) (chords2: Chord list) =
(chords1, chords2)
||> List.forall2 sameChord

let private skipWhileNot eq elem list =
let rec doSkip remaining =
match remaining with
| [] ->
let private findNextMatch equal skipped1 skipped2 list1 list2 =
let rec search skipped1 skipped2 remaining1 remaining2 =
match remaining1, remaining2 with
| [], _
| _, [] ->
ValueNone
| head :: tail when not <| eq head elem ->
doSkip tail
| _ :: tail ->
ValueSome tail
| head1 :: tail1, head2 :: tail2 when equal head1 head2 ->
ValueSome (tail1, tail2)
| head1 :: tail1, head2 :: tail2 ->
match List.tryFindIndex (equal head2) skipped1 with
| Some i ->
ValueSome (List.skip i list1, tail2)
| None ->
match List.tryFindIndex (equal head1) skipped2 with
| Some j ->
ValueSome (tail1, List.skip j list2)
| None ->
search (head1 :: skipped1) (head2 :: skipped2) tail1 tail2

doSkip list
search skipped1 skipped2 list1 list2

/// Calculates the number of same items in two lists, when the order of the items matters.
let getSameItemCount (equal: 'a -> 'a -> bool) (input1: 'a list) (input2: 'a list) =
Expand All @@ -78,24 +87,15 @@ let getSameItemCount (equal: 'a -> 'a -> bool) (input1: 'a list) (input2: 'a lis
elif len1 < len2 then
getCount count len1 (len2 - 1) list1 tail2
else
// Same lengths, skip items until the next match for both lists
let newTail1 = skipWhileNot equal head2 tail1
let newTail2 = skipWhileNot equal head1 tail2

match newTail1, newTail2 with
| ValueNone, _
| _, ValueNone ->
// Skip both
getCount count (len1 - 1) (len2 - 1) tail1 tail2
| ValueSome newTail1, ValueSome newTail2 ->
// Select the new lists to use based on which skipped the least items
// Same lengths, find the next matching items, taking into account skipped items
match findNextMatch equal [head1] [head2] tail1 tail2 with
| ValueNone ->
count
| ValueSome (newTail1, newTail2) ->
let newLen1 = List.length newTail1
let newLen2 = List.length newTail2

if newLen1 >= newLen2 then
getCount (count + 1) newLen1 (len2 - 1) newTail1 tail2
else
getCount (count + 1) (len1 - 1) newLen2 tail1 newTail2
getCount (count + 1) newLen1 newLen2 newTail1 newTail2
| _ ->
count

Expand Down
143 changes: 139 additions & 4 deletions tests/Rocksmith2014.DD.Tests/ComparerTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ let comparerTests =
let notes1 = [ Note(Time = 25, String = 0y, Fret = 1y)
Note(Time = 50, String = 0y, Fret = 5y)
Note(Time = 75, String = 1y, Fret = 9y) ]

let notes2 = [ Note(Time = 125, String = 0y, Fret = 2y)
Note(Time = 175, String = 0y, Fret = 4y)
Note(Time = 200, String = 1y, Fret = 8y) ]
Expand All @@ -51,6 +52,7 @@ let comparerTests =
let notes1 = [ Note(Time = 25, String = 0y, Fret = 14y)
Note(Time = 50, String = 0y, Fret = 13y)
Note(Time = 75, String = 1y, Fret = 12y) ]

let notes2 = [ Note(Time = 125, String = 0y, Fret = 14y)
Note(Time = 175, String = 0y, Fret = 13y)
Note(Time = 200, String = 1y, Fret = 12y) ]
Expand All @@ -62,18 +64,22 @@ let comparerTests =
testCase "Correct for same chords" <| fun _ ->
let chords1 = [ Chord(Time = 125, ChordId = 50s)
Chord(Time = 225, ChordId = 25s, Mask = ChordMask.FretHandMute) ]

let chords2 = [ Chord(Time = 500, ChordId = 50s)
Chord(Time = 625, ChordId = 25s, Mask = ChordMask.FretHandMute) ]

let sameCount = getSameItemCount sameChord chords1 chords2

Expect.equal sameCount chords1.Length "Count is correct"

// [ 0 14 13 12 ]
// [ 14 13 12 ]
testCase "Correct when extra note at the beginning 1/2" <| fun _ ->
let notes1 = [ Note(Time = 15, String = 0y, Fret = 0y)
Note(Time = 25, String = 0y, Fret = 14y)
Note(Time = 50, String = 0y, Fret = 13y)
Note(Time = 75, String = 1y, Fret = 12y) ]

let notes2 = [ Note(Time = 125, String = 0y, Fret = 14y)
Note(Time = 175, String = 0y, Fret = 13y)
Note(Time = 200, String = 1y, Fret = 12y) ]
Expand All @@ -82,10 +88,13 @@ let comparerTests =

Expect.equal sameCount 3 "Count is correct"

// [ 14 13 12 ]
// [ 0 14 13 12 ]
testCase "Correct when extra note at the beginning 2/2" <| fun _ ->
let notes1 = [ Note(Time = 25, String = 0y, Fret = 14y)
Note(Time = 50, String = 0y, Fret = 13y)
Note(Time = 75, String = 1y, Fret = 12y) ]

let notes2 = [ Note(Time = 115, String = 0y, Fret = 0y)
Note(Time = 125, String = 0y, Fret = 14y)
Note(Time = 175, String = 0y, Fret = 13y)
Expand All @@ -95,11 +104,14 @@ let comparerTests =

Expect.equal sameCount 3 "Count is correct"

// [ 14 13 15 12 ]
// [ 14 13 12 ]
testCase "Correct when extra note in between 1/2" <| fun _ ->
let notes1 = [ Note(Time = 25, String = 0y, Fret = 14y)
Note(Time = 50, String = 0y, Fret = 13y)
Note(Time = 55, String = 1y, Fret = 13y)
Note(Time = 55, String = 1y, Fret = 15y)
Note(Time = 75, String = 1y, Fret = 12y) ]

let notes2 = [ Note(Time = 125, String = 0y, Fret = 14y)
Note(Time = 175, String = 0y, Fret = 13y)
Note(Time = 200, String = 1y, Fret = 12y) ]
Expand All @@ -108,39 +120,48 @@ let comparerTests =

Expect.equal sameCount 3 "Count is correct"

// [ 14 13 12 ]
// [ 14 15 13 12 ]
testCase "Correct when extra note in between 2/2" <| fun _ ->
let notes1 = [ Note(Time = 25, String = 0y, Fret = 14y)
Note(Time = 50, String = 0y, Fret = 13y)
Note(Time = 75, String = 1y, Fret = 12y) ]

let notes2 = [ Note(Time = 125, String = 0y, Fret = 14y)
Note(Time = 155, String = 1y, Fret = 13y)
Note(Time = 155, String = 1y, Fret = 15y)
Note(Time = 175, String = 0y, Fret = 13y)
Note(Time = 200, String = 1y, Fret = 12y) ]

let sameCount = getSameItemCount sameNote notes1 notes2

Expect.equal sameCount 3 "Count is correct"

// [ 14 13 12 ]
// [ 14 15 15 13 12 ]
testCase "Correct when two extra notes in between (one after the other)" <| fun _ ->
let notes1 = [ Note(Time = 25, String = 0y, Fret = 14y)
Note(Time = 50, String = 0y, Fret = 13y)
Note(Time = 75, String = 1y, Fret = 12y) ]

let notes2 = [ Note(Time = 125, String = 0y, Fret = 14y)
Note(Time = 155, String = 1y, Fret = 13y)
Note(Time = 165, String = 1y, Fret = 13y)
Note(Time = 155, String = 1y, Fret = 15y)
Note(Time = 165, String = 1y, Fret = 15y)
Note(Time = 175, String = 0y, Fret = 13y)
Note(Time = 200, String = 1y, Fret = 12y) ]

let sameCount = getSameItemCount sameNote notes1 notes2

Expect.equal sameCount 3 "Count is correct"

// [ 14 22 13 22 12 ]
// [ 14 13 12 ]
testCase "Correct when two extra notes in between (here and there)" <| fun _ ->
let notes1 = [ Note(Time = 25, String = 0y, Fret = 14y)
Note(Time = 25, String = 5y, Fret = 22y)
Note(Time = 50, String = 1y, Fret = 13y)
Note(Time = 25, String = 5y, Fret = 22y)
Note(Time = 75, String = 1y, Fret = 12y) ]

let notes2 = [ Note(Time = 125, String = 0y, Fret = 14y)
Note(Time = 155, String = 1y, Fret = 13y)
Note(Time = 200, String = 1y, Fret = 12y) ]
Expand All @@ -149,12 +170,15 @@ let comparerTests =

Expect.equal sameCount 3 "Count is correct"

// [ 0 0 14 13 12 ]
// [ 14 13 12 ]
testCase "Correct when two extra notes at the beginning" <| fun _ ->
let notes1 = [ Note(Time = 0, String = 0y, Fret = 0y)
Note(Time = 10, String = 0y, Fret = 0y)
Note(Time = 25, String = 0y, Fret = 14y)
Note(Time = 50, String = 0y, Fret = 13y)
Note(Time = 75, String = 1y, Fret = 12y) ]

let notes2 = [ Note(Time = 125, String = 0y, Fret = 14y)
Note(Time = 175, String = 0y, Fret = 13y)
Note(Time = 200, String = 1y, Fret = 12y) ]
Expand All @@ -163,11 +187,14 @@ let comparerTests =

Expect.equal sameCount 3 "Count is correct"

// [ 10 14 13 12 ]
// [ 12 14 13 12 ]
testCase "Correct when starting note is different 1/3" <| fun _ ->
let notes1 = [ Note(Time = 0, String = 0y, Fret = 10y)
Note(Time = 5, String = 0y, Fret = 14y)
Note(Time = 50, String = 0y, Fret = 13y)
Note(Time = 75, String = 1y, Fret = 12y) ]

let notes2 = [ Note(Time = 100, String = 1y, Fret = 12y)
Note(Time = 125, String = 0y, Fret = 14y)
Note(Time = 175, String = 0y, Fret = 13y)
Expand All @@ -177,12 +204,15 @@ let comparerTests =

Expect.equal sameCount 3 "Count is correct"

// [ 7 5 4 5 4 ]
// [ 5 5 4 5 4 ]
testCase "Correct when starting note is different 2/3" <| fun _ ->
let notes1 = [ Note(Time = 0, String = 1y, Fret = 7y)
Note(Time = 1, String = 0y, Fret = 5y)
Note(Time = 2, String = 0y, Fret = 4y)
Note(Time = 50, String = 0y, Fret = 5y)
Note(Time = 75, String = 0y, Fret = 4y) ]

let notes2 = [ Note(Time = 100, String = 0y, Fret = 5y)
Note(Time = 100, String = 0y, Fret = 5y)
Note(Time = 125, String = 0y, Fret = 4y)
Expand All @@ -193,12 +223,15 @@ let comparerTests =

Expect.equal sameCount 4 "Count is correct"

// [ 5 5 4 5 4 ]
// [ 7 5 4 5 4 ]
testCase "Correct when starting note is different 3/3" <| fun _ ->
let notes1 = [ Note(Time = 0, String = 0y, Fret = 5y)
Note(Time = 1, String = 0y, Fret = 5y)
Note(Time = 2, String = 0y, Fret = 4y)
Note(Time = 50, String = 0y, Fret = 5y)
Note(Time = 75, String = 0y, Fret = 4y) ]

let notes2 = [ Note(Time = 100, String = 1y, Fret = 7y)
Note(Time = 100, String = 0y, Fret = 5y)
Note(Time = 125, String = 0y, Fret = 4y)
Expand Down Expand Up @@ -319,6 +352,7 @@ let comparerTests =
Note(Time = 2, String = 0y, Fret = 8y)
Note(Time = 50, String = 0y, Fret = 8y)
Note(Time = 75, String = 0y, Fret = 8y) ]

let notes2 = [ Note(Time = 100, String = 0y, Fret = 5y)
Note(Time = 100, String = 0y, Fret = 0y)
Note(Time = 125, String = 0y, Fret = 1y)
Expand All @@ -337,6 +371,7 @@ let comparerTests =
Note(Time = 1, String = 0y, Fret = 1y)
Note(Time = 2, String = 0y, Fret = 2y)
Note(Time = 50, String = 0y, Fret = 3y) ]

let notes2 = [ Note(Time = 50, String = 0y, Fret = 5y)
Note(Time = 100, String = 0y, Fret = 0y)
Note(Time = 110, String = 0y, Fret = 0y)
Expand Down Expand Up @@ -397,4 +432,104 @@ let comparerTests =
let sameCount = getSameItemCount sameNote notes1 notes2

Expect.equal sameCount 6 "Count is correct"

// [ 0 1 2 3 1 2 3 9 ]
// [ 9 1 2 3 1 2 3 0 ]
testCase "Correct when different starting and ending note (Same number of notes)" <| fun _ ->
let notes1 = [ Note(Time = 0, String = 0y, Fret = 0y)
Note(Time = 1, String = 0y, Fret = 1y)
Note(Time = 2, String = 0y, Fret = 2y)
Note(Time = 3, String = 0y, Fret = 3y)
Note(Time = 4, String = 0y, Fret = 1y)
Note(Time = 5, String = 0y, Fret = 2y)
Note(Time = 6, String = 0y, Fret = 3y)
Note(Time = 7, String = 0y, Fret = 9y) ]

let notes2 = [ Note(Time = 0, String = 0y, Fret = 9y)
Note(Time = 1, String = 0y, Fret = 1y)
Note(Time = 2, String = 0y, Fret = 2y)
Note(Time = 3, String = 0y, Fret = 3y)
Note(Time = 4, String = 0y, Fret = 1y)
Note(Time = 5, String = 0y, Fret = 2y)
Note(Time = 6, String = 0y, Fret = 3y)
Note(Time = 7, String = 0y, Fret = 0y) ]

let sameCount = getSameItemCount sameNote notes1 notes2

Expect.equal sameCount 6 "Count is correct"

// [ 0 8 1 2 3 1 2 3 9 ]
// [ 9 7 1 2 3 1 2 3 0 ]
testCase "Correct when different starting notes and ending note (Same number of notes)" <| fun _ ->
let notes1 = [ Note(Time = 0, String = 0y, Fret = 0y)
Note(Time = 1, String = 0y, Fret = 8y)
Note(Time = 2, String = 0y, Fret = 1y)
Note(Time = 3, String = 0y, Fret = 2y)
Note(Time = 4, String = 0y, Fret = 3y)
Note(Time = 5, String = 0y, Fret = 1y)
Note(Time = 6, String = 0y, Fret = 2y)
Note(Time = 7, String = 0y, Fret = 3y)
Note(Time = 8, String = 0y, Fret = 9y) ]

let notes2 = [ Note(Time = 0, String = 0y, Fret = 9y)
Note(Time = 1, String = 0y, Fret = 7y)
Note(Time = 2, String = 0y, Fret = 1y)
Note(Time = 3, String = 0y, Fret = 2y)
Note(Time = 4, String = 0y, Fret = 3y)
Note(Time = 5, String = 0y, Fret = 1y)
Note(Time = 6, String = 0y, Fret = 2y)
Note(Time = 7, String = 0y, Fret = 3y)
Note(Time = 8, String = 0y, Fret = 0y) ]

let sameCount = getSameItemCount sameNote notes1 notes2

Expect.equal sameCount 6 "Count is correct"

// [ 0 1 2 3 1 2 3 9 ]
// [ 9 5 5 1 2 3 1 2 3 0 ]
testCase "Correct when different starting and ending notes, with different notes in between" <| fun _ ->
let notes1 = [ Note(Time = 0, String = 0y, Fret = 0y)
Note(Time = 1, String = 0y, Fret = 1y)
Note(Time = 2, String = 0y, Fret = 2y)
Note(Time = 3, String = 0y, Fret = 3y)
Note(Time = 4, String = 0y, Fret = 1y)
Note(Time = 5, String = 0y, Fret = 2y)
Note(Time = 6, String = 0y, Fret = 3y)
Note(Time = 7, String = 0y, Fret = 9y) ]

let notes2 = [ Note(Time = 0, String = 0y, Fret = 9y)
Note(Time = 1, String = 0y, Fret = 5y)
Note(Time = 2, String = 0y, Fret = 5y)
Note(Time = 3, String = 0y, Fret = 1y)
Note(Time = 4, String = 0y, Fret = 2y)
Note(Time = 5, String = 0y, Fret = 3y)
Note(Time = 6, String = 0y, Fret = 1y)
Note(Time = 7, String = 0y, Fret = 2y)
Note(Time = 8, String = 0y, Fret = 3y)
Note(Time = 9, String = 0y, Fret = 0y) ]

let sameCount = getSameItemCount sameNote notes1 notes2

Expect.equal sameCount 6 "Count is correct"

// [ 5 4 4 4 5 5 ]
// [ 4 5 5 5 4 4 ]
testCase "Correct with interleaved same notes" <| fun _ ->
let notes1 = [ Note(Time = 0, String = 0y, Fret = 5y)
Note(Time = 1, String = 0y, Fret = 4y)
Note(Time = 2, String = 0y, Fret = 4y)
Note(Time = 3, String = 0y, Fret = 4y)
Note(Time = 4, String = 0y, Fret = 5y)
Note(Time = 5, String = 0y, Fret = 5y) ]

let notes2 = [ Note(Time = 0, String = 0y, Fret = 4y)
Note(Time = 1, String = 0y, Fret = 5y)
Note(Time = 2, String = 0y, Fret = 5y)
Note(Time = 3, String = 0y, Fret = 5y)
Note(Time = 4, String = 0y, Fret = 4y)
Note(Time = 5, String = 0y, Fret = 4y) ]

let sameCount = getSameItemCount sameNote notes1 notes2

Expect.equal sameCount 3 "Count is correct"
]

0 comments on commit 45107c7

Please sign in to comment.