Coding Problem 9

Después de un tiempo volvemos con nuestros famosos Coding Problems.


Este problema fue preguntado por Google.


Implementa una clase PrefixMapSum con los siguientes métodos:

  • insert(key: str, value: int): establece el valor de una clave determinada en el mapa. Si la clave ya existe, sobrescriba el valor.

  • sum(prefix: str): devuelve la suma de todos los valores de las claves que comienzan con un prefijo determinado.

Por ejemplo, debería poder ejecutar el siguiente código:

mapsum.insert("columnar", 3)
assert mapsum.sum("col") == 3

mapsum.insert("column", 2)
assert mapsum.sum("col") == 5   



Solución:


Bien, comencemos con los tests, lo que nos dice el enunciado es que tenemos que encontrar todas las claves que comiencen con el prefijo que pasamos por parámetro y sumar todos los valores. Para ello primero debemos crear un método que nos permita insertar estos valores y sobrescribirlos si ya existen, no añadirlos.


Tests:

public class PrefixMapSumTest {

    private PrefixMapSum prefixMapSum;

    @Before
    public void setup() {
        prefixMapSum = new PrefixMapSum(new HashMap<>());
    }

    @Test
    public void shouldAddValueToMap() {
        prefixMapSum.insert("columnar", 3);

        assertTrue(prefixMapSum.getMap().containsKey("columnar"));
        assertEquals(prefixMapSum.getMap().size(), 1);
    }

    @Test
    public void shouldOverrideValueIfAlreadyExists() {
        prefixMapSum.insert("columnar", 3);
        prefixMapSum.insert("columnar", 3);
        prefixMapSum.insert("columnar", 3);

        assertTrue(prefixMapSum.getMap().containsKey("columnar"));
        assertEquals(prefixMapSum.getMap().size(), 1);
    }

    @Test
    public void shouldWriteAllValuesIfNotExists() {
        prefixMapSum.insert("columnar", 3);
        prefixMapSum.insert("columna", 2);
        prefixMapSum.insert("pepito", 5);

        assertTrue(prefixMapSum.getMap().containsKey("columnar"));
        assertEquals(prefixMapSum.getMap().size(), 3);
    }

    @Test
    public void shouldReturnTheExpectedSumOfValues() {
        prefixMapSum.insert("columnar", 3);
        prefixMapSum.insert("column", 2);

        assertEquals(prefixMapSum.sum("col"), 5);
        assertEquals(prefixMapSum.getMap().size(), 2);
    }
}

Ahora implementamos el mínimo código posible:

public class PrefixMapSum {
    private Map<String, Integer> map;

    public PrefixMapSum(Map<String, Integer> map) {
        this.map = map;
    }

    public void insert(String key, int value) {
        map.put(key, value);
    }

    public Map<String, Integer> getMap() {
        return map;
    }

    public int sum(String prefix) {
        int sum = 0;
        for (String key : map.keySet()) {
            if(key.startsWith(prefix)) sum += map.get(key);
        }

        return sum;
    }
}

Pero claro, esto es refactorizable, al menos el método sum, vamos a ello:

public int sum(String prefix) {

    return map.entrySet().stream()
            .filter(value -> value.getKey().startsWith(prefix))
            .map(Map.Entry::getValue)
            .reduce(Integer::sum)
            .orElse(0);
}


Espero que te haya gustado este nuevo Coding Problem con su solución, espero que te sirva para practicar, nos vemos en la próxima :)

©2020 por Juanma Perez.