context("Distinct K-Partitions")

test_that("Integer distinct partitions in k parts - npartitions", {
    expect_equal(npartitions(20, 3, distinct = TRUE), 24)
    expect_equal(npartitions(20, 6, distinct = TRUE), 0)
    expect_equal(npartitions(20, 21, distinct = TRUE), 0)
    expect_equal(npartitions(1000, 50, distinct = TRUE), 0)
    expect_equal(sum(sapply(1:20, function(k) npartitions(20, k, distinct = TRUE))), 64)
    expect_equal(npartitions(100, 10, distinct = TRUE), 33401)
    expect_error(npartitions(500, 20, distinct = TRUE), "integer overflow")
    expect_equal(npartitions(20, 3, distinct = TRUE, bigz = TRUE), 24)
    expect_equal(npartitions(100, 10, distinct = TRUE, bigz = TRUE), 33401)
    expect_equal(npartitions(500, 20, distinct = TRUE, bigz = TRUE), gmp::as.bigz("55918063581549"))
    expect_equal(npartitions(1000, 50, distinct = TRUE, bigz = T), 0)
    expect_equal(npartitions(20, 0, distinct = TRUE), 0)
    expect_equal(npartitions(0, 0, distinct = TRUE), 1)
    expect_error(npartitions(20, -1, distinct = TRUE), "expect integer")
    expect_error(npartitions(20, 1.5, distinct = TRUE), "expect integer")
})

test_that("Integer distinct k-partitions - ascending partitions", {
    part <- partitions(20, 3, distinct = TRUE)
    expect_equal(nrow(part), 24)
    expect_equal(ncol(part), 3)
    expect_equal(part[1, ], c(1, 2, 17))
    expect_equal(part[2, ], c(1, 3, 16))
    expect_equal(part[24, ], c(5, 7, 8))
    expect_true(all(apply(part, 1, sum) == 20))

    part <- partitions(20, 3, distinct = TRUE, layout = "row")
    expect_equal(nrow(part), 24)
    expect_equal(ncol(part), 3)
    expect_equal(part[1, ], c(1, 2, 17))
    expect_equal(part[2, ], c(1, 3, 16))
    expect_equal(part[24, ], c(5, 7, 8))
    expect_true(all(apply(part, 1, sum) == 20))

    part <- partitions(20, 3, distinct = TRUE, layout = "column")
    expect_equal(nrow(part), 3)
    expect_equal(ncol(part), 24)
    expect_equal(part[, 1], c(1, 2, 17))
    expect_equal(part[, 2], c(1, 3, 16))
    expect_equal(part[, 24], c(5, 7, 8))
    expect_true(all(apply(part, 2, sum) == 20))

    part <- partitions(20, 3, distinct = TRUE, layout = "list")
    expect_equal(length(part), 24)
    expect_equal(part[[1]], c(1, 2, 17))
    expect_equal(part[[2]], c(1, 3, 16))
    expect_equal(part[[24]], c(5, 7, 8))
    expect_true(all(sapply(part, sum) == 20))

    expect_error(partitions(2000, 50, distinct = TRUE), "too many results")
    expect_equal(dim(partitions(20, 21, distinct = TRUE)), c(0, 21))
    expect_equal(dim(partitions(20, 21, distinct = TRUE, layout = "column")), c(21, 0))
    expect_equal(length(partitions(20, 21, distinct = TRUE, layout = "list")), 0)
    expect_error(partitions(20, -1, distinct = TRUE), "expect integer")
    expect_error(partitions(20, 1.5, distinct = TRUE), "expect integer")
})

test_that("Integer distinct k-partitions - descending partitions", {
    part <- partitions(20, 3, distinct = TRUE, descending = TRUE)
    expect_equal(nrow(part), 24)
    expect_equal(ncol(part), 3)
    expect_equal(part[1, ], c(17, 2, 1))
    expect_equal(part[2, ], c(16, 3, 1))
    expect_equal(part[24, ], c(8, 7, 5))
    expect_true(all(apply(part, 1, sum) == 20))

    part <- partitions(20, 3, distinct = TRUE, descending = TRUE, layout = "row")
    expect_equal(nrow(part), 24)
    expect_equal(ncol(part), 3)
    expect_equal(part[1, ], c(17, 2, 1))
    expect_equal(part[2, ], c(16, 3, 1))
    expect_equal(part[24, ], c(8, 7, 5))
    expect_true(all(apply(part, 1, sum) == 20))

    part <- partitions(20, 3, distinct = TRUE, descending = TRUE, layout = "column")
    expect_equal(nrow(part), 3)
    expect_equal(ncol(part), 24)
    expect_equal(part[, 1], c(17, 2, 1))
    expect_equal(part[, 2], c(16, 3, 1))
    expect_equal(part[, 24], c(8, 7, 5))
    expect_true(all(apply(part, 2, sum) == 20))

    part <- partitions(20, 3, distinct = TRUE, descending = TRUE, layout = "list")
    expect_equal(length(part), 24)
    expect_equal(part[[1]], c(17, 2, 1))
    expect_equal(part[[2]], c(16, 3, 1))
    expect_equal(part[[24]], c(8, 7, 5))
    expect_true(all(sapply(part, sum) == 20))

    expect_error(partitions(2000, 50, distinct = TRUE, descending = TRUE), "too many results")
    expect_equal(dim(partitions(20, 21, distinct = TRUE, descending = TRUE)), c(0, 21))
    expect_equal(dim(partitions(20, 21, distinct = TRUE, descending = TRUE, layout = "column")), c(21, 0))
    expect_equal(length(partitions(20, 21, distinct = TRUE, descending = TRUE, layout = "list")), 0)
    expect_error(partitions(20, -1, distinct = TRUE, descending = TRUE), "expect integer")
    expect_error(partitions(20, 1.5, distinct = TRUE, descending = TRUE), "expect integer")
})

test_that("Integer distinct k-partitions - ascending ipartitions", {
    part <- partitions(20, 3, distinct = TRUE)
    ipart <- ipartitions(20, 3, distinct = TRUE)
    expect_is(ipart, "Partitions")
    expect_equal(ipart$collect(), part)
    expect_equal(ipart$getnext(), part[1, ])
    expect_equal(ipart$getnext(), part[2, ])
    expect_equal(ipart$getnext(2), part[3:4, ])
    ipart$getnext(15)
    expect_equal(nrow(ipart$getnext(15)), 5)
    expect_equal(ipart$getnext(), NULL)

    part <- partitions(20, 3, distinct = TRUE, layout = "row")
    ipart$reset()
    expect_equal(ipart$collect(layout = "row"), part)
    expect_equal(ipart$getnext(layout = "row"), part[1, , drop = FALSE])
    expect_equal(ipart$getnext(layout = "row"), part[2, , drop = FALSE])
    expect_equal(ipart$getnext(2, layout = "row"), part[3:4, ])
    ipart$getnext(15, layout = "row")
    expect_equal(nrow(ipart$getnext(15, layout = "row")), 5)
    expect_equal(ipart$getnext(layout = "row"), NULL)

    part <- partitions(20, 3, distinct = TRUE, layout = "column")
    ipart$reset()
    expect_equal(ipart$collect(layout = "column"), part)
    expect_equal(ipart$getnext(layout = "column"), part[, 1, drop = FALSE])
    expect_equal(ipart$getnext(layout = "column"), part[, 2, drop = FALSE])
    expect_equal(ipart$getnext(2, layout = "column"), part[, 3:4])
    ipart$getnext(15, layout = "column")
    expect_equal(ncol(ipart$getnext(15, layout = "column")), 5)
    expect_equal(ipart$getnext(layout = "column"), NULL)

    part <- partitions(20, 3, distinct = TRUE, layout = "list")
    ipart$reset()
    expect_equal(ipart$collect(layout = "list"), part)
    expect_equal(ipart$getnext(layout = "list"), part[1])
    expect_equal(ipart$getnext(layout = "list"), part[2])
    expect_equal(ipart$getnext(2, layout = "list"), part[3:4])
    ipart$getnext(15, layout = "list")
    expect_equal(length(ipart$getnext(15, layout = "list")), 5)
    expect_equal(ipart$getnext(layout = "list"), NULL)

    ipart <- ipartitions(20, 21, distinct = TRUE)
    expect_equal(dim(ipart$collect()), c(0, 21))
    expect_equal(ipart$getnext(), NULL)
    expect_error(ipartitions(20, -1), "expect integer")
    expect_error(ipartitions(20, 1.5), "expect integer")
})

test_that("Integer distinct partitions - descending ipartitions", {
    part <- partitions(20, 3, distinct = TRUE, descending = TRUE)
    ipart <- ipartitions(20, 3, distinct = TRUE, descending = TRUE)
    expect_is(ipart, "Partitions")
    expect_equal(ipart$collect(), part)
    expect_equal(ipart$getnext(), part[1, ])
    expect_equal(ipart$getnext(), part[2, ])
    expect_equal(ipart$getnext(2), part[3:4, ])
    ipart$getnext(15)
    expect_equal(nrow(ipart$getnext(15)), 5)
    expect_equal(ipart$getnext(15), NULL)

    part <- partitions(20, 3, distinct = TRUE, descending = TRUE, layout = "row")
    ipart$reset()
    expect_equal(ipart$collect(layout = "row"), part)
    expect_equal(ipart$getnext(layout = "row"), part[1, , drop = FALSE])
    expect_equal(ipart$getnext(layout = "row"), part[2, , drop = FALSE])
    expect_equal(ipart$getnext(2, layout = "row"), part[3:4, ])
    ipart$getnext(15, layout = "row")
    expect_equal(nrow(ipart$getnext(15, layout = "row")), 5)
    expect_equal(ipart$getnext(layout = "row"), NULL)

    part <- partitions(20, 3, distinct = TRUE, descending = TRUE, layout = "column")
    ipart$reset()
    expect_equal(ipart$collect(layout = "column"), part)
    expect_equal(ipart$getnext(layout = "column"), part[, 1, drop = FALSE])
    expect_equal(ipart$getnext(layout = "column"), part[, 2, drop = FALSE])
    expect_equal(ipart$getnext(2, layout = "column"), part[, 3:4])
    ipart$getnext(15, layout = "column")
    expect_equal(ncol(ipart$getnext(15, layout = "column")), 5)
    expect_equal(ipart$getnext(layout = "column"), NULL)

    part <- partitions(20, 3, distinct = TRUE, descending = TRUE, layout = "list")
    ipart$reset()
    expect_equal(ipart$collect(layout = "list"), part)
    expect_equal(ipart$getnext(layout = "list"), part[1])
    expect_equal(ipart$getnext(layout = "list"), part[2])
    expect_equal(ipart$getnext(2, layout = "list"), part[3:4])
    ipart$getnext(15, layout = "list")
    expect_equal(length(ipart$getnext(15, layout = "list")), 5)
    expect_equal(ipart$getnext(layout = "list"), NULL)

    ipart <- ipartitions(20, 21, distinct = TRUE, descending = TRUE)
    expect_equal(dim(ipart$collect()), c(0, 21))
    expect_equal(ipart$getnext(), NULL)
    expect_error(ipartitions(20, -1, descending = TRUE), "expect integer")
    expect_error(ipartitions(20, 1.5, descending = TRUE), "expect integer")
})

test_that("Integer distinct k-partitions - index", {
    part <- partitions(30, 5, distinct = TRUE)
    expect_equal(partitions(30, 5, distinct = TRUE, index = 1:84), part)
    expect_equal(partitions(30, 5, distinct = TRUE, index = as.numeric(1:84)), part)
    expect_equal(partitions(30, 5, distinct = TRUE, index = as.character(1:84)), part)
    expect_equal(partitions(30, 5, distinct = TRUE, index = gmp::as.bigz(1:84)), part)
    expect_equal(partitions(30, 5, distinct = TRUE, index = 2), c(1, 2, 3, 5, 19))
    expect_equal(partitions(30, 5, distinct = TRUE, index = 84), 4:8)
    expect_equal(partitions(2000, 50, distinct = TRUE, index = 2), c(1:48, 50, 774))
    expect_equal(partitions(2000, 50, distinct = TRUE, index = "17596186237961231843789396"), c(15:39, 41:65))

    expect_error(partitions(5, 0, distinct = TRUE, index = 1), "invalid index")
    expect_equal(partitions(0, 0, distinct = TRUE, index = 1), integer(0))
    expect_error(partitions(0, 1, distinct = TRUE, index = 1), "invalid index")

    part <- partitions(30, 5, distinct = TRUE, descending = TRUE)
    expect_error(partitions(5, 0, distinct = TRUE, descending = TRUE, index = 1), "invalid index")
    expect_equal(partitions(0, 0, distinct = TRUE, descending = TRUE, index = 1), integer(0))
    expect_error(partitions(0, 1, distinct = TRUE, descending = TRUE, index = 1), "invalid index")
})



test_that("Integer distinct k-partitions - skip", {
    expect_equal(partitions(30, 5, distinct = TRUE, skip = 84), partitions(30, 5, distinct = TRUE))
    expect_equal(partitions(30, 5, distinct = TRUE, skip = 3), partitions(30, 5, distinct = TRUE)[4:84, ])
    expect_equal(partitions(30, 5, distinct = TRUE, skip = 3, nitem = 4), partitions(30, 5, distinct = TRUE)[4:7, ])
    expect_equal(partitions(30, 5, distinct = TRUE, skip = gmp::as.bigz(3), nitem = 4), partitions(30, 5, distinct = TRUE)[4:7, ])

    expect_equal(partitions(30, 5, distinct = TRUE, descending = TRUE, skip = 84), partitions(30, 5, distinct = TRUE, descending = TRUE))
    expect_equal(partitions(30, 5, distinct = TRUE, descending = TRUE, skip = 3), partitions(30, 5, distinct = TRUE, descending = TRUE)[4:84, ])
    expect_equal(partitions(30, 5, distinct = TRUE, descending = TRUE, skip = 3, nitem = 4), partitions(30, 5, distinct = TRUE, descending = TRUE)[4:7, ])
    expect_equal(partitions(30, 5, distinct = TRUE, descending = TRUE, skip = gmp::as.bigz(3), nitem = 4), partitions(30, 5, distinct = TRUE, descending = TRUE)[4:7, ])
})
