DataWeave scripts used in the adventofcode.com site for 2023.
Live stream @ twitch.tv/mulesoft_community: It's that time of the year again ๐ฒ Let's play Advent of Code 2023 with DataWeave โจ
Script
%dw 2.0
import lines, isNumeric from dw::core::Strings
output application/json
---
lines(payload) map ((line) -> do {
var nums = line filter (isNumeric($))
---
(nums[0] ++ nums[-1]) as Number
})
then sum($)
Script
%dw 2.0
import lines, isNumeric from dw::core::Strings
output application/json
var regex = /one|two|three|four|five|six|seven|eight|nine|ten|\d/
var numbers = {
one: "1",
two: "2",
three: "3",
four: "4",
five: "5",
six: "6",
seven: "7",
eight: "8",
nine: "9"
}
---
lines(payload) map ((line) -> do {
var cleanLine = line
replace "one" with "onee"
replace "two" with "twoo"
replace "three" with "threee"
replace "five" with "fivee"
replace "seven" with "sevenn"
replace "eight" with "eightt"
replace "nine" with "ninee"
var nums = flatten(cleanLine scan regex) map ((n) ->
if (isNumeric(n)) n
else numbers[n]
)
---
(nums[0] ++ nums[-1]) as Number
})
then sum($)
Live stream @ twitch.tv/mulesoft_community: First stream of the year!! ~ Advent of Code 2023 Day 2
Script
%dw 2.0
import every from dw::core::Arrays
import lines from dw::core::Strings
output application/json
var maxRed = 12
var maxGreen = 13
var maxBlue = 14
---
lines(payload) map ((game, gameidx) -> do {
var sets = game[8 to -1] splitBy ";" map (
trim($) splitBy "," reduce ((item, acc={}) ->
acc ++ {
((item scan /red|green|blue/)[0][0]): (item scan /\d+/)[0][0] as Number
}
)
)
---
{
game: gameidx+1,
sets: sets,
isPossible: (sets reduce (set, acc=[]) -> (
acc
+ ((set.red default 0) <= maxRed)
+ ((set.green default 0) <= maxGreen)
+ ((set.blue default 0) <= maxBlue)
)) every $
}
})
filter $.isPossible
then $.game
then sum($)
Live stream @ twitch.tv/mulesoft_community: Playing Advent of Code with DataWeave once more! (Programming challenges)
Script
%dw 2.0
import lines from dw::core::Strings
output application/json
---
lines(payload) map ((game, gameidx) -> do {
var sets = game[8 to -1] splitBy ";" map (
trim($) splitBy "," reduce ((item, acc={}) ->
acc ++ {
((item scan /red|green|blue/)[0][0]): (item scan /\d+/)[0][0] as Number
}
)
)
fun getMaxNumber(color:String): Number = (
max(sets[color] default []) default 1
)
---
getMaxNumber("red")
* getMaxNumber("green")
* getMaxNumber("blue")
})
then sum($)
Live streams @ twitch.tv/mulesoft_community:
- Playing Advent of Code with DataWeave once more! (Programming challenges)
- DataWeave, Advent of Code, reading your suggestions!
Caution
I made a horrible code for this one. I'm really embarrassed about this. Check out Ignacio's code instead :'D https://github.com/iglosiggio/aoc2023/blob/main/aoc2023day3ex1.dwl
Bad Alex :(
Script
%dw 2.0
import update from dw::util::Values
import some from dw::core::Arrays
output application/json
var linesArr = (payload splitBy "\n")
var regexForChars = /[^\d.\s]/
var mainArray = linesArr reduce ((line, acc=[]) -> do {
acc ++ (flatten(line scan /\d+/) map ((number) -> do {
var regexExactNumberMatch = ("(?<!\d)$(number)(?!\d)" as Regex)
var exactNumberMatchesIdxs = flatten(line find regexExactNumberMatch)
var firstIndex = (line find regexExactNumberMatch)[0][0]
var lastIndex = (firstIndex + (sizeOf(number)-1))
var firstIndexToCheck = if ((firstIndex-1) >= 0) firstIndex-1 else firstIndex
var lastIndexToCheck = if ((lastIndex+1) > sizeOf(line)-1) lastIndex else lastIndex+1
var currentLineIdx = (linesArr find line)[0]
var previousLineIdx = currentLineIdx - 1
var nextLineIdx = currentLineIdx + 1
var isPartAbove = if (previousLineIdx >= 0)
linesArr[previousLineIdx][firstIndexToCheck to lastIndexToCheck] contains regexForChars
else false
var isPartBelow = if (nextLineIdx > (sizeOf(linesArr)-1)) false
else linesArr[nextLineIdx][firstIndexToCheck to lastIndexToCheck] contains regexForChars
var isPartNext = line[firstIndexToCheck to lastIndexToCheck] contains regexForChars
---
{
line: line,
number: number as Number,
firstIndex: firstIndex,
exactNumberMatchesIdxs: exactNumberMatchesIdxs,
isDupNum: sizeOf(exactNumberMatchesIdxs) >1,
isPart: [isPartAbove, isPartBelow, isPartNext] some $
}
}))
})
---
do {
var resultWithDups = sum((mainArray filter $.isPart).number)
var dupNums = sum((mainArray filter $.isPart and $.isDupNum).number distinctBy $)
var duplicatesNotChecked = ((mainArray filter $.isDupNum filter ($$ mod 2) != 0) map do {
var firstIndex = $.exactNumberMatchesIdxs[-1] // decided to assume there's only 2 matches per line :')
var lastIndex = (firstIndex + (sizeOf($.number)-1))
var firstIndexToCheck = if ((firstIndex-1) >= 0) firstIndex-1 else firstIndex
var lastIndexToCheck = if ((lastIndex+1) > sizeOf($.line)-1) lastIndex else lastIndex+1
var currentLineIdx = (linesArr find $.line)[0]
var previousLineIdx = currentLineIdx - 1
var nextLineIdx = currentLineIdx + 1
var isPartAbove = if (previousLineIdx >= 0)
linesArr[previousLineIdx][firstIndexToCheck to lastIndexToCheck] contains regexForChars
else false
var isPartBelow = if (nextLineIdx > (sizeOf(linesArr)-1)) false
else linesArr[nextLineIdx][firstIndexToCheck to lastIndexToCheck] contains regexForChars
var isPartNext = $.line[firstIndexToCheck to lastIndexToCheck] contains regexForChars
---
{
line: $.line,
number: $.number as Number,
exactNumberMatchesIdxs: $.exactNumberMatchesIdxs,
firstIndex: firstIndex,
isPart: [isPartAbove, isPartBelow, isPartNext] some $
}
}) filter $.isPart then sum($.number)
---
{
resultWithDups: resultWithDups, // suming up everything that is considered a part (even duplicates per line)
dupNums: dupNums, // suming up the duplicate numbers that are a part (to remove them from the previous count)
duplicatesNotChecked: duplicatesNotChecked, // suming up the duplicates that are a part that were not previously checked correctly
finalResult: resultWithDups - dupNums + duplicatesNotChecked // final operations :')
}
}
Note
I couldn't solve Part 2, but check out this amazing script to solve it.
Live stream @ twitch.tv/mulesoft_community:
Script
%dw 2.0
import countBy from dw::core::Arrays
import lines, substringBefore, substringAfter from dw::core::Strings
output application/json
fun getNumbers(numbers) = flatten(numbers scan /\d+/)
---
lines(payload) map ((line) -> do {
var cardName = (line substringBefore ":")
var numbers = (line substringAfter ":") splitBy "|"
var winningNumbers = getNumbers(numbers[0])
var actualNumbers = getNumbers(numbers[1])
var matchingNumbers = winningNumbers countBy (actualNumbers contains $)
var score = matchingNumbers match {
case 1 -> 1
case 0 -> 0
else -> 2 pow matchingNumbers-1
}
---
// for debugging purposes
// {
// (cardName): {
// winning: winningNumbers,
// actual: actualNumbers,
// matchingNumbers: matchingNumbers,
// score: score
// }
// }
// actual needed code
score
})
then sum($)
Live stream @ twitch.tv/mulesoft_community:
Script
%dw 2.0
output application/json
import charCode from dw::core::Strings
fun getnum(currentvalue, asciicode) = ((currentvalue + asciicode) * 17) mod 256
fun getResult(string, r=0) = do {
@Lazy
var newR = r getnum charCode(string)
---
if (!isEmpty(string))
string[1 to -1] getResult newR
else r
}
---
(payload splitBy ",") map getResult($)
then sum($)
- Ryan Hoegg's adventofcode2023
- Ignacio Esteban Losiggio's aoc2023