Futhark
I translated my Haskell solution to Futhark, basically. It runs abysmally faster.
The syntax highlighting is likely very off, because the closest language highlighter I could find was ocaml.
def fst 'a 'b ((a, _b): (a, b)): a = a
def snd 'a 'b ((_a, b): (a, b)): b = b
def (>>>) 'a 'b 'c (f: a -> b) (g: b -> c) (x: a): c = g (f x)
def (|) '^a 'b (f: a -> b) (x: a): b = f x -- $ is not allowed
def even (x: i64): bool = x % 2 == 0
def digitCount (x: i64): i64
= snd |
loop (i, len) = (x, 0)
while i != 0
do (i / 10, len + 1)
def digitAt (n: i64) (i: i64): i64 = (n / 10 ** i) % 10
def keepTrue (p: i64 -> bool) (x: i64): i64
= if p x
then x
else 0
def tup2RangeArray ((start, end): (i64, i64)): []i64
= (start ... end)
def sumInvalidIds (p: i64 -> bool) (rangeTup: (i64, i64)): i64
= let range = tup2RangeArray rangeTup in
reduce (+) 0 (map (keepTrue p) range)
def tup2FromArray 'a (as: [2]a): (a, a) = (as[0], as[1])
def impl (p: i64 -> bool) (ranges: [](i64, i64)): i64
= reduce (+) 0 (map (sumInvalidIds p) ranges)
def withValidRepeatOffsets (nDigits: i64) (f: i64 -> bool): bool
= match nDigits
case 2 -> map f >>> or | [1]
case 3 -> map f >>> or | [1]
case 4 -> map f >>> or | [1, 2]
case 5 -> map f >>> or | [1]
case 6 -> map f >>> or | [1, 2, 3]
case 7 -> map f >>> or | [1]
case 8 -> map f >>> or | [1, 2, 4]
case 9 -> map f >>> or | [1, 3]
case 10 -> map f >>> or | [1, 2, 5]
case 11 -> map f >>> or | [1]
case 12 -> map f >>> or | [1, 2, 3, 4, 6]
case _ -> false
def isValid2 (x: i64): bool =
let len = digitCount x in
let lookupDigit = digitAt x in
withValidRepeatOffsets len | \ repeatOffset ->
let repeatCount = len / repeatOffset in
let digitIndices = (0..< repeatOffset) in
let repeatIndices = (0..<repeatCount) in
and |
map (\ digitIndex ->
and |
map (\ repeatIndex ->
let expectedDigit = lookupDigit digitIndex in
let actualDigit = lookupDigit | repeatIndex * repeatOffset + digitIndex in
expectedDigit == actualDigit
)
repeatIndices
) digitIndices
def part2 : [](i64, i64) -> i64 = impl isValid2
def isValid1 (x: i64): bool =
let len = digitCount x in
let halfLength = len / 2 in
let first = x / 10 ** halfLength in
let second = x % 10 ** halfLength in
even len && first == second
def part1 : [](i64, i64) -> i64 = impl isValid1
def main (rangeArrays: [][2]i64)
= let rangeTuples = map tup2FromArray rangeArrays in
(part1 rangeTuples, part2 rangeTuples)
Sed-Script to Transform input for Futhark
i [
s/\([0-9]\+\)-\([0-9]\+\)/\[\1, \2]/g
a ]