2015-05-08 38 views
5

Also, ich versuche, etwas ähnliches zu einer paginator (Liste der Seitenzahlen), wo die aktuelle Zahl in der Mitte zu tun, oder so nah wieErste Zahlen um eine Reihe

Jeder Weg kann ich es lösen ist hart und komisch, nur fragen, ob ein netter mathy Weg dorthin es

gegeben zu tun ist :):

  • a: aktuelle Seitenzahl
  • x: erste Seitenzahl
  • y: letzte Seitenzahl
  • n: Nummer erforderlich

ich eine Liste von Zahlen erzeugen möchten, wo a so nah an der Mitte ist wie sein kann, während des Aufenthaltes in x und y

würde so f(5, 1, 10, 5) würde [3, 4, 5, 6, 7] zurückgeben aber f(1, 1, 10, 5) würde zurückgeben [1, 2, 3, 4, 5] und f(9, 1, 10, 5) würdezurückgeben

Kann mir jemand einen schönen Weg vorstellen, so etwas zu bekommen?

In einer wahrscheinlich komplizierten Weise in Rubin implementiert, kann es einfacher gemacht werden?

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

in welcher Sprache? – Nidhoegger

+0

Jede Sprache, ich bin einfach –

+0

Was möchten Sie tun, wenn (y-x)

Antwort

0

Wie man wird nicht die Sprache, die Sie dies hier tun möchte erwähnen werden, ist einige erläutert Code, den ich zusammen in C setzen ++:

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; 
} 

Was sie tut, ist im Grunde:

  1. Beginnen Sie am Element page - (count/2) (count/2 ist in Ordnung, Sie müssen nicht Null abziehen, wie zB 2.5 wird auf 2 gerundet werden).
  2. Wenn Startelement unterhalb first ist, beginnen zunächst
  3. Halten Elements zu dem Ergebnis Zugabe solange aktuelle Seitennummer kleiner oder gleich ist der LASTPAGE oder bis genügend Elemente eingesetzt sind
  4. Halten auf Elemente am Anfang Einfügen solange es weniger als count Elemente in der Resultvector oder bis das aktuelle Element ist kleiner als die erste Seite

das jetzt mein Grund Versuch ist. Der Code ist ausführbar.

+0

Danke, es ist ähnlich wie ich, wenn nicht komplizierter :) Ich habe auf einfache mathematische Lösung gehofft Wenn es so etwas gibt –

0

Hier ist, was scheint der effizienteste Weg zu mir. Suchen Sie mit einem Array von 1 bis n den Index für den Wert a. Suchen Sie zuerst den Mittelpunkt der Indizes des Arrays, dann prüfen Sie, ob die Zahl nahe dem einen oder anderen Ende ist, und ändern Sie sie um den Unterschied. Dann fülle die Werte aus.

Es sollte schnell sein, da es anstelle der Iteration Algorithmen verwendet, um die Indexnummern zu erhalten.

Pseudocode:

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

Es gibt wahrscheinlich sogar eine Möglichkeit, die centerindex Nummer in einer Berechnung zu berechnen, aber das würde mehr Zeit brauchen, um herauszufinden, als ich für dieses Problem ausgeben muss. –

0

Danach schreiben, ich erkennen, dass es sehr ähnlich ist zu @ Nidhoegger Antwort, aber vielleicht wird es helfen?

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

Ihr Kommentar zu $ ​​page_counter scheint nicht zu dem zu passen, was er tut; Es beginnt bei 2 nicht 0. Ihre erste $ page_to_add wäre 4. Es zentriert auch nicht wie er wollte. –

1

Hier ist etwas Art von mathy, die die erste Zahl in der Liste zurück (JavaScript-Code):

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); 
} 

Ausgang:

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

Ich denke, es ist nur eines dieser Probleme mit vielen nervigen Eckfällen.

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. 

oder höherer Ebene Primitiven unter der Annahme, wenn Sie es vorziehen:

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. 
Verwandte Themen