What's a line-second? Never heard/seen this term before.
janAkali
Nim
Part 1: I made the only procedure - to roll rocks to the right. First, I rotate input 90 degrees clockwise. Then roll rocks in each row. To roll a row of rocks - I scan from right to left, until I find a rock and try to find the most right available position for it. Not the best approach, but not the worst either.
Part 2: To do a cycle I use the same principle as part 1: (rotate clockwise + roll rocks right) x 4 = 1 cycle
. A trillion cycles would obviously take too long. Instead, I cycle the input and add every configuration to a hashTable and once we reach a full copy of one of previous cycles - it means we're in a loop. And then finding out in what configuration rocks will be after trillion steps is easy with use of a modulo.
Total Runtime: 60ms relatively slow today =(
Puzzle rating: 7/10
Code: day_14/solution.nim
Nim
Part 1: For part 1 I just compare rows, then transpose matrix and compare rows again.
Part 2: For part 2 I compare rows and get symmetry type for each comparison: symmetric(==), almost symmetric (1 smudge), not symmetric (2+ difference). Then I just use two booleans to make sure we found exactly one smudge in each mirror.
Total runtime: 0.3 ms
Puzzle rating: 6/10
Code: day_13/solution.nim
Nim
Part 1 and 2:
I solved today's puzzle without expanding the universe. Path in expanded universe is just a path in the original grid + expansion rate times the number of crossed completely-empty lines (both horizontal and vertical). For example, if a single tile after expansion become 5 tiles (rate = +4), original path was 12 and it crosses 7 lines, new path will be: 12 + 4 * 7 = 40
.
The shortest path is easy to calculate in O(1) time: abs(start.x - finish.x) + abs(start.y - finish.y)
.
And to count crossed lines I just check if line is between the start and finish indexes.
Total runtime: 2.5 ms
Puzzle rating: 7/10
Code: day_11/solution.nim
Snippet:
proc solve(lines: seq[string]): AOCSolution[int] =
let
galaxies = lines.getGalaxies()
emptyLines = lines.emptyLines()
emptyColumns = lines.emptyColumns()
for gi, g1 in galaxies:
for g2 in galaxies[gi+1..^1]:
let path = shortestPathLength(g1, g2)
let crossedLines = countCrossedLines(g1, g2, emptyColumns, emptyLines)
block p1:
result.part1 += path + crossedLines * 1
block p2:
result.part2 += path + crossedLines * 999_999
Nim
I have zero idea how this functions correctly. I fear to touch it more than necessary or it would fall apart in a moment.
I got second star after 8 hours (3 hours for part 1 + 4 hour break + 1 hour part 2), at that moment I've figured out how to mark edges of enclosed tiles. Then I just printed the maze and counted all in-between tiles manually. A bit later I've returned and fixed the code with an ugly regex hack, but atleast it works.
Code: day_10/solution.nim
Nim
Part 1:
The extrapolated value to the right is just the sum of all last values in the diff pyramid. 45 + 15 + 6 + 2 + 0 = 68
Part 2:
The extrapolated value to the left is just a right-folded difference (right-associated subtraction) between all first values in the pyramid. e.g. 10 - (3 - (0 - (2 - 0))) = 5
So, extending the pyramid is totally unneccessary.
Total runtime: 0.9 ms
Puzzle rating: Easy, but interesting 6.5/10
Full Code: day_09/solution.nim
Snippet:
proc solve(lines: seq[string]): AOCSolution[int] =
for line in lines:
var current = line.splitWhitespace().mapIt(it.parseInt())
var firstValues: seq[int]
while not current.allIt(it == 0):
firstValues.add current[0]
block p1:
result.part1 += current[^1]
var nextIter = newSeq[int](current.high)
for i, v in current[1..^1]:
nextIter[i] = v - current[i]
current = nextIter
block p2:
result.part2 += firstValues.foldr(a-b)
I love every single game these guys make, but World of Goo is definitely in my top 10 games of all time.
I can't even believe they're making a sequel. It's the dream comes true.
Going to replay the original in 100th time.
Nim
Part 1 is just a sorting problem. Nim's standard library supports sorting with custom compare functions, so I only had to implement cmp() for my custom type and I was done in no time.
To get the star in Part 2 I was generating every possible combination of card hands with Jokers replaced by other cards. It was pretty fast, under a second. Didn't figure out the deterministic method by myself, but coded it after couple hints from Nim Discord people.
Didn't expect an easy challenge for today, but was pleasantly surprised. No weird edge cases, no hidden traps, puzzle text was easy to understand and input parsing is painless.
Total runtime: 1 ms
Puzzle rating: Almost Pefect 9/10
Code: day_07/solution.nim
Nim
Today's puzzle was too easy. I solved it with bruteforce in 20 minutes, but that's boring. So here's the optimized solution with quadratic formula.
Total runtime: 0.008 ms
Puzzle rating: Too Easy 5/10
Code: day_06/solution.nim
Thank you, should be fixed now.
Well, then we have the same solution but coded very differently. Here's mine.
ruleApplied
is one function with almost all logic. I take a range and compare it to a rule's source range (50 98 2 is a rule). Overlaps get transformed and collected into the first sequence and everything that left goes in the second. I need two seq
s there, for transformed values to skip next rules in the same map.
Repeat for each rule and each map (seq[Rule]). And presto, it's working!
I have all apps I use daily in the appimage format. Yesterday I decided to try btrfs for my root partition and did my annual Linux reinstall. All my apps were already there and ready for work from the start.
I also have a usb flashdrive always on me with the same appimages. Just in case I'd wipe a hard drive by accident and wouldn't have an internet connection or something like that (in case of emergencies). You can't do this with flatpaks or snaps.