Codewars I - Pagination Helper

What is Codewars? - ¿Qué es Codewars?

Untitled.png

Codewars is an educational community for systems programming. On the platform, software developers participate in programming challenges known as kata. These exercises train a range of skills in a variety of programming languages and are completed within an integrated online development environment, where users have the chance to earn ranks and honor.

According to its own page: “Codewars is a platform that helps you learn, train, and improve your coding skills by solving programming tasks of many types and difficulty levels. You choose how you would like to learn. Do you want to take on increasingly difficult challenges? Maybe you prefer training through repetition and by improving your solutions. After solving a task, compare your answer with other users and learn from them or help less experienced users by answering their questions.”

Codewars es una comunidad educativa de programación de sistemas. En la plataforma, los desarrolladores de software participan en desafíos de programación conocidos como kata. Estos ejercicios entrenan un rango de habilidades en una variedad de lenguajes de programación y se completan dentro de un ambiente de desarrollo integrado en línea, en el que los usuarios tienen la posibilidad de ganar rangos y honor.
Según su propia página: “Codewars es una plataforma que te ayuda a aprender, entrenar y mejorar tus habilidades de codificación resolviendo tareas de programación de muchos tipos y niveles de dificultad. Tú eliges cómo quieres aprender. ¿Quieres enfrentarte a retos cada vez más difíciles? Tal vez prefieras entrenarte mediante la repetición y la mejora de tus soluciones. Después de resolver una tarea, compara tu respuesta con la de otros usuarios y aprende de ellos o ayuda a los usuarios menos experimentados respondiendo a sus preguntas.”

My intention with this series of posts is to solve a kata, explain it and analyze the answers from other users to see where I could have improved my code.

Mi intención con esta serie de posts es resolver un kata, explicarlo y analizar las respuestas de otros usuarios para ver en qué podía haber mejorado mi código.

Kata: Pagination Helper - 5 kyu

Situation: For this exercise you will be strengthening your page-fu mastery. You will complete the "PaginationHelper" class, which is a utility class helpful for querying paging information related to an array. The class is designed to take in an array of values and an integer indicating how many items will be allowed per each page. The types of values contained within the collection/array are not relevant. The following are some examples of how this class is used:

Captura de pantalla 2024-06-05 113520.png

Situación: Con este ejercicio reforzarás tu dominio del page-fu. Completarás la clase "PaginationHelper", que es una clase de utilidad que te ayudará a consultar información de paginación relacionada con un array. La clase está diseñada para tomar un array de valores y un número entero que indica cuántos elementos serán permitidos por cada página. Los tipos de valores contenidos en la colección/array no son relevantes. A continuación se ofrecen algunos ejemplos de uso de esta clase:

So, you have to complete this empty class:

Captura de pantalla 2024-06-04 132905.png

Captura de pantalla 2024-06-04 132952.png

Tienes que completar esta clase vacía:

The first thing is simple. We simply have to complete the constructor of the class. We create 2 class fields and initialize them in the constructor, since the “PaginationHelper” class instance must accept a list of items and a certain number of items per page.

Captura de pantalla 2024-06-05 114505.png

Lo primero es sencillo. Simplemente hay que completar el constructor de la clase. Creamos 2 campos de clase y los inicializamos en el constructor, ya que la instancia de la clase “PaginationHelper” debe aceptar una lista de artículos y una cierta cantidad de artículos por página.

Then the number of items in the list, something simple as well. To access it we simply invoke the “Count” property of the generic class “List<>”.

Captura de pantalla 2024-06-05 114542.png

Luego la cantidad de artículos en la lista, algo sencillo igualmente. Para acceder a ello simplemente invocamos la propiedad “Count” de la clase genérica “List<>”.

The next thing we need to do is to complete this read-only property, which should return the number of pages our book will have. We take the number of items in the collection and divide it by the number of items per page, if the remainder of that division is 0, then the number of pages will be the quotient of that division. Think of it this way: if the number of items is divisible by the maximum number of items per page, that means that the quantity on each page will always be the same and, therefore, that no items will be left over. The remainder of the division represents the leftover items, which we will have to put in an extra page; that is why in our next code block (whose condition to be fulfilled would be that the remainder is different from 0), we add 1 extra page to the quotient of the division.

Captura de pantalla 2024-06-05 114616.png

Lo siguiente que debemos hacer completar esta propiedad de sólo lectura, que debe devolver la cantidad de páginas que tendrá nuestro libro. Tomamos la cantidad de artículos de la colección y la dividimos entre la cantidad de artículos por página, si el resto de dicha división es 0, entonces la cantidad de páginas será el cociente de dicha división. Piénsalo de este modo: si el número de artículos es divisible por la cantidad máxima de artículos por página, eso significa que la cantidad en cada página siempre será la misma y, por lo tanto, que no sobrará ningún artículo. El resto de la división representan los artículos que nos sobran, los cuales tendremos que meter en una página extra; es por eso que en nuestro siguiente bloque de código (cuya condición a cumplir sería que el resto fuera diferente de 0), le sumamos 1 página extra al cociente de dicha división.

In the next method what we have to do is to return the number of articles in a certain page that we will take as a parameter. The page count is zero-based index (it starts from 0, so page number 1 of the book would be indicated by the number 0). If the indicated number is outside the page limit, -1 must be returned.

As long as it is not the last page, all the other pages will have the same number of items. It is on the last page where we must focus our attention. As we saw in the previous code, if the remainder of the division is not equal to 0, the book will have one more page, with the number of articles left over, that is, the remainder of the division.

For some reason that I still do not understand, this code does not work for me in Codewars. However on my PC it works correctly, taking the same data that Codewars uses to make its Tests. If anyone uses the site and has any idea why this is happening, please let me know in a comment.

Captura de pantalla 2024-06-05 114506.png

En el método siguiente lo que debemos hacer es devolver la cantidad de artículos que hay en cierta página que tomaremos por parámetro. El conteo de las páginas comienza por 0 (o sea que la página número 1 del libro se indicaría mediante el número 0). Si el número indicado está fuera del límite de páginas, se debe devolver -1.
Siempre, mientras no se trate de la última página, todas las demás tendrán el mismo número de artículos. Es en la última página donde debemos centrar nuestra atención. Y es que como vimos en el código anterior, si el resto de la división nos da distinto de 0, el libro tendrá una página más, con la cantidad de artículos que nos sobran, o sea el resto de la división.
Por alguna razón que todavía no comprendo, este código no me funciona en Codewars. Sin embargo en mi PC funciona correctamente, tomando los mismos datos que usa Codewars para hacer sus Tests. Si alguien usa la página y tiene idea de por qué sucede esto que me lo diga en un comentario, por favor.

However, after racking my brain guessing why the previous one didn't work I ended up changing it for this one, which worked perfectly. The problem with these conditional blocks is that there is a redundancy in some conditions. For example:

  • In the first block I discard the values that are out of the page range, so only the valid values would remain.
  • In the second block I discard the last page, as long as the remainder of the division between the number of items in the collection and the number of items per page is 0.
  • In the third one I do the same as in the previous one but if the rest is different from 0.
  • The fourth and fifth blocks are completely unnecessary. Each conditional block works as a filter, so if certain values have already been filtered in the previous conditionals, it is not necessary to express it again in the next one. The fourth is a redundancy. And I put the fifth one because not all code access paths returned a value.

Captura de pantalla 2024-06-05 143931.png

No obstante, luego de romperme la cabeza adivinando por qué el anterior no funcionaba terminé cambiándolo por este, que funcionó perfectamente. El problema con estos bloques condicionales es que hay una redundancia en algunas condiciones. Por ejemplo:

  • En el primer bloque descarto los valores que estén fuera del rango de páginas, por lo que quedarían solamente los valores válidos.
  • En el segundo bloque descarto la última página, siempre y cuando el resto de la división entre la cantidad de artículos de la colección y la cantidad de artículos por página sea 0.
  • En el tercero hago lo mismo pero si el resto es diferente de 0.
  • El cuarto y el quinto bloques son totalmente innecesarios. Cada bloque condicional funciona como un filtro, por lo que si ya ciertos valores han sido filtrados en los condicionales anteriores, no es necesario volver a expresarlo en el siguiente. El cuarto es una redundancia. Y el quinto lo puse porque no todas las rutas de acceso de código devolvían un valor.

After refactoring the above code, the method looks like this:

Captura de pantalla 2024-06-05 144048.png

Luego de refactorizar el código anterior, el método queda como sigue:

Finally we have the “PageIndex” method, which takes as parameters the index of an article in the collection and returns the page to which the article belongs. Again, both the article index and the page index are zero-based index.

If we divide the index by the number of articles on each page, we get the index of the page it belongs to. To check this, let's do the following: let's suppose that the collection has 18 articles, and that each page contains 4 of these. We see that from 0 to 3, that is, the first 4 articles, the quotient of this division is equal to 0, the first page. The following ones would no longer be on the first page, since we would exceed the maximum amount per page and, if we make the division, we see that in effect the quotient (1) tells us that the articles from 4 to 7 are on the second page of the book.

The first conditional block filters out those items that are within the collection, while the second deals with the remainder, those that are outside the range.

Captura de pantalla 2024-06-05 144302.png

Por último tenemos el método “PageIndex”, que toma por parámetros el índice de un artículo en la colección y devuelve la página a la que pertenece dicho artículo. De nuevo, tanto el índice del artículo como el índice de la página comienzan por 0.
Si dividimos el índice por la cantidad de artículos en cada página, nos dará como resultado el índice de la página a la que pertenece. Para comprobarlo hagamos lo siguiente: supongamos que la colección tiene 18 artículos, y que cada página contiene 4 de estos. Vemos que de 0 a 3, o sea, los 4 primeros artículos, el cociente dicha división es igual a 0, la primera página. Los siguientes ya no estarían en la primera, pues superaríamos la cantidad máxima por página y, si efectuamos la división, vemos que en efecto el cociente (1) nos dice que los artículos del 4 al 7 se encuentran en la segunda página del libro.
El primer bloque condicional filtra aquellos artículos que están dentro de la colección, mientras que el segundo lidia con los restantes, aquellos que están fuera del rango.

Alternative solutions - [Soluciones alternativas]

Users zabihy and TomaszCitko propose the following solution as an alternative to mine. The first difference between their code and mine is in the order of the conditionals, which allows them to refactor the code in a better way:

  • The first block filters out values that are out of range.
  • The second filters out those within range, except for the last page of the book. Needless to say: those values below the last page and above -1. Although this condition includes those less than or equal to -1, the previous block already filtered those negative values, so it will not take them into account this time. It would therefore be redundant to include such a condition.
  • Then, since only the last page remains to be analyzed, the third block does not need to specify that it is the last page, but simply focus on whether the remainder of the division is 0.
  • And in the last block there is only one option left: to analyze if the remainder of the division is different from 1.

Captura de pantalla 2024-06-05 150352.png

Los usuarios zabihy y TomaszCitko proponen la siguiente solución como alternativa a la mía. La primera diferencia entre su código y el mío está en el orden de los condicionales, lo cual le permite refactorizar el código de mejor manera:

  • El primer bloque filtra los valores que están fuera de rango.
  • El segundo filtra los que están dentro de rango, excepto la última página del libro. No es necesario decir: aquellos valores que se encuentren por debajo de la última página y por encima de -1. Si bien esta condición incluye a los menores o iguales que -1, el bloque anterior ya filtró dichos valores negativos, por lo que no los tendrá en cuenta en esta ocasión. Por lo tanto sería redundante incluir dicha condición.
  • Luego, al quedar sólo la última página por analizar, el tercer bloque no necesita especificar que se trata de ella, sino simplemente centrarse en si el resto de la división es 0.
  • Y en el último bloque sólo queda una única opción: analizar si el resto de la división es diferente de 1.

Links - [Enlaces]

PaginationHelper
https://www.codewars.com/kata/515bb423de843ea99400000a

This is my repository: Codewars-kata
https://github.com/Kirito0922/Codewars-kata/blob/2a6c802240fad4261efe53357e4a2e9f1ecb4957/PaginationHelper.cs

Solutions for PaginationHelper
https://www.codewars.com/kata/515bb423de843ea99400000a/solutions/csharp


English translation made with DeepL Translate
Traducción al Inglés hecha con Deepl Translate

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now