How did dotnetkicks.com implement their ASP.NET paging? - asp.net

I know the dotnetkicks.com system is open source so I can view the code myself but I can't make sense of how they did their paging. It's hard to explain but if you goto dotnetkicks.com you can play with the paging on their front page.
What I am specifically interested in is how they show the first few pages, then "..." and then the last few pages.
It starts off like this
Prev 1 2 3 4 5 6 ... 355 356 Next
Then if you hit page 10 it changes to this
Prev 1 2 ... 6 7 8 9 10 11 12 13 14 ... 355 356 Next
It's by far my favorite paging system so I'd like to do the same thing on my websites

The Pagination control in the project is fairly straight forward, if you've ever written a paging control. I think what may be confusing you is the use of urlrewriting.net for the /page/n url format.

I've written such a control and it took some code... there are plenty decisions to take.
public class SimplePagerLinkGenerator : IPagerLinkGenerator
{
private PagingDisplaySettings _displaySettings;
public SimplePagerLinkGenerator(PagingDisplaySettings displaySettings)
{
this._displaySettings = displaySettings;
}
public PageLinkData[] GetPagesLinkData(uint crtPageIndex, uint pageCount, ushort pageSize,
string urlLinkTemplate)
{
int i, crtPage = (int)crtPageIndex, pageCnt = (int)pageCount,
pgInnerCnt = (int)this._displaySettings.PagesBeforeOrAfterCurrent,
pgEndCnt = (int)this._displaySettings.PagesShownAtEndingsCount;
int innerBlockStart = crtPage - pgInnerCnt;
int innerBlockEnd = crtPage + pgInnerCnt;
int innerBlockStartNormalized = innerBlockStart < 1 ? 1 : innerBlockStart;
int innerBlockEndNormalized = innerBlockEnd > pageCount ? pageCnt : innerBlockEnd;
List<PageLinkData> result = new List<PageLinkData>(2 * pgEndCnt + 3 + 2 * pgInnerCnt);
for (i = 1; i <= pgEndCnt && i <= pageCount; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
if (i > pageCount)
return result.ToArray();
if (innerBlockStart > pgEndCnt + 1)
{
result.Add(PageLinkData.Ellipsis);
for (i = innerBlockStart; i <= innerBlockEndNormalized; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
}
else
for (i = pgEndCnt + 1; i <= innerBlockEndNormalized; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
if (innerBlockEnd < pageCount - pgInnerCnt)
{
result.Add(PageLinkData.Ellipsis);
for (i = pageCnt - pgInnerCnt + 1; i <= pageCount; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
}
else
for (; i <= pageCount; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
return result.ToArray();
}
public PagingDisplaySettings DisplaySettings { get { return this._displaySettings; } }
}

Related

Why do I get a StackOverFlow error on the first recursive call?

Below is the code I am referring to, and the first recursive call # checkDirections(grid, i - 1, j) is giving me a StackOverFlow error. I understand that this means the code is not hitting the base case, but I do not understand why.
class Solution {
public int orangesRotting(int[][] grid) {
int rowLength = grid.length;
int colLength = grid[0].length;
int minMinutes = 0;
for (int i = 0; i < rowLength; i++) {
for (int j = 0; j < colLength; j++) {
if (grid[i][j] == 2) {
checkDirections(grid, i, j);
}
}
}
return minMinutes;
}
public void checkDirections(int[][] grid, int i, int j) {
if ((i < 0 || i > grid.length || j < 0 || j > grid[0].length) || grid[i][j] == 0) {
return;
} else if (grid[i][j] == 1) {
grid[i][j] = 2;
return;
}
//check left
checkDirections(grid, i - 1, j);
//check right
checkDirections(grid, i + 1, j);
//check up
checkDirections(grid, i, j - 1);
//check down
checkDirections(grid, i, j + 1);
}
}

Game Of Life ends quickly (Java)

I've created a basic version of the Game Of Life: each turn, the board is simulated by a 2D array of 1's and 0's, after which another class creates a drawing of it for me using the 2d array
I've read all the other questions here regarding this game, but no answer seems to work out for me....sorry if I'm beating a dead horse here.
I think I have a problem with my algorithm, thus maybe the board gets filled with the wrong amount of dead and alive cells and thus ends rather quickly (5-10 turns).
I've found an algorithm here to scan all the neighbors and even added a count = -1 in case it a cell in the grid scans itself as it's own neighbor, but I think I'm missing something here.
public static void repaint(board game, int size,int[][] alive, int[][] newGeneration)
{
int MIN_X = 0, MIN_Y = 0, MAX_X =9, MAX_Y =9, count;
for ( int i = 0; i < size; i++ )
{
for (int j = 0; j < size; j++) //here we check for each matrix cell's neighbors to see if they are alive or dead
{
count = 0;
if (alive[i][j] == 1)
count = -1;
int startPosX = (i - 1 < MIN_X) ? i : i - 1;
int startPosY = (j - 1 < MIN_Y) ? j : j - 1;
int endPosX = (i + 1 > MAX_X) ? i : i + 1;
int endPosY = (j + 1 > MAX_Y) ? j : j + 1;
for (int rowNum = startPosX; rowNum <= endPosX; rowNum++)
{
for (int colNum = startPosY; colNum <= endPosY; colNum++)
{
if (alive[rowNum][colNum] == 1)
count++;
}
}
if (alive[i][j] == 0 && count == 3) //conditions of the game of life
newGeneration[i][j] = 1; //filling the new array for the next life
if (alive[i][j] == 1 && count < 2)
newGeneration[i][j] = 0;
if (alive[i][j] == 1 && count >= 4)
newGeneration[i][j] = 0;
if (alive[i][j] == 1 && count == 3)
newGeneration[i][j] = 1;
}
}
game.setAlive(newGeneration); //we created a new matrix with the new lives, now we set it
SetupGUI(game,size); //re drawing the panel
}
}
What am I doing wrong? thanks for the help.

Recursive Method StackOverflow Error - Minesweeper

I am writing the recursive method for a minesweeper game and I am encountering a stackOverflow error in the recursive method that clears out empty spaces, The error does not occur when checking for 3 of the surrounding spaces but only when checking all eight. Can you please help identify the issue?
The stack trace is :
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at java.awt.Component.firePropertyChange(Component.java:8419)
at javax.swing.AbstractButton.setText(AbstractButton.java:306)
at Minesweeper.Minesweeper.showTile(Minesweeper.java:105)
at Minesweeper.Minesweeper.clearEmpty(Minesweeper.java:137)
at Minesweeper.Minesweeper.clearEmpty(Minesweeper.java:177)
The class:
public class Minesweeper implements ActionListener {
JFrame frame = new JFrame("Minesweeper");
JButton reset = new JButton("Reset");
JButton solve = new JButton("Solve");
JToggleButton[][] buttons = new JToggleButton[20][20];
int[][] counts = new int [20][20];
Container grid = new Container();
final int MINE = 10;
public static void main(String[] args)
{
new Minesweeper();
}
public Minesweeper()
{
frame.setSize(600, 600);
frame.setLayout(new BorderLayout());
frame.add(reset, BorderLayout.NORTH);
frame.add(solve, BorderLayout.SOUTH);
reset.addActionListener(this);
solve.addActionListener(this);
grid.setLayout(new GridLayout(20, 20));
for (int r = 0; r < buttons.length; r++) {
for (int c = 0; c < buttons[0].length; c++) {
buttons[r][c] = new JToggleButton();
buttons[r][c].addActionListener(this);
grid.add(buttons[r][c]);
buttons[r][c].setSize(frame.getWidth() / 20, frame.getHeight() / 22);
}
}
frame.add(grid,BorderLayout.CENTER);
addRandomMines();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void addRandomMines()
{
ArrayList<Integer> mineList = new ArrayList<Integer>();
for (int x = 0; x < counts.length; x++) {
for (int y = 0; y < counts[0].length; y++){
mineList.add((x*100)+y);
}
}
counts = new int[20][20];
for (int i = 0; i < 30; i++) {
int choice = (int)(Math.random()*mineList.size());
counts[mineList.get(choice)/100][mineList.get(choice)%100] = MINE;
mineList.remove(choice);
}
for (int x = 0; x < counts.length; x++) {
for (int y = 0; y < counts[0].length; y++){
if (counts[x][y]!=MINE) {
int mineCount = 0;
if (x > 0 && y > 0 && counts[x - 1][y - 1] == MINE)
mineCount++;
if (y > 0 && counts[x][y - 1] == MINE)
mineCount++;
if (x > 0 && counts[x - 1][y] == MINE)
mineCount++;
if (x < counts.length - 1 && counts[x + 1][y] == MINE)
mineCount++;
if (y < counts.length - 1 && counts[x][y + 1] == MINE)
mineCount++;
if (x < counts.length - 1 && y < counts.length - 1 && counts[x + 1][y + 1] == MINE)
mineCount++;
if (x > 0 && y < counts.length - 1 && counts[x - 1][y + 1] == MINE)
mineCount++;
if (x < counts.length - 1 && y > 0 && counts[x + 1][y - 1] == MINE)
mineCount++;
counts[x][y] = mineCount;
}
}
}
}
public void showTile(int r, int c)
{
if (counts[r][c] == 0) {
buttons[r][c].setText("");
buttons[r][c].setSelected(true);
}
else if (counts[r][c]==MINE) {
buttons[r][c].setForeground(Color.red);
buttons[r][c].setText("X");
buttons[r][c].setSelected(true);
}
else {
buttons[r][c].setText(counts[r][c] + "");
if (counts[r][c]==1)
buttons[r][c].setForeground(Color.blue);
else if (counts[r][c]==2)
buttons[r][c].setForeground(Color.magenta);
else if (counts[r][c]==3)
buttons[r][c].setForeground(Color.green);
buttons[r][c].setSelected(true);
}
}
public void lostGame() {
for (int x = 0; x < buttons.length; x++) {
for (int y = 0; y < buttons[0].length; y++) {
if (counts[x][y]==MINE) {
showTile(x, y);
}
}
}
}
public void clearEmpty(ArrayList<Integer> toClear)
{
if (toClear.size()==0){
return;
}
else {
int x = toClear.get(0)/100;
int y = toClear.get(0)%100;
toClear.remove(0);
if (counts[x][y]==0) {
if (x > 0 && y > 0) {
showTile(x-1,y-1);
if (counts[x-1][y-1]==0)
toClear.add((x-1)*100 + (y-1));
}
if (y > 0) {
showTile(x,y-1);
if (counts[x][y-1]==0)
toClear.add(x*100 + (y-1));
}
if (x <counts.length-1 && y > 0) {
showTile(x+1,y-1);
if (counts[x+1][y-1]==0)
toClear.add((x+1)*100 + (y-1));
}
if (x > 0) {
showTile(x-1,y);
if (counts[x-1][y]==0)
toClear.add((x-1)*100 + y);
}
if (x <counts.length-1 && y > 0) {
showTile(x+1,y);
if (counts[x+1][y]==0)
toClear.add((x+1)*100 + y);
}
if (x > 0 && y < counts[0].length-1) {
showTile(x-1,y+1);
if (counts[x-1][y+1]==0)
toClear.add((x-1)*100 + (y+1));
}
if (y < counts[0].length-1) {
showTile(x,y+1);
if (counts[x][y+1]==0)
toClear.add(x*100 + (y+1));
}
if (x <counts.length-1 && y < counts[0].length-1) {
showTile(x+1,y+1);
if (counts[x+1][y+1]==0)
toClear.add((x+1)*100 + (y+1));
}
}
clearEmpty(toClear);
}
}
#Override
public void actionPerformed(ActionEvent event) {
if (event.getSource().equals(reset)) {
for (int r = 0; r < buttons.length; r++) {
for (int c = 0; c < buttons[0].length; c++) {
buttons[r][c].setSelected(false);
buttons[r][c].setText("");
}
}
addRandomMines();
} else if (event.getSource().equals(solve)) {
} else {
for (int r = 0; r < buttons.length; r++) {
for (int c = 0; c < buttons[0].length; c++) {
if (event.getSource().equals(buttons[r][c])) {
if (counts[r][c] == MINE) {
showTile(r, c);
lostGame();
}
else if (counts[r][c] == 0) {
ArrayList<Integer> toClear = new ArrayList<Integer>();
toClear.add(r*100+c);
clearEmpty(toClear);
}
else {
showTile(r, c);
}
}
}
}
}
}
}
I think that you're using the wrong algorithm...
Try to use an iterative instead of an recursive approach.
As User404 already mentioned your current algorithm keeps the list growing...
For your implementation: you have 400 tiles. Assuming (worst case) all tiles are empty you call your method clearEmpty() once. You will find out that all 8 neighbors are empty so you add this 8 neighbors to the list while only removing the first one. Now you pass the array to the method again (2nd call) and will find 8 neighbors for the first entry again. So your 3rd call will have a list with 15 tiles.
Real problem
This way you will never come to an end as you never check if the current checked tile is already cleared but you only add to the list more than you will ever remove.
Solution
At least you should check if the tile you want to add to the list is already cleared or is already in the list.
You example is a clear example why recursive algorithms should be used with care as the termination is difficult sometimes and also you have to take care that no work is done multiple times.

When using scanf/cin, program works fine in debug mode but gives runtime error

I'm trying to take to the following input:
1
4
47 2 4 43577
The part of my code that deals with this is:
for (scanf("%d", &t); t --; )
{
int count = 0;
scanf("%d",&n);
for (int i = 0, x; i < n; ++ i)
{
scanf("%d",&x);
str = to_string(x);
f4[i] = get_count(str,'4');
f7[i] = get_count(str,'7');
}
However, with this I get a runtime error, which shows an access violation in the file free.c.
But, when I try to debug it, it runs well in the debug mode and gives the correct answer.
Also, when I output the variable x right after I input it, the program works well in runtime as well. This is shown in the following code, which runs fine in runtime as well:
for (scanf("%d", &t); t --; )
{
int count = 0;
scanf("%d",&n);
for (int i = 0, x; i < n; ++ i)
{
scanf("%d",&x);
cout<<"A"<<i<<" is "<<x<<'\n';
str = to_string(x);
f4[i] = get_count(str,'4');
f7[i] = get_count(str,'7');
}
Any idea why this may be happening?
Some of the stackoverflow users are saying that the code runs fine. I'm using VS 2012. Can this be something that is compiler specific?
The complete code:
#include<iostream>
#include<conio.h>
#include<string>
#include<math.h>
using namespace std;
int get_count(string s, char x)
{
int count = 0;
int l = s.length();
for(int i = 0; i < l;i++)
{
if (s[i] == x)
count++;
}
return count;
}
void main()
{
int * f4 = new int;
int * f7 = new int;
string * back = new string;
int n = 0;
int t = 0;
string str;
for (scanf("%d", &t); t --; )
{
int count = 0;
scanf("%d",&n);
for (int i = 0, x; i < n; ++ i)
{
scanf("%d",&x);
str = to_string(x);
f4[i] = get_count(str,'4');
f7[i] = get_count(str,'7');
}
for(int i = 0;i < n;i++)
{
for(int j = i; j < n;j++)
{
int c4 = 0;
int c7 = 0;
for(int k = i; k <= j;k++)
{
c4 += f4[k];
c7 += f7[k];
}
double value = pow((double)c4,(double)c7);
if(value <= (double)(j - i + 1)&&(c4!=2)&&(c7!=2))
{
count++;
//cout<<"yes"<<'\t';
}
}
}
cout<<"Ans: "<<count<<'\n';
}
//getch();
}
There are no other variable assignments apart from those in this code.
The exact error that I get with runtime is:
Unhandled exception at 0x7794E3BE (ntdll.dll) in Practice1.exe: 0xC0000005: Access violation reading location 0x38389246.
You did not include the "get_count" function. I think it has something to do with that function. I rewrote that function to return some number and I don't get that error. Try to assert that you are not attempting to use a null pointer in that function.
Works fine on my machine:
Here's what I changed
for (int i = 0, x; i < n; ++ i)
{
scanf("%d",&x);
stringstream ss;
ss << x;
str = ss.str();
f4[i] = get_count(str,'4');
f7[i] = get_count(str,'7');
}
Output:
1
4
47 2 4 43577
Ans: 5

Changing method to be completely recursive

void merge(List<E> l, int lower, int upper) {
ArrayList<E> array = new ArrayList<E>();
for (int i = lower; i <= upper; i++)
array.add(list.get(i));
int front= 0;
int front2= (array.size() + 1) / 2;
for (int i = lower; i <= upper; i++) {
if (front2 >= array.size() ||
(first < ((array.size() + 1) / 2) &&
(array.get(first).compareTo(array.get(second)) <= 0))) {
l.set(i, array.get(front));
front++;
}// end if
else {
l.set(i, array.get(front2));
front2++;
}
}
}
This is my method. I want to change it to be completely recursive(I don't want to use for loops), but I simply don't see how. Is there a way to make this recursive or avoid using loops?

Resources