In some ways what you are asking for is less mathematics and more string handling. I am curious why you may think getting this result would be of use to you? I am confident that it can be done but expect the answer to take some effort to write, so I won’t jump into it without a little more confidence.
The typical algorithm would be to count occurrences and reset the count on change eg from a to b, b to a. to detect a change you need to store the last value to compare.
the new %if statements within a list widget may be helpful.
perhaps you could generate substrings of a and b and then test length[] or split and count.
the list widget now has the counter parameter
post script
the new let and multi-value variables in the 5.4.0 prerelease may be of use here.
also depending on the nature of your output you could use the contains operator to test for different sized strings ‘aaaa’ ‘aaa’ etc…
Sorry, I should have been clearer - the outcome field is in individual tiddlers collecting data so I will have a series of tiddlers with each outcome field containing a or b
Perhaps no need to go into the detail, but this answer is definitely what I need but unfortunately the potential solutions are beyond me. I suspect if I copy and paste into a spreadsheet I could get the answer and do that process periodically, but it would have been nice to have it within the wiki and producing the result continually.
We join together the outcome strings, then split on any run of b's. This leaves us with a list of runs of a's. We take the length of each run and return the maximum value of all of them.
We could make this slightly more generic, where we don’t know about b, but only not-a with this version:
But this technique only works if your outcome values are single characters.
For something more generic, I’m sure we could write a procedure that finds the longest contiguous group of a given title in a title-list. But, as big a fan as I am of recursion, I still struggle to turn simple recursive JS functions into TW procedures or functions.
If someone else wants to have a go, here’s a pretty simple JS version:
const maxContiguous = (x, xs, m = 0) =>
xs.length === 0
? m
: x === xs[0]
? maxContiguous (x, xs.slice(1), m + 1)
: Math.max(m, maxContiguous(x, xs.slice(1), 0))
maxContiguous ('a', 'abaabbbabaaaaabaaabaaa') //=> 5
Ah, with a search, I see the need to know what is being searched for when things are being split up - the actual content of the field outcome would be “win” and “loss”. I was thinking keeping it more generic would be easier - sorry for any confusion.
(The divide[3] is because there are three characters in "win".)
This is fragile, in that it expects every tiddler tagged A to have a outcome field with value of either win or loss (no blanks, no ties, no missing fields.) But that might still be reasonable.
I would like to find a way to write a procedure for this along the lines of the JS sample I sent, but I don’t have time to play with that now.
Not quite. This counts wins. It’s actually splitting the string "winwinlosslosslosswinlosswinwinwinwinlosswin at every run of losses, leaving you with ["winwin", "win", "winwinwinwin", "win"], counting characters to get [6, 3, 12, 3], taking the max, 12, and dividing by 3 to get 4. The maximum streak of wins is 4.
By splitting at (win)+ and dividing by 4, you would get the longest streak of losses.
<$let outcome="aaccabbbbbccccbbbaacacaaccaaaccccccccaaabbcbbabab"
re="(a+|b+|c+)"
>
outcome: <<outcome>> <br>
Consecutive string of ( "a" or "b" or "c" ) with a trailing space: {{{ [<outcome>search-replace:g:regexp<re>,[$1 ]] }}} <br>
Length of each consecutive string: {{{ [<outcome>search-replace:g:regexp<re>,[$1 ]split[ ]length[]butlast[]join[ ]] }}} <br>
Max length: {{{ [<outcome>search-replace:g:regexp<re>,[$1 ]split[ ]length[]maxall[]] }}} <br>
</$let>
Output:
outcome: aaccabbbbbccccbbbaacacaaccaaaccccccccaaabbcbbabab
Consecutive string of ( "a" or "b" or "c" ) with a trailing space: aa cc a bbbbb cccc bbb aa c a c aa cc aaa cccccccc aaa bb c bb a b a b
Length of each consecutive string: 2 2 1 5 4 3 2 1 1 1 2 2 3 8 3 2 1 2 1 1 1 1
Max length: 8
This sort of works with the words “win”,“loss” and “even” also.
outcome: winwinevenevenwinlosslosslosslosslossevenevenevenevenlosslosslosswinwinevenwinevenwinwinevenevenwin
Consecutive string of keywords : winwin eveneven win losslosslosslossloss eveneveneveneven losslossloss winwin even win even winwin eveneven win
But it requires three global search-replace for the three keywords into a different character for the counting. So maybe better to perform the three global search-replace right at the beginning into a different character each, and just use the first solution.