R语言Codewars实战——Sum by Factors(4kyu)

Description:

Given an array of positive or negative integers

I= [i1,..,in]

you have to produce a sorted array P of the form

[ [p, sum of all ij of I for which p is a prime factor (p positive) of ij] ...]

P will be sorted by increasing order of the prime numbers. The final result has to be given as a string in Java, C#, C, C++ and as an array of arrays in other languages.

Example:

I = (/12, 15/); // result = "(2 12)(3 27)(5 15)"

[2, 3, 5] is the list of all prime factors of the elements of I, hence the result.

Notes:

  • It can happen that a sum is 0 if some numbers are negative!

Example: I = [15, 30, -45] 5 divides 15, 30 and (-45) so 5 appears in the result, the sum of the numbers for which 5 is a factor is 0 so we have [5, 0] in the result amongst others.

  • In Fortran - as in any other language - the returned string is not permitted to contain any redundant trailing whitespace: you can use dynamically allocated character strings.

Test Cases:

testing <- function(ls, expected) {
  actual <- sumOfDivided(ls)
  expect_equal(actual, expected)
}

test_that("tests", {
  testing(c(12, 15), list(c(2, 12), c(3, 27), c(5, 15)))
  testing(c(15,21,24,30,45), list(c(2, 54), c(3, 135), c(5, 90), c(7, 21)))
  testing(c(15,21,24,30,-45), list(c(2, 54), c(3, 45), c(5, 0), c(7, 21)))
  testing(c(107, 158, 204, 100, 118, 123, 126, 110, 116, 100), 
                     list(c(2, 1032), c(3, 453), c(5, 310), c(7, 126), c(11, 110), c(17, 204), c(29, 116), c(41, 123), c(59, 118), c(79, 158), c(107, 107)))
  testing(c(-29804, -4209, -28265, -72769, -31744), 
                     list(c(2, -61548), c(3, -4209), c(5, -28265), c(23, -4209), c(31, -31744), c(53, -72769), c(61, -4209), c(1373, -72769), c(5653, -28265), c(7451, -29804)))
  testing(c(), list())
  testing(c(1070, 1580, 2040, 1000, 1180, 1230, 1260, 1100, 1160, 1000), 
                     list(c(2, 12620), c(3, 4530), c(5, 12620), c(7, 1260), c(11, 1100), c(17, 2040), c(29, 1160), c(41, 1230), c(59, 1180), c(79, 1580), c(107, 1070)))
  testing(c(17, 34, 51, 68, 102), list(c(2, 204), c(3, 153), c(17, 272)))
  testing(c(17, -17, 51, -51), list(c(3, 0), c(17, 0)))
  testing(c(173471), list(c(41, 173471), c(4231, 173471)))
})

sumOfDivided098 <- function (lst) {
  if (length(lst) == 0) return(list())
  r <- rep(0, times = length(lst)); mx <- lst[1]; result <- list()
  for (i in 1:length(lst)) {
    r[i] <- abs(lst[i])
    mx <- max(mx, r[i])
  }
  for (fac in 2:mx) {
    isFactor <- FALSE; tot <- 0;
    for (i in 1:length(r)) {
      if (r[i] %% fac == 0) {
        isFactor <- TRUE
        tot <- tot + lst[i]
        while (r[i] %% fac == 0)
          r[i] <- r[i] / fac
      }
    }
    if (isFactor == TRUE)
      result <- c(result, list(c(fac, tot)))
  }
  result
}

yTests <- function() {
  i <- 0
  while (i < 100) {
    a <- floor(runif(1, 4, 8))
    ls <- floor(runif(n = a, min = 10, max = 10000))
    #print(ls)
    testing(ls, sumOfDivided098(ls))
    i <- i + 1
  }
}
test_that("Random tests", {
  yTests()
})

我的思路与代码

思路

我的想法很简单,首先,直接遍历(用repeat函数,这个我觉得看起来简洁)从2到max(abs(lst)),讲到这里,坑啊,必须得取绝对值,因为lst可以全是负数,或者最小的负数的绝对值大于最大的正数,这两种情况都会导致结果出问题。

接着,肯定不是每一个数都符合要求,因此需要添加if条件,我这里加了两个:第一,k必须要是lst中某一个数的因子;第二,新的k不能是已经找到的因子的倍数。

好了,要说的就这些了,没有其他特别重要的东西了。

代码

sumOfDivided <- function (lst) {
  if(is.null(lst)) {return(list())}
  k <- 2
  k.list <- c()
  result <- list()
  repeat{
    if(any(lst%%k == 0) & all(k%%k.list != 0)){
      result[[ length(k.list)+1 ]] <- c(k,sum(lst[lst%%k==0]))
      k.list <- c(k.list, k)
    }
    if(k >= max(abs(lst))){break}
    k <- k + 1
  }
  result
}

别人的代码

sumOfDivided <- function (lst) {
  n <- max(abs(as.integer(lst)), 0)
  p <- rep(TRUE, n)
  p[1] <- FALSE
  for (i in seq_len(sqrt(n))) {
    q <- min(which(cumsum(p) == i))
    p[seq_along(p) > q][c(logical(q - 1), TRUE)] <- FALSE
  }
  primes <- which(p)
  sums <- lapply(primes,
                 function(p, x) {
                   q <- x %% p
                   if(any(q == 0)) {
                     c(p, sum(x[q == 0]))
                   }
                 },
                 lst)
  sums[sapply(sums, length) > 0]
}

放这段代码的目的是学习一下seq_lenseq_along函数的,seq_len(n)1:n的作用是一样的,生成从1到n的向量。seq_along(seq)1:length(seq)的作用一样,在此不再多说了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三只佩奇不结义

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值