const n_robot_layers := 26; fn simulate_movements~cache(n : int, src dest : tuple2(int, int)) : int; fn simulate_push(n : int, dx dy : int, count : int) : int [ if n = 0 then return count; var target_x := 1 + dx; var target_y := select(dy >= 0, 0, 1); var s1 := simulate_movements(n, mktuple2(2, 0), mktuple2(target_x, target_y)); var s2 := simulate_movements(n, mktuple2(target_x, target_y), mktuple2(2, 0)); return s1 + count + s2; ] fn simulate_push3(n : int, dx1 dy1 count1 dx2 dy2 count2 : int) : int [ if n = 0 then return count1 + count2; var target1_x := 1 + dx1; var target1_y := select(dy1 >= 0, 0, 1); var target2_x := 1 + dx2; var target2_y := select(dy2 >= 0, 0, 1); var s1 := simulate_movements(n, mktuple2(2, 0), mktuple2(target1_x, target1_y)); var s2 := simulate_movements(n, mktuple2(target1_x, target1_y), mktuple2(target2_x, target2_y)); var s3 := simulate_movements(n, mktuple2(target2_x, target2_y), mktuple2(2, 0)); return s1 + count1 + s2 + count2 + s3; ] fn simulate_movements~cache(n : int, src dest : tuple2(int, int)) : int [ var forbidden_place : tuple2(int, int); if n = n_robot_layers then forbidden_place := mktuple2(0, 3); else forbidden_place := mktuple2(0, 0); var dx := sgn(dest.v1 - src.v1); var dy := sgn(dest.v2 - src.v2); if dx = 0, dy = 0 then return 0; if dx = 0 then [ return simulate_push(n - 1, 0, dy, abs(dest.v2 - src.v2)); ] else if dy = 0 then [ return simulate_push(n - 1, dx, 0, abs(dest.v1 - src.v1)); ] var s1, s2 := -1, -1; if mktuple2(dest.v1, src.v2) <> forbidden_place then s1 := simulate_push3(n - 1, dx, 0, abs(dest.v1 - src.v1), 0, dy, abs(dest.v2 - src.v2)); if mktuple2(src.v1, dest.v2) <> forbidden_place then s2 := simulate_push3(n - 1, 0, dy, abs(dest.v2 - src.v2), dx, 0, abs(dest.v1 - src.v1)); if s1 < s2 and s1 <> -1 or s2 = -1 then return s1; else return s2; ] fn calculate_steps(l : bytes) : int [ var large_keypad := [ mktuple2(1, 3), mktuple2(0, 2), mktuple2(1, 2), mktuple2(2, 2), mktuple2(0, 1), mktuple2(1, 1), mktuple2(2, 1), mktuple2(0, 0), mktuple2(1, 0), mktuple2(2, 0) ]; var cpos := mktuple2(2, 3); var steps := 0; for i := 0 to len(l) do [ var c := l[i]; var dest : tuple2(int, int); if c >= '0', c <= '9' then dest := large_keypad[c - '0']; else if c = 'A' then dest := mktuple2(2, 3); else abort; var s := simulate_movements(n_robot_layers, cpos, dest); steps += s + 1; cpos := dest; ] return steps; ] fn main [ var lines := list_break_to_lines(read_lazy(h[0])); var sum := 0; for l in lines do [ var steps := calculate_steps(l); sum += steps * ston(l[ .. len(l) - 1]); ] write(h[1], ntos(sum) + nl); ]