Here is the solution I came up with.
You said , Team A played D and won; winning gets 3 points; so I ignored the 4 in your example table, as by your words it should be 3.
I calculated 81 possible timelines from the given starting point; of which D would be in the top 2 positions in 32 cases.
library(tidyverse)
(matches <- tibble(as.data.frame(t(combn(LETTERS[1:4],2)))))
(point_pos <- tibble(p1 = c(3,1,0), p2 =c(0,1,3)))
(possibility_groups <- crossing(matches,point_pos) |>
mutate(group=paste0(V1,V2)) |> split(f=~group))
# how many rows to expect (unfiltered) ?
3^6 # 729
filtered_possibility_groups <- possibility_groups
#can comment out these next two rows to have no filtering applied
filtered_possibility_groups$AD <- filtered_possibility_groups$AD |> filter(p1==1)
filtered_possibility_groups$BC <- filtered_possibility_groups$BC |> filter(p1==1)
(all_messy <- reduce(filtered_possibility_groups,crossing,.name_repair="universal"))
(cleanup1 <- all_messy |> rename_with(~str_replace_all(.x,fixed('...'),"_")) |>
mutate(possible_timeline = row_number()) |>
relocate(possible_timeline))
#timelines post any filtering
nrow(cleanup1)
# 81 in given example filtering
make_points_frame_from_row <- function(row){
timeid <- row$possible_timeline
row$possible_timeline <- NULL
groups <- (ncol(row)) /5
starts <- seq_len(groups)*5 - 4
ends <- starts + 3
starts_and_ends <- map2(starts,ends,~seq(from=.x,to=.y))
stacked <- map_dfr(starts_and_ends,
~select(row,.x) |> set_names(c("V1","V2","P1","P2")))
smry <- bind_rows(stacked |> select(V=V1,P=P1) ,
stacked |> select(V=V2,P=P2)) |>
group_by(V) |>
summarise(P=sum(P,na.rm=TRUE)) |> arrange(desc(P))
bind_cols(t_id = timeid,smry)
}
time_lines <- map(seq_len(nrow(cleanup1)),
~make_points_frame_from_row(cleanup1 |> slice(.x)))
# count the subset of timelines for which D is in top 2
map_int(time_lines,~{
head(.x,n=2) |> filter(V == 'D') |> nrow()
}) |> sum()
# 32 for given example filter