Nim
parts 1 and 2 - easy
For part 3 - When I first looked at the example input - it seemed a bit daunting to solve.
But then I had a hunch and decided to check the real input and turns out - I was right! The real input is easier to solve because it’s longer than 1000 chars.
This means that there is only 3 possible configurations we care about in repeated input: leftmost section, rightmost section and 998 identical sections in the middle. We solve each individually and sum them.
Another trick I used is looking up mentors with modulo to avoid copying the input.
proc solve_part1*(input: string): Solution =
var mentors: CountTable[char]
for c in input:
if c notin {'a','A'}: continue
if c.isUpperAscii: mentors.inc c
else:
result.intVal += mentors.getOrDefault(c.toUpperAscii)
proc solve_part2*(input: string): Solution =
var mentors: CountTable[char]
for c in input:
if c.isUpperAscii: mentors.inc c
else:
result.intVal += mentors.getOrDefault(c.toUpperAscii)
proc solve_part3*(input: string): Solution =
var mentors: Table[char, seq[int]]
for index in -1000 ..< input.len + 1000:
let mi = index.euclMod input.len
if input[mi].isLowerAscii: continue
let lower = input[mi].toLowerAscii
if mentors.hasKeyOrPut(lower, @[index]):
mentors[lower].add index
var most, first, last = 0
for ci, ch in input:
if ch.isUpperAscii: continue
for mi in mentors[ch]:
let dist = abs(mi - ci)
if dist <= 1000:
inc most
if mi >= 0: inc first
if mi <= input.high: inc last
result := first + (most * 998) + last