获取数字

时间:2015-05-08 15:01:39

标签: algorithm math language-agnostic

所以,我正在尝试做一些类似于paginator(页码列表)的事情,其中​​当前的数字在中间或尽可能接近

我解决它的每一种方式都很难和奇怪,只是想知道是否有一种不错的方式来做它:)

下式给出:

  • a:当前页码
  • x:首页编号
  • y:最后一页编号
  • n:需要号码

我希望生成一个数字列表,其中a尽可能靠近中心,同时保持在xy

所以f(5, 1, 10, 5)会返回[3, 4, 5, 6, 7] 但是f(1, 1, 10, 5)会返回[1, 2, 3, 4, 5]f(9, 1, 10, 5)将返回[6, 7, 8, 9, 10]

有人能想出一种很好的方式来获得那种东西吗?

在ruby中以一种可能复杂的方式实现,可以更简单吗?

def numbers_around(current:, total:, required: 5)
  required_before = (required - 1) / 2
  required_after = (required - 1) / 2

  before_x = current - required_before
  after_x = current + required_after

  if before_x < 1
    after_x += before_x.abs + 1
    before_x = 1
  end

  if after_x > total
    before_x -= (after_x - total)
    after_x = total
  end

  (before_x..after_x)
end

5 个答案:

答案 0 :(得分:1)

这里有一些东西可以返回列表中的第一个数字(JavaScript代码):

function f(a,x,y,n){
  var m = n >> 1;
  return x * (n > y - x) || a - m
                          + Math.max(0,m - a + x)
                          - Math.max(0,m - y + a);
}

输出:

console.log(f(5,1,10,5)); // 3
console.log(f(1,1,10,5)); // 1
console.log(f(9,1,10,5)); // 6
console.log(f(2,1,10,5)); // 1
console.log(f(11,1,10,5)); // 6
console.log(f(7,3,12,10)); // 3

答案 1 :(得分:0)

由于您不想提及您希望这样做的语言,以下是我在C ++中编写的一些解释代码:

std::vector<int> getPageNumbers(int first, int last, int page, int count) {
    int begin = page - (count / 2);
    if (begin < first) {
        begin = first;
    }
    int cur = 0;
    std::vector<int> result;
    while (begin + cur <= last && cur < count) {
        result.push_back(begin + cur);
        ++cur;
    }
    cur = 0;
    while (begin - cur >= first && result.size() < count) {
        ++cur;
        result.insert(result.begin(), begin-cur);
    }
    return result;
}


int main() {
    std::vector<int> foo = getPageNumbers(1,10,10,4);
    std::vector<int>::iterator it;
    for (it = foo.begin(); it != foo.end(); ++it) {
        std::cout << *it << " " << std::endl;
    }
    return 0;
}

它的作用基本上是:

  1. 从元素page - (count/2)开始(count/2很好,您不需要减零,因为例如2.5将四舍五入到2)。
  2. 如果start元素低于first,请先从
  3. 开始
  4. 只要当前页码小于或等于最后一页或插入足够的元素,就继续向结果添加元素
  5. 只要在Resultvector中的元素少于count或者当前元素小于第一页
  6. ,就继续在元素的开头插入元素。

    这是我现在的基本尝试。代码是可执行的。

答案 2 :(得分:0)

这对我来说似乎是最有效的方式。使用从1到n的数组,找到a值的索引。首先找到数组索引的中心点,然后检查数字是否接近一端或另一端,并根据差异进行修改。然后填写值。

它应该很快,因为它不是迭代,而是使用算法来得到索引号。

伪代码:

centerindex = Ceiling(n/2, 1)

If (y-a) < (n - centerindex) Then centerindex = 2 * centerindex - (y - a) - 1

If (a-x) < (n - centerindex) Then centerindex = (a - x) + 1

For i = 1 to n
  pages(i) = a - (centerindex - i)
Next i

答案 3 :(得分:0)

写完这篇文章之后,我意识到这与@ Nidhoegger的回答非常相似,但也许会有所帮助? PHP

var p;
[1,2,3,4,5,6,7,8,9,10].forEach(function(i){
     p = $.when(p, delay(i,i * 500));
});
p.then(function(){
   log("All done");
});

答案 4 :(得分:0)

我认为这只是其中一个问题,其中有很多烦人的角落案例。

start = a - (n / 2);
if (start < x) start = x;   // don't go past first page.
end = start + (n - 1);      // whereever you start, proceed n pages
if (end > y) {              // also don't go past last page.
  end = y;
  start = end - (n - 1);    // if you hit the end, go back n pages
  if (start < x) start = x; // but _still_ don't go past first page (fewer than n pages)
}
// make some kind of vector [start..end] inclusive.

或者,假设更高级别的原语,如果您愿意:

start = max(x, a - (n / 2))   // (n/2) pages before but don't pass x
end = min(start + (n - 1), y) // n pages long, but don't pass y
start = max(x, end - (n - 1)) // really n pages long, but really don't pass x
// make some kind of vector [start..end] inclusive.