2015-05-08 21 views
5

Vì vậy, tôi đang cố gắng làm điều gì đó tương tự như một người làm trang (danh sách số trang), nơi số hiện tại ở giữa hoặc gần nhất có thể làLấy số xung quanh một số

Mọi cách tôi giải quyết Thật khó và lạ, chỉ tự hỏi nếu có một cách mathy tốt đẹp để làm điều đó :)

đưa ra:

  • a: hiện số trang
  • x: số trang đầu tiên
  • y: trang cuối cùng số
  • n: số lượng yêu cầu

Tôi muốn tạo ra một danh sách các số nơi a là càng gần trung tâm như có thể, trong khi lưu trú trong vòng xy

do đó f(5, 1, 10, 5) sẽ trả lại [3, 4, 5, 6, 7] nhưng f(1, 1, 10, 5) sẽ trả về [1, 2, 3, 4, 5]f(9, 1, 10, 5) sẽ trả về [6, 7, 8, 9, 10]

Có ai có thể nghĩ ra một cách tốt đẹp để nhận được loại điều đó không?

Thực hiện theo cách có thể phức tạp trong ruby, có thể thực hiện đơn giản hơn không?

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 
+1

trong đó ngôn ngữ? – Nidhoegger

+0

Bất kỳ ngôn ngữ nào, tôi rất dễ dàng –

+0

Bạn muốn điều gì xảy ra nếu (y-x)

Trả lời

0

Như bạn sẽ không được đề cập đến ngôn ngữ mà bạn muốn điều này để làm, đây là một số mã giải thích tôi đặt lại với nhau trong 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; 
} 

Những gì nó về cơ bản là:

  1. Bắt đầu tại phần tử page - (count/2) (count/2 là tốt, bạn không cần phải trừ số không, ví dụ: 2.5 sẽ được làm tròn thành 2).
  2. Nếu phần tử bắt đầu nằm dưới first, bắt đầu từ đầu
  3. tiếp tục bổ sung các yếu tố đến kết quả chừng nào số trang hiện nay là nhỏ hơn hoặc bằng các LASTPAGE hoặc cho đến khi đủ các yếu tố được chèn
  4. Tiếp tục chèn yếu tố trong đầu miễn là có ít hơn count yếu tố trong Resultvector hoặc cho đến khi Element hiện tại nhỏ hơn trang đầu tiên

Đó là nỗ lực cơ bản của tôi ngay bây giờ. Mã có thể thực thi được.

+0

Cảm ơn, loại của nó tương tự như những gì tôi đang làm, nếu không phức tạp hơn :) Tôi đã hy vọng cho giải pháp toán học đơn giản , nếu một điều như vậy tồn tại –

0

Đây là những gì có vẻ là cách hiệu quả nhất đối với tôi. Sử dụng một mảng từ 1 đến n, tìm chỉ mục cho giá trị a. Đầu tiên tìm điểm trung tâm của các chỉ mục của mảng, sau đó kiểm tra xem số đó có gần một đầu hay điểm kia hay không và sửa đổi nó bằng sự khác biệt. Sau đó điền vào các giá trị.

Cần nhanh chóng thay vì lặp lại, nó sử dụng thuật toán để đến các số chỉ mục.

Mã giả:

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 
+0

Có lẽ ngay cả một cách để tính số centerindex trong một phép tính, nhưng điều đó sẽ mất nhiều thời gian hơn để tìm ra hơn là tôi phải chi cho vấn đề này. –

0

Sau khi viết những dòng này, tôi nhận ra nó rất giống với câu trả lời @ Nidhoegger của nhưng có lẽ nó sẽ giúp? PHP

<? 
//Assume 0 index pages 
$current = 2; 
$first = 1; 
$last = 10; 
$limit = 5; 
$page_counter = floor($limit/2); //start at half the limit, so if the limit is 5, start at current -2 (page 0) and move up 

$pages = array(); 

for ($i = 0; $i < $limit) { 
    $page_to_add = $current + $page_counter; 
    $page_counter++; 
    if ($page_to_add > $last) 
     break; 
    if ($page_to_add > -1) { 
     $i++; 
     $pages[] = $page_to_add; 
    } 
} 
?> 
+0

Nhận xét của bạn cho $ page_counter dường như không khớp với những gì nó làm; nó bắt đầu từ 2 không 0. $ page_to_add đầu tiên của bạn sẽ là 4. Nó cũng không "trung tâm" như anh ta muốn. –

1

Dưới đây là một cái gì đó loại mathy mà trả về số đầu tiên trong danh sách (mã 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); 
} 

Output:

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 
0

Tôi nghĩ rằng nó chỉ là một trong những vấn đề với rất nhiều trường hợp góc khó chịu.

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. 

hoặc, giả định nguyên thủy cấp cao hơn, nếu bạn thích:

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. 
Các vấn đề liên quan