context("Multiset Permutations")

test_that("Multiset Permutations - npermutations", {
    expect_equal(npermutations(freq = c(3, 1, 3)), 140)
    expect_equal(npermutations(x = LETTERS[1:3], freq = c(3, 1, 3)), 140)
    expect_error(npermutations(freq = c(10, 5, 10)), "integer overflow")
    expect_error(npermutations(x = LETTERS[1:3], freq = c(10, 5, 10)), "integer overflow")
    expect_equal(npermutations(freq = c(10, 5, 10), bigz = TRUE), gmp::as.bigz("9816086280"))
    expect_equal(npermutations(freq = c(0, 0, 0)), 1)
    expect_error(npermutations(freq = c(2, -1, 0)), "expect integer")
    expect_error(npermutations(freq = c(2, 2, 1.5)), "expect integer")
})

test_that("Multiset Permutations - permutations", {
    perm <- permutations(freq = c(3, 1, 3))
    expect_equal(nrow(perm), 140)
    expect_equal(ncol(perm), 7)
    expect_equal(perm[1, ], c(1, 1, 1, 2, 3, 3, 3))
    expect_equal(perm[140, ], c(3, 3, 3, 2, 1, 1, 1))

    perm <- permutations(freq = c(3, 1, 3), layout = "row")
    expect_equal(nrow(perm), 140)
    expect_equal(ncol(perm), 7)
    expect_equal(perm[1, ], c(1, 1, 1, 2, 3, 3, 3))
    expect_equal(perm[140, ], c(3, 3, 3, 2, 1, 1, 1))

    perm <- permutations(freq = c(3, 1, 3), layout = "column")
    expect_equal(ncol(perm), 140)
    expect_equal(nrow(perm), 7)
    expect_equal(perm[, 1], c(1, 1, 1, 2, 3, 3, 3))
    expect_equal(perm[, 140], c(3, 3, 3, 2, 1, 1, 1))

    perm <- permutations(freq = c(3, 1, 3), layout = "list")
    expect_equal(length(perm), 140)
    expect_equal(perm[[1]], c(1, 1, 1, 2, 3, 3, 3))
    expect_equal(perm[[140]], c(3, 3, 3, 2, 1, 1, 1))

    perm <- permutations(x = LETTERS[1:3], freq = c(3, 1, 3))
    expect_equal(nrow(perm), 140)
    expect_equal(ncol(perm), 7)
    expect_equal(perm[1, ], LETTERS[c(1, 1, 1, 2, 3, 3, 3)])
    expect_equal(perm[140, ], LETTERS[c(3, 3, 3, 2, 1, 1, 1)])

    expect_error(permutations(freq = c(10, 5, 10)), "too many results")
    expect_error(permutations(freq = c(2, -1, 0)), "expect integer")
    expect_error(permutations(freq = c(2, 2, 1.5)), "expect integer")
    expect_equal(dim(permutations(freq = c(0, 0, 0))), c(1, 0))
})

test_that("Multiset Permutations - ipermutations", {
    iperm <- ipermutations(freq = c(3, 1, 3))
    perm <- permutations(freq = c(3, 1, 3))
    expect_equal(iperm$collect(), perm)
    expect_equal(iperm$getnext(), c(1, 1, 1, 2, 3, 3, 3))
    expect_equal(iperm$getnext(), c(1, 1, 1, 3, 2, 3, 3))
    iperm$getnext(130)
    expect_equal(nrow(iperm$getnext(10)), 8)
    expect_equal(iperm$getnext(), NULL)

    perm <- permutations(freq = c(3, 1, 3), layout = "row")
    expect_equal(iperm$collect(layout = "row"), perm)
    expect_equal(iperm$getnext(layout = "row"), t(c(1, 1, 1, 2, 3, 3, 3)))
    expect_equal(iperm$getnext(layout = "row"), t(c(1, 1, 1, 3, 2, 3, 3)))
    iperm$getnext(130, layout = "row")
    expect_equal(nrow(iperm$getnext(10, layout = "row")), 8)
    expect_equal(iperm$getnext(layout = "row"), NULL)

    perm <- permutations(freq = c(3, 1, 3), layout = "column")
    expect_equal(iperm$collect(layout = "column"), perm)
    expect_equal(iperm$getnext(layout = "column"), t(t(c(1, 1, 1, 2, 3, 3, 3))))
    expect_equal(iperm$getnext(layout = "column"), t(t(c(1, 1, 1, 3, 2, 3, 3))))
    iperm$getnext(130, layout = "column")
    expect_equal(ncol(iperm$getnext(10, layout = "column")), 8)
    expect_equal(iperm$getnext(layout = "column"), NULL)

    perm <- permutations(freq = c(3, 1, 3), layout = "list")
    expect_equal(iperm$collect(layout = "list"), perm)
    expect_equal(iperm$getnext(layout = "list"), list(c(1, 1, 1, 2, 3, 3, 3)))
    expect_equal(iperm$getnext(layout = "list"), list(c(1, 1, 1, 3, 2, 3, 3)))
    iperm$getnext(130, layout = "list")
    expect_equal(length(iperm$getnext(10, layout = "list")), 8)
    expect_equal(iperm$getnext(layout = "list"), NULL)

    expect_error(ipermutations(freq = c(2, -1, 0)), "expect integer")
    expect_error(ipermutations(freq = c(2, 2, 1.5)), "expect integer")
})



context("Multiset K-Permutations")

test_that("Multiset K-Permutations - npermutations", {
    expect_equal(npermutations(freq = c(3, 2, 3), k = 4), 70)
    expect_equal(npermutations(x = LETTERS[1:3], freq = c(3, 2, 3), k = 4), 70)
    expect_error(npermutations(freq = c(10, 50, 10), k = 20), "integer overflow")
    expect_error(npermutations(x = LETTERS[1:3], freq = c(10, 50, 10), k = 20), "integer overflow")
    expect_equal(npermutations(freq = c(10, 50, 10), k = 20, bigz = TRUE), gmp::as.bigz("3224323183"))
    expect_equal(npermutations(freq = c(0, 0, 0), k = 4), 0)
    expect_equal(npermutations(freq = c(0, 0, 0), k = 0), 1)
    expect_error(npermutations(freq = c(3, 2, 3), k = -1), "expect integer")
    expect_error(npermutations(freq = c(3, 2, 3), k = 1.5), "expect integer")
})

test_that("Multiset K-Permutations - permutations", {
    perm <- permutations(freq = c(3, 2, 3), k = 4)
    expect_equal(nrow(perm), 70)
    expect_equal(ncol(perm), 4)
    expect_equal(perm[1, ], c(1, 1, 1, 2))
    expect_equal(perm[70, ], c(3, 3, 3, 2))

    perm <- permutations(freq = c(3, 2, 3), k = 4, layout = "column")
    expect_equal(ncol(perm), 70)
    expect_equal(nrow(perm), 4)
    expect_equal(perm[, 1], c(1, 1, 1, 2))
    expect_equal(perm[, 70], c(3, 3, 3, 2))

    perm <- permutations(freq = c(3, 2, 3), k = 4, layout = "list")
    expect_equal(length(perm), 70)
    expect_equal(perm[[1]], c(1, 1, 1, 2))
    expect_equal(perm[[70]], c(3, 3, 3, 2))

    perm <- permutations(x = LETTERS[1:3], freq = c(3, 2, 3), k = 4)
    expect_equal(nrow(perm), 70)
    expect_equal(ncol(perm), 4)
    expect_equal(perm[1, ], LETTERS[c(1, 1, 1, 2)])
    expect_equal(perm[70, ], LETTERS[c(3, 3, 3, 2)])

    expect_error(permutations(freq = c(10, 50, 10), k = 20), "too many results")
    expect_error(permutations(freq = c(3, 2, 3), k = -1), "expect integer")
    expect_error(permutations(freq = c(3, 2, 3), k = 1.5), "expect integer")
    expect_equal(dim(permutations(freq = c(3, 2, 3), k = 0)), c(1, 0))
    expect_equal(dim(permutations(freq = c(0, 0, 0), k = 1 )), c(0, 1))
    expect_equal(dim(permutations(freq = c(0, 0, 0), k = 0 )), c(1, 0))
})

test_that("Multiset K-Permutations - ipermutations", {
    iperm <- ipermutations(freq = c(3, 2, 3), k = 4)
    perm <- permutations(freq = c(3, 2, 3), k = 4)
    expect_equal(iperm$collect(), perm)
    expect_equal(iperm$getnext(), c(1, 1, 1, 2))
    expect_equal(iperm$getnext(), c(1, 1, 1, 3))
    iperm$getnext(60)
    expect_equal(nrow(iperm$getnext(10)), 8)
    expect_equal(iperm$getnext(), NULL)

    perm <- permutations(freq = c(3, 2, 3), k = 4, layout = "row")
    expect_equal(iperm$collect(), perm)
    expect_equal(iperm$getnext(layout = "row"), t(c(1, 1, 1, 2)))
    expect_equal(iperm$getnext(layout = "row"), t(c(1, 1, 1, 3)))
    iperm$getnext(60, layout = "row")
    expect_equal(nrow(iperm$getnext(10, layout = "row")), 8)
    expect_equal(iperm$getnext(layout = "row"), NULL)

    perm <- permutations(freq = c(3, 2, 3), k = 4, layout = "column")
    expect_equal(iperm$collect(layout = "column"), perm)
    expect_equal(iperm$getnext(layout = "column"), t(t(c(1, 1, 1, 2))))
    expect_equal(iperm$getnext(layout = "column"), t(t(c(1, 1, 1, 3))))
    iperm$getnext(60, layout = "column")
    expect_equal(ncol(iperm$getnext(10, layout = "column")), 8)
    expect_equal(iperm$getnext(layout = "column"), NULL)

    perm <- permutations(freq = c(3, 2, 3), k = 4, layout = "list")
    expect_equal(iperm$collect(layout = "list"), perm)
    expect_equal(iperm$getnext(layout = "list"), list(c(1, 1, 1, 2)))
    expect_equal(iperm$getnext(layout = "list"), list(c(1, 1, 1, 3)))
    iperm$getnext(60, layout = "list")
    expect_equal(length(iperm$getnext(10, layout = "list")), 8)
    expect_equal(iperm$getnext(layout = "list"), NULL)

    expect_error(ipermutations(freq = c(3, 2, 3), k = -1), "expect integer")
    expect_error(ipermutations(freq = c(3, 2, 3), k = 1.5), "expect integer")
    iperm <- ipermutations(freq = c(3, 2, 3), k = 0)
    expect_equal(dim(iperm$collect()), c(1, 0))
    expect_equal(iperm$getnext(), integer(0))
    iperm <- ipermutations(freq = c(3, 2, 3), k = 9)
    expect_equal(dim(iperm$collect()), c(0, 9))
    expect_equal(iperm$getnext(), NULL)
})

test_that("Multiset Permutations - index", {
    perm <- permutations(freq = c(3, 2, 3), k = 4)
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, index = 1:70), perm)
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, index = as.numeric(1:70)), perm)
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, index = as.character(1:70)), perm)
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, index = gmp::as.bigz(1:70)), perm)
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, index = 2), c(1, 1, 1, 3))
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, index = 70), c(3, 3, 3, 2))
    expect_equal(permutations(freq = c(10, 50, 10), k = 20, index = 2), c(rep(1, 10), rep(2, 9), 3))
    expect_equal(permutations(freq = c(10, 50, 10), k = 20, index = "3224323183"), rep(3:2, each = 10))

    expect_equal(permutations(freq = c(2, 3, 3, 4), k = 0, index = 1), integer(0))
    expect_equal(permutations(freq = 0, k = 0, index = 1), integer(0))
    expect_error(permutations(freq = 0, k = 1, index = 1), "invalid index")
    expect_equal(permutations(freq = c(2, 3, 3, 4), k = 0, index = gmp::as.bigz(1)), integer(0))
    expect_equal(permutations(freq = 0, k = 0, index = gmp::as.bigz(1)), integer(0))
    expect_error(permutations(freq = 0, k = 1, index = gmp::as.bigz(1)), "invalid index")
})

test_that("Multiset Permutations - skip", {
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, skip = 70), permutations(freq = c(3, 2, 3), k = 4))
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, skip = 3), permutations(freq = c(3, 2, 3), k = 4)[4:70, ])
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, skip = 3, nitem = 4), permutations(freq = c(3, 2, 3), k = 4)[4:7, ])
    expect_equal(permutations(freq = c(3, 2, 3), k = 4, skip = gmp::as.bigz(3), nitem = 4), permutations(freq = c(3, 2, 3), k = 4)[4:7, ])
})
