fn small_keypad_move(pos dx dy : int) : int [ var npos := pos + dx + dy * 3; if npos <= 0 or npos >= 6 then return -1; if dy = 0, pos div 3 <> npos div 3 then return -1; return npos; ] fn large_keypad_move(pos dx dy : int) : int [ var npos := pos + dx + dy * 3; if npos < 0 or npos >= 12 or npos = 9 then return -1; if dy = 0, pos div 3 <> npos div 3 then return -1; return npos; ] fn calculate_steps(l : bytes) : int [ var states := array_fill(-1, [ 12, 6, 6, 4 ]); var queue := [ mktuple4(11, 2, 2, 0 )]; var dist := 0; while len_greater_than(queue, 0) do [ var new_queue := empty(tuple4(int, int, int, int)); for i := 0 to len(queue) do [ var p := queue[i]; if p.v4 = 4 then return dist; if states[p.v1, p.v2, p.v3, p.v4] >= 0 then continue; states[p.v1, p.v2, p.v3, p.v4] := dist; for d in [ [0, 1], [0, -1], [1, 0], [-1, 0] ] do [ var new_pos := small_keypad_move(p.v3, d[0], d[1]); if new_pos >= 0 then [ var np := p; np.v3 := new_pos; new_queue +<= np; ] ] var d := [ [0 div 0, 0 div 0], [0, -1], [0, 0], [-1, 0], [0, 1], [1, 0] ][p.v3]; if d[0] <> 0 or d[1] <> 0 then [ var new_pos := small_keypad_move(p.v2, d[0], d[1]); if new_pos >= 0 then [ var np := p; np.v2 := new_pos; new_queue +<= np; ] ] else [ var d := [ [0 div 0, 0 div 0], [0, -1], [0, 0], [-1, 0], [0, 1], [1, 0] ][p.v2]; if d[0] <> 0 or d[1] <> 0 then [ var new_pos := large_keypad_move(p.v1, d[0], d[1]); if new_pos >= 0 then [ var np := p; np.v1 := new_pos; new_queue +<= np; ] ] else [ var c := "789456123 0A"[p.v1]; if c = l[p.v4] then [ var np := p; np.v4 += 1; new_queue +<= np; ] ] ] ] queue := new_queue; dist += 1; ] abort; ] 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); ]