I think it's time to start blocking news about US politics.
Karmmah
I switched to Commit Mono for Terminal not too long ago but I really like it. Otherwise I use Cantarell but only because it is default and I never felt the need to change it.
So what music do you listen to? Me: ... can I just show you my playlists?
Julia
Quite happy that today went a lot smoother than yesterday even though I am not really familiar with recursion. Normally I never use recursion but I felt like today could be solved by it (or using trees, but I'm even less familiar with them). Surprisingly my solution actually worked and for part 2 only small modifications were needed to count peaks reached by each trail.
Code
function readInput(inputFile::String)
f = open(inputFile,"r")
lines::Vector{String} = readlines(f)
close(f)
topoMap = Matrix{Int}(undef,length(lines),length(lines[1]))
for (i,l) in enumerate(lines)
topoMap[i,:] = map(x->parse(Int,x),collect(l))
end
return topoMap
end
function getTrailheads(topoMap::Matrix{Int})
trailheads::Vector{Vector{Int}} = []
for (i,r) in enumerate(eachrow(topoMap))
for (j,c) in enumerate(r)
c==0 ? push!(trailheads,[i,j]) : nothing
end
end
return trailheads
end
function getReachablePeaks(topoMap::Matrix{Int},trailheads::Vector{Vector{Int}})
reachablePeaks = Dict{Int,Vector{Vector{Int}}}()
function getPossibleMoves(topoMap::Matrix{Int},pos::Vector{Int})
possibleMoves::Vector{Vector{Int}} = []
pos[1]-1 in 1:size(topoMap)[1] && topoMap[pos[1]-1,pos[2]]==topoMap[pos[1],pos[2]]+1 ? push!(possibleMoves,[pos[1]-1,pos[2]]) : nothing #up?
pos[1]+1 in 1:size(topoMap)[1] && topoMap[pos[1]+1,pos[2]]==topoMap[pos[1],pos[2]]+1 ? push!(possibleMoves,[pos[1]+1,pos[2]]) : nothing #down?
pos[2]-1 in 1:size(topoMap)[2] && topoMap[pos[1],pos[2]-1]==topoMap[pos[1],pos[2]]+1 ? push!(possibleMoves,[pos[1],pos[2]-1]) : nothing #left?
pos[2]+1 in 1:size(topoMap)[2] && topoMap[pos[1],pos[2]+1]==topoMap[pos[1],pos[2]]+1 ? push!(possibleMoves,[pos[1],pos[2]+1]) : nothing #right?
return possibleMoves
end
function walkPossMoves(topoMap::Matrix{Int},pos::Vector{Int},reachedPeaks::Matrix{Bool},trailId::Int)
possMoves::Vector{Vector{Int}} = getPossibleMoves(topoMap,pos)
for m in possMoves
if topoMap[m[1],m[2]]==9
reachedPeaks[m[1],m[2]]=1
trailId += 1
continue
end
reachedPeaks,trailId = walkPossMoves(topoMap,m,reachedPeaks,trailId)
end
return reachedPeaks, trailId
end
peaksScore::Int = 0; trailsScore::Int = 0
trailId::Int = 0
for (i,t) in enumerate(trailheads)
if !haskey(reachablePeaks,i); reachablePeaks[i]=[]; end
reachedPeaks::Matrix{Bool} = zeros(size(topoMap))
trailId = 0
reachedPeaks,trailId = walkPossMoves(topoMap,t,reachedPeaks,trailId)
trailPeaksScore = sum(reachedPeaks)
peaksScore += trailPeaksScore
trailsScore += trailId
end
return peaksScore,trailsScore
end #getReachablePeaks
topoMap::Matrix{Int} = readInput("input/day10Input")
trailheads::Vector{Vector{Int}} = getTrailheads(topoMap)
@info "Part 1"
reachablePeaks = getReachablePeaks(topoMap,trailheads)[1]
println("reachable peaks: ",reachablePeaks)
@info "Part 2"
trailsScore::Int = getReachablePeaks(topoMap,trailheads)[2]
println("trails score: $trailsScore")
Julia
Oh today was a struggle. First I did not get what exactly the task wanted me to do and then in part 2 I tried a few different ideas which all failed because I changed the disk while I was indexing into it. Finally now I reworked part 2 not moving the blocks at all, just using indexes and it works.
I feel that there is definitely something to learn here and that's what I like about AoC so far. This is my first AoC but I hope that I won't have to put this much thought into the rest, since I should definitely use my time differently.
Code
function readInput(inputFile::String)
f = open(inputFile,"r"); diskMap::String = readline(f); close(f)
disk::Vector{String} = []
id::Int = 0
for (i,c) in enumerate(diskMap)
if i%2 != 0 #used space
for j=1 : parse(Int,c)
push!(disk,string(id))
end
id += 1
else #free space
for j=1 : parse(Int,c)
push!(disk,".")
end
end
end
return disk
end
function getDiscBlocks(disk::Vector{String})::Vector{Vector{Int}}
diskBlocks::Vector{Vector{Int}} = []
currBlock::Int = parse(Int,disk[1]) #-1 for free space
blockLength::Int = 0; blockStartIndex::Int = 0
for (i,b) in enumerate(map(x->(x=="." ? -1 : parse(Int,x)),disk))
if b == currBlock
blockLength += 1
else #b!=currBlock
push!(diskBlocks,[currBlock,blockLength,blockStartIndex,i-2])
currBlock = b
blockLength = 1
blockStartIndex = i-1 #start of next block
end
end
push!(diskBlocks,[currBlock,blockLength,blockStartIndex,length(disk)-1])
return diskBlocks
end
function compressDisk(disk::Vector{String})::Vector{Int} #part 1
compressedDisk::Vector{Int} = []
startPtr::Int=1; endPtr::Int=length(disk)
while endPtr >= startPtr
while endPtr>startPtr && disk[endPtr]=="."
endPtr -= 1
end
while startPtr<endPtr && disk[startPtr]!="."
push!(compressedDisk,parse(Int,disk[startPtr])) about AoC
startPtr += 1
end
push!(compressedDisk,parse(Int,disk[endPtr]))
startPtr+=1;endPtr-=1
end
return compressedDisk
end
function compressBlocks(diskBlocks::Vector{Vector{Int}})
for i=length(diskBlocks) : -1 : 1 #go through all blocks, starting from end
diskBlocks[i][1] == -1 ? continue : nothing
for j=1 : i-1 #look for large enough empty space
diskBlocks[j][1]!=-1 || diskBlocks[j][2]<diskBlocks[i][2] ? continue : nothing #skip occupied blocks and empty blocks that are too short
diskBlocks[i][3] = diskBlocks[j][3] #set start index
diskBlocks[i][4] = diskBlocks[j][3]+diskBlocks[i][2]-1 #set end index
diskBlocks[j][3] += diskBlocks[i][2] #move start of empty block
diskBlocks[j][2] -= diskBlocks[i][2] #adjust length of empty block
break
end
end
return diskBlocks
end
function calcChecksum(compressedDisk::Vector{Int})::Int
checksum::Int = 0
for (i,n) in enumerate(compressedDisk)
checksum += n*(i-1)
end
return checksum
end
function calcChecksumBlocks(diskBlocks::Vector{Vector{Int}})::Int
checksum::Int = 0
for b in diskBlocks
b[1]==-1 ? continue : nothing
for i=b[3] : b[4]
checksum += b[1]*i
end
end
return checksum
end
disk::Vector{String} = readInput("input/day09Input")
@info "Part 1"
println("checksum: $(calcChecksum(compressDisk(disk)))")
@info "Part 2"
println("checksum: $(calcChecksumBlocks(compressBlocks(getDiscBlocks(disk)))")
Julia
I was surprised when my solution worked for part 2 since I thought you also had to include fractions of antenna distances, but apparently not.
Code
function readInput(inputFile::String)::Matrix{Char}
f = open(inputFile,"r")
lines::Vector{String} = readlines(f)
close(f)
cityMap = Matrix{Char}(undef,length(lines),length(lines[1]))
for (i,l) in enumerate(lines)
cityMap[i,:] = collect(l)
end
return cityMap
end
function getAntennaLocations(cityMap::Matrix{Char})::Dict
antennaLocations = Dict{Char,Vector{Vector{Int}}}()
for l=1 : size(cityMap)[1]
for c=1 : size(cityMap)[2]
cityMap[l,c]=='.' ? continue : nothing
if !haskey(antennaLocations,cityMap[l,c])
antennaLocations[cityMap[l,c]] = []
end
push!(antennaLocations[cityMap[l,c]],[l,c])
end
end
return antennaLocations
end
function countAntinodes(cityMap::Matrix{Char},antLoc::Dict{Char,Vector{Vector{Int}}},withHarmonics::Bool)::Int #antLoc: antenna locations
lBounds = 1:size(cityMap)[1]; cBounds = 1:size(cityMap)[2]
anodeLocs::Matrix{Bool} = zeros(size(cityMap))
for key in keys(antLoc)
for i=1 : length(antLoc[key])
withHarmonics&&length(antLoc[key])>1 ? anodeLocs[antLoc[key][i][1],antLoc[key][i][2]]=1 : nothing #add antenna locations as antinodes
#should also add fractions of antenna distances, but works without
for j=i+1 : length(antLoc[key])
harmonic::Int = 1
while true
n1l = antLoc[key][i][1]+harmonic*(antLoc[key][i][1]-antLoc[key][j][1])
n1c = antLoc[key][i][2]+harmonic*(antLoc[key][i][2]-antLoc[key][j][2])
n2l = antLoc[key][j][1]+harmonic*(antLoc[key][j][1]-antLoc[key][i][1])
n2c = antLoc[key][j][2]+harmonic*(antLoc[key][j][2]-antLoc[key][i][2])
if n1l in lBounds && n1c in cBounds
anodeLocs[n1l,n1c] = 1
end
if n2l in lBounds && n2c in cBounds
anodeLocs[n2l,n2c] = 1
end
withHarmonics ? nothing : break
!(n1l in lBounds) && !(n1c in cBounds) && !(n2l in lBounds) && !(n2c in cBounds) ? break : harmonic+=1
end
end
end
end
return sum(anodeLocs)
end
@info "Part 1"
println("antinode count $(countAntinodes(getAntennaLocations(readInput("day08Input"))),false)")
@info "Part 2"
println("antinode count $(countAntinodes(getAntennaLocations(readInput("day08Input"))),faltrue)")
Julia
Took quite some time to debug but in the end I think it's a nice solution using base 2 and 3 numbers counting up to check all operator combinations.
Code
function readInput(inputFile::String)::Vector{Vector{Int}}
f = open(inputFile,"r")
lines::Vector{String} = readlines(f)
close(f)
equations::Vector{Vector{Int}} = []
function getValues(line::String)
return map(sp->parse(Int,sp),(sp=split(line," ");sp[1]=sp[1][1:end-1];sp))
end
map(l->push!(equations,getValues(l)),lines)
return equations
end
function checkEq(eq::Vector{Int},withConCat::Bool)::Bool
function calcEq(eq::Vector{Int},operators::Vector{Int},withConCat::Bool)::Int
res::Int = eq[2]
for (i,op) in enumerate(operators)
if op == 0 #+
res += eq[i+2]
elseif op ==1 #*
res *= eq[i+2]
else #op==2 ||
res = parse(Int,string(res)*string(eq[i+2]))
end
end
return res
end
opInt::Int = 0
operators = Vector{Int}(undef,length(eq)-2)
while opInt < (withConCat ? 3^(length(eq)-2) : 2^(length(eq)-2))
withConCat==true ? operators=digits(opInt,base=3,pad=length(eq)-2) : operators=digits(opInt,base=2,pad=length(eq)-2)
#calcEq(eq,operators,withConCat)==eq[1] ? (return true) : opInt -= 1
calcEq(eq,operators,withConCat)==eq[1] ? (return true) : opInt += 1
end
return false
end
function calcTotCalRes(equations::Vector{Vector{Int}},withConCat::Bool)::Int
totCalRes::Int = 0
for e in equations
checkEq(e,withConCat) ? totCalRes+=e[1] : nothing
end
return totCalRes
end
@info "Part 1"
println("result: $(calcTotCalRes(readInput("day07Input"),false))")
@info "Part 2"
println("result: $(calcTotCalRes(readInput("day07Input"),true))")
I'm also struggling with part 2. At the moment I am following the path and in each place I look if can connect with an earlier part of the path to the right by placing an obstacle, but without cutting off another earlier part of the path with that obstacle. I have indexes for each path location to see where in the path they first appear.
However at the moment I still have a bug counting too many possibilities. Any other ideas?
The Marvel universe is mainly there to create possibilities to make more money, not to tell a good story. Granted I have hardly seen any of the movies/series, but after Avengers I never saw a reason to. Marvel realised Avengers was good and now they pulled out as much stuff out of the universe to fill a seemingly endless stream of "storytelling".
Julia
No really proud of todays solution. Probably because I started too late today.
I used a dictionary with the numbers that should be in front of any given number. Then I checked if they appear after that number. Part1 check. For part 2 I just hoped for the best that ordering it would work by switching each two problematic entries and it worked.
::: spoiler
function readInput(inputFile::String)
f = open(inputFile,"r"); lines::Vector{String} = readlines(f); close(f)
updates::Vector{Vector{Int}} = []
pageOrderingRules = Dict{Int,Vector{Int}}()
readRules::Bool = true #switch off after rules are read, then read updates
for (i,line) in enumerate(lines)
line=="" ? (readRules=false;continue) : nothing
if readRules
values::Vector{Int} = map(x->parse(Int,x),split(line,"|"))
!haskey(pageOrderingRules,values[2]) ? pageOrderingRules[values[2]]=Vector{Int}() : nothing
push!(pageOrderingRules[values[2]],values[1])
else #read updates
push!(updates,map(x->parse(Int,x),split(line,",")))
end
end
return updates, pageOrderingRules
end
function checkUpdateInOrder(update::Vector{Int},pageOrderingRules::Dict{Int,Vector{Int}})::Bool
inCorrectOrder::Bool = true
for i=1 : length(update)-1
for j=i+1 : length(update)
!haskey(pageOrderingRules,update[i]) ? continue : nothing
update[j] in pageOrderingRules[update[i]] ? inCorrectOrder=false : nothing
end
!inCorrectOrder ? break : nothing
end
return inCorrectOrder
end
function calcMidNumSum(updates::Vector{Vector{Int}},pageOrderingRules::Dict{Int,Vector{Int}})::Int
midNumSum::Int = 0
for update in updates
checkUpdateInOrder(update,pageOrderingRules) ? midNumSum+=update[Int(ceil(length(update)/2))] : nothing
end
return midNumSum
end
function calcMidNumSumForCorrected(updates::Vector{Vector{Int}},pageOrderingRules::Dict{Int,Vector{Int}})::Int
midNumSum::Int = 0
for update in updates
inCorrectOrder::Bool = checkUpdateInOrder(update,pageOrderingRules)
inCorrectOrder ? continue : nothing #skip already correct updates
while !inCorrectOrder
for i=1 : length(update)-1
for j=i+1 : length(update)
!haskey(pageOrderingRules,update[i]) ? continue : nothing
if update[j] in pageOrderingRules[update[i]]
mem::Int = update[i]; update[i] = update[j]; update[j]=mem #switch entries
end
end
end
inCorrectOrder = checkUpdateInOrder(update,pageOrderingRules)
end
midNumSum += update[Int(ceil(length(update)/2))]
end
return midNumSum
end
updates, pageOrderingRules = readInput("day05Input")
println("part 1 sum: $(calcMidNumSum(updates,pageOrderingRules))")
println("part 2 sum: $(calcMidNumSumForCorrected(updates,pageOrderingRules))")
:::
Julia
Had some time to clean up the code today since the solution was quite straight forward after making a plan on how to approach it.
spoiler
function readWordSearch(inputFile::String)::Matrix{Char}
f = open(inputFile,"r")
lines::Vector{String} = readlines(f)
close(f)
wordSearch = Matrix{Char}(undef,length(lines),length(lines))
for (i,line) in enumerate(lines)
wordSearch[i,:] = collect(line)
end
return wordSearch
end
function countXMASAppearances(wS::Matrix{Char})::Int
appearanceCount::Int = 0
for i=1 : size(wS)[1] #lines
for j=1 : size(wS)[2] #columns
wS[i,j]!='X' ? continue : nothing #continue if char is not X
#if char is X, check surrounding area
# check horizontals
#left
j>=4 ? (wS[i,j-1]*wS[i,j-2]*wS[i,j-3]=="MAS" ? appearanceCount+=1 : nothing) : nothing
#right
j<=size(wS)[2]-3 ? (wS[i,j+1]*wS[i,j+2]*wS[i,j+3]=="MAS" ? appearanceCount+=1 : nothing) : nothing
# check verticals
#up
i>=4 ? (wS[i-1,j]*wS[i-2,j]*wS[i-3,j]=="MAS" ? appearanceCount+=1 : nothing) : nothing
#down
i<=size(wS)[1]-3 ? (wS[i+1,j]*wS[i+2,j]*wS[i+3,j]=="MAS" ? appearanceCount+=1 : nothing) : nothing
# check diagonals
#left up
i>=4 && j>=4 ? (wS[i-1,j-1]*wS[i-2,j-2]*wS[i-3,j-3]=="MAS" ? appearanceCount+=1 : nothing) : nothing
#right up
i>=4 && j<=size(wS)[2]-3 ? (wS[i-1,j+1]*wS[i-2,j+2]*wS[i-3,j+3]=="MAS" ? appearanceCount+=1 : nothing) : nothing
#left down
i<=size(wS)[1]-3 && j>=4 ? (wS[i+1,j-1]*wS[i+2,j-2]*wS[i+3,j-3]=="MAS" ? appearanceCount+=1 : nothing) : nothing
#right down
i<=size(wS)[1]-3 && j<=size(wS)[2]-3 ? (wS[i+1,j+1]*wS[i+2,j+2]*wS[i+3,j+3]=="MAS" ? appearanceCount+=1 : nothing) : nothing
end
end
return appearanceCount
end
function countX_MASAppearances(wordSearch::Matrix{Char})::Int
appearances::Int = 0
for l=2 : size(wordSearch)[1]-1
for c=2 : size(wordSearch)[2]-1
wordSearch[l,c]!='A' ? continue : nothing
checkArr = [wordSearch[l-1,c-1],wordSearch[l-1,c+1],wordSearch[l+1,c-1],wordSearch[l+1,c+1]]
if checkArr in [['M','M','S','S'],['M','S','M','S'],['S','S','M','M'],['S','M','S','M']]
appearances += 1
end
end
end
return appearances
end
wordSearch::Matrix{Char} = readWordSearch(inputFile
prinltn("part 1 appearances: $(countXMASAppearances(wordSearch))")
prinltn("part 2 appearances: $(countX_MASAppearances(wordSearch))")
Would recommend it. Much better than having your brain rot away at a massively increased pace for the next four years.