Advent of Code 2023 Day 04: Scratchcards
Foto de Capa gerada por IA
Ao usar o Teleférico para chegar na ilha seguinte o Elfo ali presente informa que a ilha que precisa de ajuda não é uma que não é possível chegar com o Teleférico, mas com um barco. Ele oferece o barco dele caso tenha sua ajuda com algo rápido: Ele possui uma porção de scratchcards (ou raspadinhas) mas não sabe quais estão premiadas.
Contexto específico
Cada um desses scartchcards possuem uma lista de números premiados (winning numbers
) e uma lista de números daquele scratchcard (card numbers
), separados por uma barra vertical (|
). Após organizar toda a informação, essa lista se torna seu input. Segundo o elfo, você precisa validar quais dos números do scratchcard aparecem como números premiados.
Para o primeiro número premiado encontrado você ganha 1 ponto naquele scratchcard e cada número premiado seguinte dobra a pontuação do scratchcard.
Resolução Parte 1
Caso queira resolver antes de ler a respeito de minha solução, esse é o momento!
Ao observar o formato do input, novamente notei que poderia tirar proveito de uma abordagem que usasse Expressões Regulares (RegExp
) para buscar tanto os winningNumbers
quanto os cardNumbers
:
Card <id>: <w-1> <w-2> ... <w-n> | <c-1> <c-2> ... <c-n>
Sabendo disso foi possível já quebrar o input todo separando pelos caracteres :
e |
usando a função split()
const lines = data
.split('\n')
.slice(0, -1)
.map((line) => line.split(/:|\|/))
Bastava então iterar sobre a lista de linhas e validar quantos dos cardNumbers
estavam presentes na lista de winningNumbers
.
- Para quebrar a string em uma lista de números foi usada a função
match()
- Para validar se o valor estava presente na lista de
winningNumbers
foi usada a funçãoincludes()
const getTotalPointsFromScratchCards = (lines) => {
let totalPoints = 0
for (const line of lines) {
const [_cardLabel, winningNumbers, cardNumbers] = line
const winningNumbersList = winningNumbers.match(/\d+/g)
const cardNumbersList = cardNumbers.match(/\d+/g)
let cardPoints = 0
for (const cardNumber of cardNumbersList) {
if (winningNumbersList.includes(cardNumber)) {
cardPoints = cardPoints === 0 ? 1 : cardPoints * 2
}
}
totalPoints += cardPoints
}
return totalPoints
}
Ao descobrir o valor total de pontos a segunda parte do desafio fica habilitada. Você percebe que na parte de trás dos scratchcards existem informações sobre como funcionam as regras deles.
Para sua surpresa não existem “pontos”! O sistema dos scratchcards é um pouco mais complexo que a cada número de cardNumbers
presentes nos winningNumbers
o jogador agora é recompensado com mais scratchcards subsequentes!
A resposta para a segunda parte do desafio agora é o número total e final de scratchcards que você terá, sejam eles originais ou “cópias”.
Resolução Parte 2
Novamente, Caso queira resolver a segunda parte antes de ler a respeito de minha solução, interrompa sua leitura aqui mesmo!
Após pensar um pouco a respeito, decidi abordar o problema por partes:
- Iterar sobre o input montando uma estrutura (um
Map()
) com- o valor de
cardPoints
do scratchcard atual - adicionar os
cardPoints
usando oid
do scratchcard atual, adicionando uma cópia a ele - popular os próximos
id
s de scratchcards subsequentes com cópias baseado no número de réplicas do scratchcard atual
- o valor de
- Somar todos os scratchcards existentes na estrutura montada
Duas funções auxiliares foram criadas para realizar essas tarefas. São elas, respectivamente: findOriginalScratchCardsAndCopies()
(código disponível no repositório do GitHub!) e getTotalScratchCards()
. Enquanto a primeira é relativamente parecida com a função que resolvia a primeira parte do desafio, a segunda apenas itera sobre o Map()
criado.
const getTotalScratchCards = (scratchCardsMap) => {
let totalScratchCards = 0
for (let scratchCard of scratchCardsMap.values()) {
totalScratchCards += scratchCard.copies
}
return totalScratchCards
}
Com isso, após montar o mapa de scratchcards com a quantidade de cada um existente e suas respectivas cópias, uma chamada a função getTotalScratchCards()
fornece a solução para a segunda parte do desafio: o número total de scratchcards.
Referências
O código final esta disponível no repositório do GitHub. Esses são alguns links que podem te auxiliar a compreender melhor o código e cada detalhe que mencionei ou esqueci de comentar a respeito de minha solução: