1

挑战:

德国极客播客Fanboys在他们最新的第 135 集中询问他们的观众,以检查即将播出的节目中的哪一集编号将是 2 级 Harshad 编号。

给定数字基数的Harshad 数是一个整数,当写入该基数时,它可以被其数字之和整除。

根据 Fanboys 的解释,一个 2 级 Harshad 数应是一个可被其数字之和整除的数,所得比率本身应为 Harshad 数。

解决方案(丑陋,待完善):

我尝试使用以下代码在 R 中解决此任务,并使用以下代码添加函数“two.step.harshed.number(start, end)”:

# Function to calculate the two-leveled Harshed Numbers for given integer number intervall

two.step.harshed.number = function(start, end) 
{ 
  # Function to calculate a digit sum
  digitsum = function (x) {sum(as.numeric(unlist(strsplit(as.character(x), split="")))) }

  # Function returning a numbers value if integer, otherwise NA
  checkinteger = function (x) {
    if (x%%1==0) {
      return (x)
    }
    else {
      return(NA)
    }
  }

  # Setup data frame with rows of numbers from start value to end value
  db = data.frame(number=start:end)  

  # 1st level run
  # Calculate the digit sum of those numbers
  db$digitsum1 = sapply(db$number, FUN=digitsum)
  # Calculate the ratio of number and it's digit sum and keep only if it's an integer 
  db$ratio1 = db$number / db$digitsum1
  db$ratio1 = sapply(db$ratio1, FUN=checkinteger) 
  db = na.omit(db)

  # 2st level run
  # Calculate the digit sum of the previous (integer) ratio 
  db$digitsum2 = sapply(db$ratio1, FUN=digitsum) 
  # Calculate the ratio of the previous ratio and it's digit sum and keep only if it's an integer
  db$ratio2 = db$ratio1 / db$digitsum2
  db$ratio2 = sapply(db$ratio2, FUN=checkinteger) 
  db = na.omit(db)

  # Return remaining number, which proved to be two-leveled Harshed Numbers
  return(db$number)
}

使用该功能时的挑战解决方案(下一集至第 200 集):

two.step.harshed.number(136, 200)

是一系列三个数字,对我来说似乎是正确的:

162 180 200

问题:

我知道这是一个初学者代码。我想创建另一个将任务概括为 n 步的函数。即函数“n.step.harshed.number(steps, start, end)”。 有什么想法可以实现这一点并使代码更高效吗?

4

1 回答 1

0

与此同时,我在简化和推广 Harshad 函数方面取得了一些进展:

# Function to calculate the n-leveled Harshad Numbers for given integer number intervall
multi.step.harshed.number = function(numlevels, start, end) 
{ 
  digitsum = function(x) sum(floor(x / 10^(0:(nchar(x) - 1))) %% 10)
  checkinteger = function (x) {
    ifelse (x == as.integer(x), return (x), return(NA))
  }
  db = data.frame(start:end)  
  for (i in 1:numlevels) {
    db[, (2*i)] = sapply(db[, (2*i)-1], FUN=digitsum) 
    db[, (2*i)+1] = db[, (2*i)-1] / db[, (2*i)]
    db[, (2*i)+1] = sapply(db[, (2*i)+1], FUN=checkinteger) 
    db = na.omit(db)
    if (nrow(db) == 0) break
  }  
  return(db[,1])
}

编辑:第二个版本 - 也许下面的代码更优雅,更不忙:

multi.step.harshed.number = function(numlevels, start, end) {
  is.integer= function(x) ifelse (x== as.integer(x), return (x), return(NA))
  digitsum = function(x) sum(floor(x/10^(0:(nchar(x)-1))) %% 10)
  digitsumratio= function(x) ifelse(is.integer(x/digitsum(x)), x/digitsum(x), NA) 
  multi.digitsumratio= function(iter, x) {
    for (i in 1:iter) x= digitsumratio(x)
    return (ifelse(is.na(x), FALSE, TRUE))     
  }
  sequence=start:end
  idx=sapply(sequence, FUN=function (x) multi.digitsumratio(numlevels, x))
  sequence[idx]
}

编辑:第 3 版 - 与第 2 版相同,但由于使用并行包而更快:

multi.step.harshed.number = function(numlevels, start, end) {
  library(parallel)
  processors= detectCores()
  cl= makeCluster(processors)
  is.integer= function(x) ifelse (x== as.integer(x), return (x), return(NA))
  digitsum = function(x) sum(floor(x/10^(0:(nchar(x)-1))) %% 10)
  digitsumratio= function(x) ifelse(is.integer(x/digitsum(x)), x/digitsum(x), NA) 
  multi.digitsumratio= function(iter, x) {
    for (i in 1:iter) x= digitsumratio(x)
    return (ifelse(is.na(x), FALSE, TRUE))     
  }
  sequence=start:end
  idx=parSapply(cl=cl,X=sequence, FUN=function (x) multi.digitsumratio(numlevels, x))
  sequence[idx]
}

尝试:multi.step.harshed.number(42, 100, 10000)返回:

 [1]   100   108   120   162   180   200   210   216   240   243   270   300   324   360   378   400   405   420   432   450
[21]   480   486   500   540   600   630   648   700   720   756   800   810   840   864   900   972  1000  1080  1200  1296
[41]  1458  1620  1800  1944  2000  2100  2160  2400  2430  2700  2916  3000  3240  3402  3600  3780  4000  4050  4200  4320
[61]  4374  4500  4800  4860  5000  5400  5832  6000  6300  6480  6804  7000  7200  7290  7560  8000  8100  8400  8640  8748
[81]  9000  9720 10000
于 2013-09-12T17:01:35.773 回答