Skip to content

Instantly share code, notes, and snippets.

@primaryobjects
Last active November 6, 2017 19:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save primaryobjects/265b19f5d2f971027b139d07675f12b3 to your computer and use it in GitHub Desktop.
Save primaryobjects/265b19f5d2f971027b139d07675f12b3 to your computer and use it in GitHub Desktop.
#
# [2017-10-16] Challenge #336 [Easy] Cannibal numbers
# https: https://www.reddit.com/r/dailyprogrammer/comments/76qk58/20171016_challenge_336_easy_cannibal_numbers/
#
# Demo at http://www.r-fiddle.org/#/fiddle?id=xqqeOaS1&version=2
#
# Imagine a given set of numbers wherein some are cannibals.
# We define a cannibal as a larger number can eat a smaller number and increase its value by 1.
# There are no restrictions on how many numbers any given number can consume.
# A number which has been consumed is no longer available.
# Your task is to determine the number of numbers which can have a value equal to or greater than a specified value.
#
# by Kory Becker
# http://primaryobjects.com
#
cannibalize <- function(input, threshold, verbose=F) {
# Start by counting the numbers that are already >= query.
count <- length(input[input >= threshold])
if (verbose) print(paste(count, "number(s) already meet the threshold."))
# Sort the numbers in descending order.
numbers <- sort(input[input < threshold], T)
numbersAsc <- sort(input[input < threshold], F)
# Use the indices of each number to record consumptions.
indices <- seq_along(numbers)
indicesAsc <- rev(indices)
consumed <- c()
# For each number, find the smallest numbers to add to make them >= to the query value.
sapply(indices, function(i) {
if (!i %in% consumed) {
number <- numbers[i]
total <- number
for (j in indicesAsc) {
if (!j %in% consumed) {
n <- numbers[j]
# A number can't consume itself and must be bigger than the prey.
if (i != j && total > n) {
# Consume it.
total <- total + 1
if (verbose) print(paste(number, "is trying to consume", n, "for a total of", total))
# Mark the index as consumed.
consumed <<- c(consumed, j)
if (total >= threshold) {
if (verbose) print('Consumed!')
count <<- count + 1
break
}
}
}
}
}
})
count
}
# Our input data.
data <- list(
list(numbers = c(21, 9, 5, 8, 10, 1, 3), queries = c(10, 15), answers = c(4, 2)),
list(numbers = c(1, 2, 3, 4, 5), queries = c(5), answers = c(2)),
list(numbers = c(9, 10, 14, 15, 18, 21, 4, 3, 7, 8, 10, 12), queries = c(9:13), answers = c(9, 9, 8, 7, 6)),
list(numbers = c(4, 4, 4, 4, 4, 4, 4), queries = c(5), answers = c(0)),
list(numbers = c(5, 4, 4, 4, 1), queries = c(6), answers = c(1)),
list(numbers = c(2, 2, 2, 2), queries = c(3), answers = c(0)),
list(numbers = c(4, 4, 4, 3), queries = c(6), answers = c(1)),
list(numbers = c(3, 3, 3, 3), queries = c(4), answers = c(0))
)
# Run the canibal numbers method on each problem set.
x <- sapply(data, function(row) {
# Get the result for this problem set.
results <- sapply(row$queries, function(query) {
list(query=query, total=cannibalize(row$numbers, query))
})
# Print the results.
sapply(1:ncol(results), function(i) {
result <- results[,i]
print(paste('Query', result$query, 'Total', result$total, ifelse(result$total == row$answers[i], 'Pass', 'Fail')))
})
})
data <- list(
list(numbers = c(21, 9, 5, 8, 10, 1, 3), queries = c(10, 15), answers = c(4, 2)),
list(numbers = c(1, 2, 3, 4, 5), queries = c(5), answers = c(2)),
list(numbers = c(9, 10, 14, 15, 18, 21, 4, 3, 7, 8, 10, 12), queries = c(9:13), answers = c(9, 9, 8, 7, 6)),
list(numbers = c(4, 4, 4, 4, 4, 4, 4), queries = c(5), answers = c(0)),
list(numbers = c(5, 4, 4, 4, 1), queries = c(6), answers = c(1)),
list(numbers = c(2, 2, 2, 2), queries = c(3), answers = c(0)),
list(numbers = c(4, 4, 4, 3), queries = c(6), answers = c(1)),
list(numbers = c(3, 3, 3, 3), queries = c(4), answers = c(0))
)
21, 9, 5, 8, 10, 1, 3, queries = 10, 15, output = 4, 2
1, 2, 3, 4, 5, queries = 5, output = 2
9, 10, 14, 15, 18, 21, 4, 3, 7, 8, 10, 12, queries = 9, 10, 11, 12, 13, output = 9, 9, 8, 7, 6
4, 4, 4, 4, 4, 4, 4, queries = 5, output = 0
5, 4, 4, 4, 1, queries = 6, output = 1
2, 2, 2, 2, queries = 3, output = 0
4, 4, 4, 3, queries = 6, output = 1
3, 3, 3, 3, queries = 4, output = 0
"Query 10 Total 4 Pass"
"Query 15 Total 2 Pass"
"Query 5 Total 2 Pass"
"Query 9 Total 9 Pass"
"Query 10 Total 9 Pass"
"Query 11 Total 8 Pass"
"Query 12 Total 7 Pass"
"Query 13 Total 6 Pass"
"Query 5 Total 0 Pass"
"Query 6 Total 1 Pass"
"Query 3 Total 0 Pass"
"Query 6 Total 1 Pass"
"Query 4 Total 0 Pass"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment